From aeae2e4203049f09bac4e71dd0716bdf4427057f Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Mon, 13 Dec 2010 17:35:57 -0800 Subject: [PATCH 01/94] 6999460: Glassfish build with JDK 6 / 7 is 5x-10x slower on Windows than on Linux Fixed JavacFileManager to not treat a non-existant pathname as a directory. Reviewed-by: jjg --- .../tools/javac/file/JavacFileManager.java | 309 ++++++++++-------- .../com/sun/tools/javac/file/Paths.java | 21 +- 2 files changed, 186 insertions(+), 144 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java index f57579e9f0d..156b16d104b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -266,82 +266,116 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil System.out.println(message); } + /** - * Insert all files in subdirectory `subdirectory' of `directory' which end - * in one of the extensions in `extensions' into packageSym. + * Insert all files in subdirectory subdirectory of directory directory + * which match fileKinds into resultList */ private void listDirectory(File directory, RelativeDirectory subdirectory, Set fileKinds, boolean recurse, - ListBuffer l) { - Archive archive = archives.get(directory); + ListBuffer resultList) { + File d = subdirectory.getFile(directory); + if (!caseMapCheck(d, subdirectory)) + return; - boolean isFile = fsInfo.isFile(directory); + File[] files = d.listFiles(); + if (files == null) + return; - if (archive != null || isFile) { - if (archive == null) { - try { - archive = openArchive(directory); - } catch (IOException ex) { - log.error("error.reading.file", - directory, getMessage(ex)); - return; + if (sortFiles != null) + Arrays.sort(files, sortFiles); + + for (File f: files) { + String fname = f.getName(); + if (f.isDirectory()) { + if (recurse && SourceVersion.isIdentifier(fname)) { + listDirectory(directory, + new RelativeDirectory(subdirectory, fname), + fileKinds, + recurse, + resultList); } - } - - List files = archive.getFiles(subdirectory); - if (files != null) { - for (String file; !files.isEmpty(); files = files.tail) { - file = files.head; - if (isValidFile(file, fileKinds)) { - l.append(archive.getFileObject(subdirectory, file)); - } - } - } - if (recurse) { - for (RelativeDirectory s: archive.getSubdirectories()) { - if (subdirectory.contains(s)) { - // Because the archive map is a flat list of directories, - // the enclosing loop will pick up all child subdirectories. - // Therefore, there is no need to recurse deeper. - listDirectory(directory, s, fileKinds, false, l); - } - } - } - } else { - File d = subdirectory.getFile(directory); - if (!caseMapCheck(d, subdirectory)) - return; - - File[] files = d.listFiles(); - if (files == null) - return; - - if (sortFiles != null) - Arrays.sort(files, sortFiles); - - for (File f: files) { - String fname = f.getName(); - if (f.isDirectory()) { - if (recurse && SourceVersion.isIdentifier(fname)) { - listDirectory(directory, - new RelativeDirectory(subdirectory, fname), - fileKinds, - recurse, - l); - } - } else { - if (isValidFile(fname, fileKinds)) { - JavaFileObject fe = - new RegularFileObject(this, fname, new File(d, fname)); - l.append(fe); - } + } else { + if (isValidFile(fname, fileKinds)) { + JavaFileObject fe = + new RegularFileObject(this, fname, new File(d, fname)); + resultList.append(fe); } } } } + /** + * Insert all files in subdirectory subdirectory of archive archive + * which match fileKinds into resultList + */ + private void listArchive(Archive archive, + RelativeDirectory subdirectory, + Set fileKinds, + boolean recurse, + ListBuffer resultList) { + // Get the files directly in the subdir + List files = archive.getFiles(subdirectory); + if (files != null) { + for (; !files.isEmpty(); files = files.tail) { + String file = files.head; + if (isValidFile(file, fileKinds)) { + resultList.append(archive.getFileObject(subdirectory, file)); + } + } + } + if (recurse) { + for (RelativeDirectory s: archive.getSubdirectories()) { + if (subdirectory.contains(s)) { + // Because the archive map is a flat list of directories, + // the enclosing loop will pick up all child subdirectories. + // Therefore, there is no need to recurse deeper. + listArchive(archive, s, fileKinds, false, resultList); + } + } + } + } + + /** + * container is a directory, a zip file, or a non-existant path. + * Insert all files in subdirectory subdirectory of container which + * match fileKinds into resultList + */ + private void listContainer(File container, + RelativeDirectory subdirectory, + Set fileKinds, + boolean recurse, + ListBuffer resultList) { + Archive archive = archives.get(container); + if (archive == null) { + // archives are not created for directories. + if (fsInfo.isDirectory(container)) { + listDirectory(container, + subdirectory, + fileKinds, + recurse, + resultList); + return; + } + + // Not a directory; either a file or non-existant, create the archive + try { + archive = openArchive(container); + } catch (IOException ex) { + log.error("error.reading.file", + container, getMessage(ex)); + return; + } + } + listArchive(archive, + subdirectory, + fileKinds, + recurse, + resultList); + } + private boolean isValidFile(String s, Set fileKinds) { JavaFileObject.Kind kind = getKind(s); return fileKinds.contains(kind); @@ -434,95 +468,92 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil private static final RelativeDirectory symbolFilePrefix = new RelativeDirectory("META-INF/sym/rt.jar/"); - /** Open a new zip file directory. + /** Open a new zip file directory, and cache it. */ protected Archive openArchive(File zipFileName) throws IOException { - Archive archive = archives.get(zipFileName); - if (archive == null) { - File origZipFileName = zipFileName; - if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) { - File file = zipFileName.getParentFile().getParentFile(); // ${java.home} - if (new File(file.getName()).equals(new File("jre"))) - file = file.getParentFile(); - // file == ${jdk.home} - for (String name : symbolFileLocation) - file = new File(file, name); - // file == ${jdk.home}/lib/ct.sym - if (file.exists()) - zipFileName = file; + File origZipFileName = zipFileName; + if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) { + File file = zipFileName.getParentFile().getParentFile(); // ${java.home} + if (new File(file.getName()).equals(new File("jre"))) + file = file.getParentFile(); + // file == ${jdk.home} + for (String name : symbolFileLocation) + file = new File(file, name); + // file == ${jdk.home}/lib/ct.sym + if (file.exists()) + zipFileName = file; + } + + Archive archive; + try { + + ZipFile zdir = null; + + boolean usePreindexedCache = false; + String preindexCacheLocation = null; + + if (!useZipFileIndex) { + zdir = new ZipFile(zipFileName); } + else { + usePreindexedCache = options.isSet("usezipindex"); + preindexCacheLocation = options.get("java.io.tmpdir"); + String optCacheLoc = options.get("cachezipindexdir"); - try { - - ZipFile zdir = null; - - boolean usePreindexedCache = false; - String preindexCacheLocation = null; - - if (!useZipFileIndex) { - zdir = new ZipFile(zipFileName); - } - else { - usePreindexedCache = options.isSet("usezipindex"); - preindexCacheLocation = options.get("java.io.tmpdir"); - String optCacheLoc = options.get("cachezipindexdir"); - - if (optCacheLoc != null && optCacheLoc.length() != 0) { - if (optCacheLoc.startsWith("\"")) { - if (optCacheLoc.endsWith("\"")) { - optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1); - } - else { - optCacheLoc = optCacheLoc.substring(1); - } + if (optCacheLoc != null && optCacheLoc.length() != 0) { + if (optCacheLoc.startsWith("\"")) { + if (optCacheLoc.endsWith("\"")) { + optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1); } + else { + optCacheLoc = optCacheLoc.substring(1); + } + } - File cacheDir = new File(optCacheLoc); - if (cacheDir.exists() && cacheDir.canWrite()) { - preindexCacheLocation = optCacheLoc; - if (!preindexCacheLocation.endsWith("/") && - !preindexCacheLocation.endsWith(File.separator)) { - preindexCacheLocation += File.separator; - } + File cacheDir = new File(optCacheLoc); + if (cacheDir.exists() && cacheDir.canWrite()) { + preindexCacheLocation = optCacheLoc; + if (!preindexCacheLocation.endsWith("/") && + !preindexCacheLocation.endsWith(File.separator)) { + preindexCacheLocation += File.separator; } } } + } - if (origZipFileName == zipFileName) { - if (!useZipFileIndex) { - archive = new ZipArchive(this, zdir); - } else { - archive = new ZipFileIndexArchive(this, + if (origZipFileName == zipFileName) { + if (!useZipFileIndex) { + archive = new ZipArchive(this, zdir); + } else { + archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, null, usePreindexedCache, preindexCacheLocation, options.isSet("writezipindexfiles"))); - } + } + } else { + if (!useZipFileIndex) { + archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix); } else { - if (!useZipFileIndex) { - archive = new SymbolArchive(this, origZipFileName, zdir, symbolFilePrefix); - } - else { - archive = new ZipFileIndexArchive(this, + archive = new ZipFileIndexArchive(this, ZipFileIndex.getZipFileIndex(zipFileName, symbolFilePrefix, usePreindexedCache, preindexCacheLocation, options.isSet("writezipindexfiles"))); - } } - } catch (FileNotFoundException ex) { - archive = new MissingArchive(zipFileName); - } catch (IOException ex) { - if (zipFileName.exists()) - log.error("error.reading.file", zipFileName, getMessage(ex)); - archive = new MissingArchive(zipFileName); } - - archives.put(origZipFileName, archive); + } catch (FileNotFoundException ex) { + archive = new MissingArchive(zipFileName); + } catch (IOException ex) { + if (zipFileName.exists()) + log.error("error.reading.file", zipFileName, getMessage(ex)); + archive = new MissingArchive(zipFileName); } + + archives.put(origZipFileName, archive); return archive; } @@ -589,8 +620,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil ListBuffer results = new ListBuffer(); for (File directory : path) - listDirectory(directory, subdirectory, kinds, recurse, results); - + listContainer(directory, subdirectory, kinds, recurse, results); return results.toList(); } @@ -659,19 +689,22 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil return null; for (File dir: path) { - if (dir.isDirectory()) { - File f = name.getFile(dir); - if (f.exists()) - return new RegularFileObject(this, f); - } else { - Archive a = openArchive(dir); - if (a.contains(name)) { - return a.getFileObject(name.dirname(), name.basename()); + Archive a = archives.get(dir); + if (a == null) { + if (fsInfo.isDirectory(dir)) { + File f = name.getFile(dir); + if (f.exists()) + return new RegularFileObject(this, f); + continue; } - + // Not a directory, create the archive + a = openArchive(dir); + } + // Process the archive + if (a.contains(name)) { + return a.getFileObject(name.dirname(), name.basename()); } } - return null; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java index 4f69b27d013..8c5e51c7f0d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java @@ -286,9 +286,8 @@ public class Paths { } public void addFile(File file, boolean warn) { - File canonFile = fsInfo.getCanonicalFile(file); - if (contains(file) || canonicalValues.contains(canonFile)) { - /* Discard duplicates and avoid infinite recursion */ + if (contains(file)) { + // discard duplicates return; } @@ -298,7 +297,17 @@ public class Paths { log.warning(Lint.LintCategory.PATH, "path.element.not.found", file); } - } else if (fsInfo.isFile(file)) { + super.add(file); + return; + } + + File canonFile = fsInfo.getCanonicalFile(file); + if (canonicalValues.contains(canonFile)) { + /* Discard duplicates and avoid infinite recursion */ + return; + } + + if (fsInfo.isFile(file)) { /* File is an ordinary file. */ if (!isArchive(file)) { /* Not a recognized extension; open it to see if @@ -322,11 +331,11 @@ public class Paths { } /* Now what we have left is either a directory or a file name - confirming to archive naming convention */ + conforming to archive naming convention */ super.add(file); canonicalValues.add(canonFile); - if (expandJarClassPaths && fsInfo.exists(file) && fsInfo.isFile(file)) + if (expandJarClassPaths && fsInfo.isFile(file)) addJarClassPath(file, warn); } From 0e6307f4b79b2b67a25a0f6be879c86140d31eb4 Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Tue, 14 Dec 2010 13:51:07 +0000 Subject: [PATCH 02/94] 6444769: java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.html fails Remove unneeded test Reviewed-by: anthony --- .../WindowWithWarningTest.html | 20 -- .../WindowWithWarningTest.java | 315 ------------------ 2 files changed, 335 deletions(-) delete mode 100644 jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.html delete mode 100644 jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.java diff --git a/jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.html b/jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.html deleted file mode 100644 index ad6fa609d4f..00000000000 --- a/jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - WindowWithWarningTest - -
-  This test will run automatically.
-  
- - - - - diff --git a/jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.java b/jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.java deleted file mode 100644 index ab9ea6950a6..00000000000 --- a/jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - test - @bug 6391770 - @summary Content of the Window should be laid out in the area left after WarningWindow was added. - @author yuri nesterenko: area= - @run applet WindowWithWarningTest.html -*/ - -// Note there is no @ in front of test above. This is so that the -// harness will not mistake this file as a test file. It should -// only see the html file as a test file. (the harness runs all -// valid test files, so it would run this test twice if this file -// were valid as well as the html file.) -// Also, note the area= after Your Name in the author tag. Here, you -// should put which functional area the test falls in. See the -// AWT-core home page -> test areas and/or -> AWT team for a list of -// areas. -// Note also the 'AutomaticAppletTest.html' in the run tag. This should -// be changed to the name of the test. - - -/** - * WindowWithWarningTest.java - * - * summary: - */ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -//Automated tests should run as applet tests if possible because they -// get their environments cleaned up, including AWT threads, any -// test created threads, and any system resources used by the test -// such as file descriptors. (This is normally not a problem as -// main tests usually run in a separate VM, however on some platforms -// such as the Mac, separate VMs are not possible and non-applet -// tests will cause problems). Also, you don't have to worry about -// synchronisation stuff in Applet tests they way you do in main -// tests... - - -public class WindowWithWarningTest extends Applet -{ - //Declare things used in the test, like buttons and labels here - boolean buttonClicked = false; - public static final int MAX_COUNT = 100; - - public void init() - { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - - this.setLayout (new BorderLayout ()); - - String[] instructions = - { - "This is an AUTOMATIC test", - "simply wait until it is done" - }; - //Sysout.createDialog( ); - //Sysout.printInstructions( instructions ); - - }//End init() - public void start () - { - //Get things going. Request focus, set size, et cetera - System.setSecurityManager( new SecurityManager() { - // deny AWTPermission("showWindowWithoutWarningBanner") - public boolean checkTopLevelWindow(Object window) { - return false; - } - }); - JFrame frame = new JFrame("Window Test"); - frame.setBounds(50, 50, 200, 200); - frame.show(); - - JWindow window = new JWindow( frame ); - JButton jbutton1 = new JButton( "First" ); - jbutton1.addMouseListener( new MouseAdapter() { - public void mousePressed( MouseEvent me ) { - buttonClicked = true; - } - }); - JButton jbutton2 = new JButton( "Second" ); - window.setLocation( 300, 300 ); - - window.add("North", jbutton1); - window.add("South", jbutton2); - - window.pack(); - window.show(); - //wait for frame to show: - getLocation( frame ); - window.toFront(); - - Dimension size0 = window.getSize(); - Dimension size1 = null; - try { - Robot robot = new Robot(); - - robot.delay(500); - window.pack(); - robot.delay(500); - window.pack(); - // size1 must be the same as size0 - size1 = window.getSize(); - robot.delay(500); - Point pt = jbutton1.getLocationOnScreen(); - robot.mouseMove((int) jbutton1.getLocationOnScreen().x + jbutton1.getWidth() / 2, - (int) jbutton1.getLocationOnScreen().y + jbutton1.getHeight() / 2); - robot.delay(500); - robot.mousePress(MouseEvent.BUTTON1_MASK); - robot.delay(100); - robot.mouseRelease(MouseEvent.BUTTON1_MASK); - robot.delay(2000); - }catch(Exception e) { - throw new RuntimeException( "Exception "+e ); - } - if( !size0.equals(size1) ) { - throw new RuntimeException( "Wrong Window size after multiple pack()s"); - } - if( !buttonClicked ) { - throw new RuntimeException( "Button was not clicked"); - } - window.dispose(); - frame.dispose(); - - System.out.println("Test Passed."); - }// start() - public static Point getLocation( Component co ) throws RuntimeException { - Point pt = null; - boolean bFound = false; - int count = 0; - while( !bFound ) { - try { - pt = co.getLocationOnScreen(); - bFound = true; - }catch( Exception ex ) { - bFound = false; - count++; - } - if( !bFound && count > MAX_COUNT ) { - throw new RuntimeException("don't see a component to get location"); - } - } - return pt; - } - - -}// class AutomaticAppletTest - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - show(); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class From 0563626b3c698103bf2a37d901cddb597c06a3a9 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 14 Dec 2010 12:44:30 -0800 Subject: [PATCH 03/94] 7006044: materialize cheap non-oop pointers on 64-bit SPARC After 6961690 we load non-oop pointers for the constant table which could easily be materialized in a few instructions. Reviewed-by: never, kvn --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 65 +++++++++++++------- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 13 ++-- hotspot/src/cpu/sparc/vm/sparc.ad | 43 ++++++++++--- 3 files changed, 82 insertions(+), 39 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 8512afcba95..7b3d82db3b7 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "asm/assembler.hpp" #include "assembler_sparc.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" @@ -1327,37 +1328,38 @@ void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d) } -int MacroAssembler::size_of_sethi(address a, bool worst_case) { +int MacroAssembler::insts_for_sethi(address a, bool worst_case) { #ifdef _LP64 - if (worst_case) return 7; - intptr_t iaddr = (intptr_t)a; - int hi32 = (int)(iaddr >> 32); - int lo32 = (int)(iaddr); - int inst_count; - if (hi32 == 0 && lo32 >= 0) - inst_count = 1; - else if (hi32 == -1) - inst_count = 2; + if (worst_case) return 7; + intptr_t iaddr = (intptr_t) a; + int msb32 = (int) (iaddr >> 32); + int lsb32 = (int) (iaddr); + int count; + if (msb32 == 0 && lsb32 >= 0) + count = 1; + else if (msb32 == -1) + count = 2; else { - inst_count = 2; - if ( hi32 & 0x3ff ) - inst_count++; - if ( lo32 & 0xFFFFFC00 ) { - if( (lo32 >> 20) & 0xfff ) inst_count += 2; - if( (lo32 >> 10) & 0x3ff ) inst_count += 2; + count = 2; + if (msb32 & 0x3ff) + count++; + if (lsb32 & 0xFFFFFC00 ) { + if ((lsb32 >> 20) & 0xfff) count += 2; + if ((lsb32 >> 10) & 0x3ff) count += 2; } } - return BytesPerInstWord * inst_count; + return count; #else - return BytesPerInstWord; + return 1; #endif } -int MacroAssembler::worst_case_size_of_set() { - return size_of_sethi(NULL, true) + 1; +int MacroAssembler::worst_case_insts_for_set() { + return insts_for_sethi(NULL, true) + 1; } +// Keep in sync with MacroAssembler::insts_for_internal_set void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { intptr_t value = addrlit.value(); @@ -1379,6 +1381,23 @@ void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, boo } } +// Keep in sync with MacroAssembler::internal_set +int MacroAssembler::insts_for_internal_set(intptr_t value) { + // can optimize + if (-4096 <= value && value <= 4095) { + return 1; + } + if (inv_hi22(hi22(value)) == value) { + return insts_for_sethi((address) value); + } + int count = insts_for_sethi((address) value); + AddressLiteral al(value); + if (al.low10() != 0) { + count++; + } + return count; +} + void MacroAssembler::set(const AddressLiteral& al, Register d) { internal_set(al, d, false); } @@ -1443,11 +1462,11 @@ void MacroAssembler::set64(jlong value, Register d, Register tmp) { } } -int MacroAssembler::size_of_set64(jlong value) { +int MacroAssembler::insts_for_set64(jlong value) { v9_dep(); - int hi = (int)(value >> 32); - int lo = (int)(value & ~0); + int hi = (int) (value >> 32); + int lo = (int) (value & ~0); int count = 0; // (Matcher::isSimpleConstant64 knows about the following optimizations.) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index ae4357edd76..253193868f2 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1884,23 +1884,24 @@ public: void sethi(const AddressLiteral& addrlit, Register d); void patchable_sethi(const AddressLiteral& addrlit, Register d); - // compute the size of a sethi/set - static int size_of_sethi( address a, bool worst_case = false ); - static int worst_case_size_of_set(); + // compute the number of instructions for a sethi/set + static int insts_for_sethi( address a, bool worst_case = false ); + static int worst_case_insts_for_set(); // set may be either setsw or setuw (high 32 bits may be zero or sign) private: void internal_set(const AddressLiteral& al, Register d, bool ForceRelocatable); + static int insts_for_internal_set(intptr_t value); public: void set(const AddressLiteral& addrlit, Register d); void set(intptr_t value, Register d); void set(address addr, Register d, RelocationHolder const& rspec); + static int insts_for_set(intptr_t value) { return insts_for_internal_set(value); } + void patchable_set(const AddressLiteral& addrlit, Register d); void patchable_set(intptr_t value, Register d); void set64(jlong value, Register d, Register tmp); - - // Compute size of set64. - static int size_of_set64(jlong value); + static int insts_for_set64(jlong value); // sign-extend 32 to 64 inline void signx( Register s, Register d ) { sra( s, G0, d); } diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 018fe70b9ec..1909d010b08 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1086,9 +1086,9 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { uint MachConstantBaseNode::size(PhaseRegAlloc*) const { if (UseRDPCForConstantTableBase) { // This is really the worst case but generally it's only 1 instruction. - return 4 /*rdpc*/ + 4 /*sub*/ + MacroAssembler::worst_case_size_of_set(); + return (1 /*rdpc*/ + 1 /*sub*/ + MacroAssembler::worst_case_insts_for_set()) * BytesPerInstWord; } else { - return MacroAssembler::worst_case_size_of_set(); + return MacroAssembler::worst_case_insts_for_set() * BytesPerInstWord; } } @@ -1240,7 +1240,7 @@ const Pipeline * MachEpilogNode::pipeline() const { int MachEpilogNode::safepoint_offset() const { assert( do_polling(), "no return for this epilog node"); - return MacroAssembler::size_of_sethi(os::get_polling_page()); + return MacroAssembler::insts_for_sethi(os::get_polling_page()) * BytesPerInstWord; } //============================================================================= @@ -3553,7 +3553,8 @@ operand immP() %{ interface(CONST_INTER); %} -// Pointer Immediate: 32 or 64-bit +#ifdef _LP64 +// Pointer Immediate: 64-bit operand immP_set() %{ predicate(!VM_Version::is_niagara1_plus()); match(ConP); @@ -3564,10 +3565,10 @@ operand immP_set() %{ interface(CONST_INTER); %} -// Pointer Immediate: 32 or 64-bit +// Pointer Immediate: 64-bit // From Niagara2 processors on a load should be better than materializing. operand immP_load() %{ - predicate(VM_Version::is_niagara1_plus()); + predicate(VM_Version::is_niagara1_plus() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3))); match(ConP); op_cost(5); @@ -3576,6 +3577,18 @@ operand immP_load() %{ interface(CONST_INTER); %} +// Pointer Immediate: 64-bit +operand immP_no_oop_cheap() %{ + predicate(VM_Version::is_niagara1_plus() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3)); + match(ConP); + + op_cost(5); + // formats are generated automatically for constants and base registers + format %{ %} + interface(CONST_INTER); +%} +#endif + operand immP13() %{ predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095)); match(ConP); @@ -3673,7 +3686,7 @@ operand immL_32bits() %{ // Long Immediate: cheap (materialize in <= 3 instructions) operand immL_cheap() %{ - predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::size_of_set64(n->get_long()) <= 3); + predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::insts_for_set64(n->get_long()) <= 3); match(ConL); op_cost(0); @@ -3683,7 +3696,7 @@ operand immL_cheap() %{ // Long Immediate: expensive (materialize in > 3 instructions) operand immL_expensive() %{ - predicate(VM_Version::is_niagara1_plus() && MacroAssembler::size_of_set64(n->get_long()) > 3); + predicate(VM_Version::is_niagara1_plus() && MacroAssembler::insts_for_set64(n->get_long()) > 3); match(ConL); op_cost(0); @@ -6094,8 +6107,18 @@ instruct loadConP_load(iRegP dst, immP_load con) %{ ins_cost(MEMORY_REF_COST); format %{ "LD [$constanttablebase + $constantoffset],$dst\t! load from constant table: ptr=$con" %} ins_encode %{ - RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register); - __ ld_ptr($constanttablebase, con_offset, $dst$$Register); + RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register); + __ ld_ptr($constanttablebase, con_offset, $dst$$Register); + %} + ins_pipe(loadConP); +%} + +instruct loadConP_no_oop_cheap(iRegP dst, immP_no_oop_cheap con) %{ + match(Set dst con); + ins_cost(DEFAULT_COST * 3/2); + format %{ "SET $con,$dst\t! non-oop ptr" %} + ins_encode %{ + __ set($con$$constant, $dst$$Register); %} ins_pipe(loadConP); %} From 80cb99bacb349e62be063a60d540c0718400c4b6 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Tue, 14 Dec 2010 13:25:29 -0800 Subject: [PATCH 04/94] 6766342: Improve performance of Ductus rasterizer Reviewed-by: jgodinez, prr --- jdk/make/sun/awt/make.depend | 6 +- jdk/make/sun/awt/mapfile-vers | 2 + jdk/make/sun/awt/mapfile-vers-linux | 2 + .../classes/sun/dc/DuctusRenderingEngine.java | 82 + .../share/classes/sun/java2d/SurfaceData.java | 87 +- .../sun/java2d/loops/CompositeType.java | 39 +- .../classes/sun/java2d/loops/MaskFill.java | 66 + .../classes/sun/java2d/pipe/AAShapePipe.java | 68 +- .../sun/java2d/pipe/AlphaColorPipe.java | 21 +- .../sun/java2d/pipe/RenderingEngine.java | 85 + .../java2d/pisces/PiscesRenderingEngine.java | 63 + .../sun/java2d/loops/DrawParallelogram.c | 47 +- .../sun/java2d/loops/FillParallelogram.c | 42 +- .../share/native/sun/java2d/loops/MaskFill.c | 965 ++++++++++ .../sun/java2d/loops/ParallelogramUtils.h | 83 + .../sun/java2d/loops/vis_IntArgbPre_Mask.c | 12 +- .../native/sun/java2d/loops/vis_SrcMaskFill.c | 30 +- .../Graphics2D/RenderClipTest/6766342.tests | 3 + .../RenderClipTest/RenderClipTest.java | 1634 +++++++++++++++++ 19 files changed, 3204 insertions(+), 133 deletions(-) create mode 100644 jdk/src/share/native/sun/java2d/loops/ParallelogramUtils.h create mode 100644 jdk/test/java/awt/Graphics2D/RenderClipTest/6766342.tests create mode 100644 jdk/test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java diff --git a/jdk/make/sun/awt/make.depend b/jdk/make/sun/awt/make.depend index 6a6186585c6..02b3b1672d1 100644 --- a/jdk/make/sun/awt/make.depend +++ b/jdk/make/sun/awt/make.depend @@ -224,7 +224,7 @@ $(OBJDIR)/DllUtil.obj:: ../../../src/windows/native/sun/windows/DllUtil.h $(OBJDIR)/DrawLine.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawLine.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/DrawParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawParallelogram.h $(CLASSHDRDIR)/sun_java2d_loops_FillParallelogram.h ../../../src/share/javavm/export/classfile_constants.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacros.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h +$(OBJDIR)/DrawParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawParallelogram.h ../../../src/share/javavm/export/classfile_constants.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/ParallelogramUtils.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h $(OBJDIR)/DrawPath.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawPath.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/DrawPath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/ProcessPath.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -232,7 +232,7 @@ $(OBJDIR)/DrawPolygons.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDR $(OBJDIR)/DrawRect.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_DrawRect.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/FillParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_FillParallelogram.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h +$(OBJDIR)/FillParallelogram.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_FillParallelogram.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/ParallelogramUtils.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h $(OBJDIR)/FillPath.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_FillPath.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/DrawPath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/ProcessPath.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -284,7 +284,7 @@ $(OBJDIR)/IntRgbx.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/sh $(OBJDIR)/MaskBlit.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_MaskBlit.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/awt/utility/rect.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/MaskFill.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_MaskFill.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h +$(OBJDIR)/MaskFill.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_MaskFill.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/ParallelogramUtils.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h $(OBJDIR)/MouseInfo.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/classfile_constants.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h diff --git a/jdk/make/sun/awt/mapfile-vers b/jdk/make/sun/awt/mapfile-vers index 07e7c06f586..91ddcc2c52c 100644 --- a/jdk/make/sun/awt/mapfile-vers +++ b/jdk/make/sun/awt/mapfile-vers @@ -118,6 +118,8 @@ SUNWprivate_1.1 { Java_sun_java2d_loops_GraphicsPrimitiveMgr_registerNativeLoops; Java_sun_java2d_loops_MaskBlit_MaskBlit; Java_sun_java2d_loops_MaskFill_MaskFill; + Java_sun_java2d_loops_MaskFill_FillAAPgram; + Java_sun_java2d_loops_MaskFill_DrawAAPgram; Java_sun_java2d_loops_TransformHelper_Transform; Java_sun_java2d_pipe_Region_initIDs; Java_sun_java2d_pipe_SpanClipRenderer_initIDs; diff --git a/jdk/make/sun/awt/mapfile-vers-linux b/jdk/make/sun/awt/mapfile-vers-linux index 5eab78a913d..1af4fc0363b 100644 --- a/jdk/make/sun/awt/mapfile-vers-linux +++ b/jdk/make/sun/awt/mapfile-vers-linux @@ -115,6 +115,8 @@ SUNWprivate_1.1 { Java_sun_java2d_loops_GraphicsPrimitiveMgr_registerNativeLoops; Java_sun_java2d_loops_MaskBlit_MaskBlit; Java_sun_java2d_loops_MaskFill_MaskFill; + Java_sun_java2d_loops_MaskFill_FillAAPgram; + Java_sun_java2d_loops_MaskFill_DrawAAPgram; Java_sun_java2d_pipe_BufferedRenderPipe_fillSpans; Java_sun_java2d_pipe_SpanClipRenderer_initIDs; sun_awt_image_GifImageDecoder_initIDs; diff --git a/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java b/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java index 61f9b3923a8..b39c4686d6c 100644 --- a/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java +++ b/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java @@ -635,6 +635,88 @@ public class DuctusRenderingEngine extends RenderingEngine { return r; } + /** + * {@inheritDoc} + */ + @Override + public AATileGenerator getAATileGenerator(double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2, + Region clip, + int bbox[]) + { + // REMIND: Deal with large coordinates! + double ldx1, ldy1, ldx2, ldy2; + boolean innerpgram = (lw1 > 0 && lw2 > 0); + + if (innerpgram) { + ldx1 = dx1 * lw1; + ldy1 = dy1 * lw1; + ldx2 = dx2 * lw2; + ldy2 = dy2 * lw2; + x -= (ldx1 + ldx2) / 2.0; + y -= (ldy1 + ldy2) / 2.0; + dx1 += ldx1; + dy1 += ldy1; + dx2 += ldx2; + dy2 += ldy2; + if (lw1 > 1 && lw2 > 1) { + // Inner parallelogram was entirely consumed by stroke... + innerpgram = false; + } + } else { + ldx1 = ldy1 = ldx2 = ldy2 = 0; + } + + Rasterizer r = getRasterizer(); + + r.setUsage(Rasterizer.EOFILL); + + r.beginPath(); + r.beginSubpath((float) x, (float) y); + r.appendLine((float) (x+dx1), (float) (y+dy1)); + r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2)); + r.appendLine((float) (x+dx2), (float) (y+dy2)); + r.closedSubpath(); + if (innerpgram) { + x += ldx1 + ldx2; + y += ldy1 + ldy2; + dx1 -= 2.0 * ldx1; + dy1 -= 2.0 * ldy1; + dx2 -= 2.0 * ldx2; + dy2 -= 2.0 * ldy2; + r.beginSubpath((float) x, (float) y); + r.appendLine((float) (x+dx1), (float) (y+dy1)); + r.appendLine((float) (x+dx1+dx2), (float) (y+dy1+dy2)); + r.appendLine((float) (x+dx2), (float) (y+dy2)); + r.closedSubpath(); + } + + try { + r.endPath(); + r.getAlphaBox(bbox); + clip.clipBoxToBounds(bbox); + if (bbox[0] >= bbox[2] || bbox[1] >= bbox[3]) { + dropRasterizer(r); + return null; + } + r.setOutputArea(bbox[0], bbox[1], + bbox[2] - bbox[0], + bbox[3] - bbox[1]); + } catch (PRException e) { + /* + * This exeption is thrown from the native part of the Ductus + * (only in case of a debug build) to indicate that some + * segments of the path have very large coordinates. + * See 4485298 for more info. + */ + System.err.println("DuctusRenderingEngine.getAATileGenerator: "+e); + } + + return r; + } + private void feedConsumer(PathConsumer consumer, PathIterator pi) { try { consumer.beginPath(); diff --git a/jdk/src/share/classes/sun/java2d/SurfaceData.java b/jdk/src/share/classes/sun/java2d/SurfaceData.java index 08b3fcc914a..827a2e78517 100644 --- a/jdk/src/share/classes/sun/java2d/SurfaceData.java +++ b/jdk/src/share/classes/sun/java2d/SurfaceData.java @@ -367,16 +367,17 @@ public abstract class SurfaceData public static final TextPipe aaTextRenderer; public static final TextPipe lcdTextRenderer; - protected static final CompositePipe colorPipe; + protected static final AlphaColorPipe colorPipe; protected static final PixelToShapeConverter colorViaShape; protected static final PixelToParallelogramConverter colorViaPgram; protected static final TextPipe colorText; protected static final CompositePipe clipColorPipe; protected static final TextPipe clipColorText; protected static final AAShapePipe AAColorShape; - protected static final PixelToShapeConverter AAColorViaShape; + protected static final PixelToParallelogramConverter AAColorViaShape; + protected static final PixelToParallelogramConverter AAColorViaPgram; protected static final AAShapePipe AAClipColorShape; - protected static final PixelToShapeConverter AAClipColorViaShape; + protected static final PixelToParallelogramConverter AAClipColorViaShape; protected static final CompositePipe paintPipe; protected static final SpanShapeRenderer paintShape; @@ -385,9 +386,9 @@ public abstract class SurfaceData protected static final CompositePipe clipPaintPipe; protected static final TextPipe clipPaintText; protected static final AAShapePipe AAPaintShape; - protected static final PixelToShapeConverter AAPaintViaShape; + protected static final PixelToParallelogramConverter AAPaintViaShape; protected static final AAShapePipe AAClipPaintShape; - protected static final PixelToShapeConverter AAClipPaintViaShape; + protected static final PixelToParallelogramConverter AAClipPaintViaShape; protected static final CompositePipe compPipe; protected static final SpanShapeRenderer compShape; @@ -396,9 +397,9 @@ public abstract class SurfaceData protected static final CompositePipe clipCompPipe; protected static final TextPipe clipCompText; protected static final AAShapePipe AACompShape; - protected static final PixelToShapeConverter AACompViaShape; + protected static final PixelToParallelogramConverter AACompViaShape; protected static final AAShapePipe AAClipCompShape; - protected static final PixelToShapeConverter AAClipCompViaShape; + protected static final PixelToParallelogramConverter AAClipCompViaShape; protected static final DrawImagePipe imagepipe; @@ -427,6 +428,22 @@ public abstract class SurfaceData } } + private static PixelToParallelogramConverter + makeConverter(AAShapePipe renderer, + ParallelogramPipe pgrampipe) + { + return new PixelToParallelogramConverter(renderer, + pgrampipe, + 1.0/8.0, 0.499, + false); + } + + private static PixelToParallelogramConverter + makeConverter(AAShapePipe renderer) + { + return makeConverter(renderer, renderer); + } + static { colorPrimitives = new LoopPipe(); @@ -445,9 +462,10 @@ public abstract class SurfaceData clipColorPipe = new SpanClipRenderer(colorPipe); clipColorText = new TextRenderer(clipColorPipe); AAColorShape = new AAShapePipe(colorPipe); - AAColorViaShape = new PixelToShapeConverter(AAColorShape); + AAColorViaShape = makeConverter(AAColorShape); + AAColorViaPgram = makeConverter(AAColorShape, colorPipe); AAClipColorShape = new AAShapePipe(clipColorPipe); - AAClipColorViaShape = new PixelToShapeConverter(AAClipColorShape); + AAClipColorViaShape = makeConverter(AAClipColorShape); paintPipe = new AlphaPaintPipe(); paintShape = new SpanShapeRenderer.Composite(paintPipe); @@ -456,9 +474,9 @@ public abstract class SurfaceData clipPaintPipe = new SpanClipRenderer(paintPipe); clipPaintText = new TextRenderer(clipPaintPipe); AAPaintShape = new AAShapePipe(paintPipe); - AAPaintViaShape = new PixelToShapeConverter(AAPaintShape); + AAPaintViaShape = makeConverter(AAPaintShape); AAClipPaintShape = new AAShapePipe(clipPaintPipe); - AAClipPaintViaShape = new PixelToShapeConverter(AAClipPaintShape); + AAClipPaintViaShape = makeConverter(AAClipPaintShape); compPipe = new GeneralCompositePipe(); compShape = new SpanShapeRenderer.Composite(compPipe); @@ -467,9 +485,9 @@ public abstract class SurfaceData clipCompPipe = new SpanClipRenderer(compPipe); clipCompText = new TextRenderer(clipCompPipe); AACompShape = new AAShapePipe(compPipe); - AACompViaShape = new PixelToShapeConverter(AACompShape); + AACompViaShape = makeConverter(AACompShape); AAClipCompShape = new AAShapePipe(clipCompPipe); - AAClipCompViaShape = new PixelToShapeConverter(AAClipCompShape); + AAClipCompViaShape = makeConverter(AAClipCompShape); imagepipe = new DrawImage(); } @@ -591,12 +609,12 @@ public abstract class SurfaceData if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipCompViaShape; sg2d.fillpipe = AAClipCompViaShape; - sg2d.shapepipe = AAClipCompShape; + sg2d.shapepipe = AAClipCompViaShape; sg2d.textpipe = clipCompText; } else { sg2d.drawpipe = AACompViaShape; sg2d.fillpipe = AACompViaShape; - sg2d.shapepipe = AACompShape; + sg2d.shapepipe = AACompViaShape; sg2d.textpipe = compText; } } else { @@ -616,12 +634,16 @@ public abstract class SurfaceData if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipColorViaShape; sg2d.fillpipe = AAClipColorViaShape; - sg2d.shapepipe = AAClipColorShape; + sg2d.shapepipe = AAClipColorViaShape; sg2d.textpipe = clipColorText; } else { - sg2d.drawpipe = AAColorViaShape; - sg2d.fillpipe = AAColorViaShape; - sg2d.shapepipe = AAColorShape; + PixelToParallelogramConverter converter = + (sg2d.alphafill.canDoParallelograms() + ? AAColorViaPgram + : AAColorViaShape); + sg2d.drawpipe = converter; + sg2d.fillpipe = converter; + sg2d.shapepipe = converter; if (sg2d.paintState > sg2d.PAINT_OPAQUECOLOR || sg2d.compositeState > sg2d.COMP_ISCOPY) { @@ -634,12 +656,12 @@ public abstract class SurfaceData if (sg2d.clipState == sg2d.CLIP_SHAPE) { sg2d.drawpipe = AAClipPaintViaShape; sg2d.fillpipe = AAClipPaintViaShape; - sg2d.shapepipe = AAClipPaintShape; + sg2d.shapepipe = AAClipPaintViaShape; sg2d.textpipe = clipPaintText; } else { sg2d.drawpipe = AAPaintViaShape; sg2d.fillpipe = AAPaintViaShape; - sg2d.shapepipe = AAPaintShape; + sg2d.shapepipe = AAPaintViaShape; sg2d.textpipe = paintText; } } @@ -793,6 +815,18 @@ public abstract class SurfaceData } } + private static CompositeType getFillCompositeType(SunGraphics2D sg2d) { + CompositeType compType = sg2d.imageComp; + if (sg2d.compositeState == sg2d.COMP_ISCOPY) { + if (compType == CompositeType.SrcOverNoEa) { + compType = CompositeType.OpaqueSrcOverNoEa; + } else { + compType = CompositeType.SrcNoEa; + } + } + return compType; + } + /** * Returns a MaskFill object that can be used on this destination * with the source (paint) and composite types determined by the given @@ -802,9 +836,10 @@ public abstract class SurfaceData * surface) before returning a specific MaskFill object. */ protected MaskFill getMaskFill(SunGraphics2D sg2d) { - return MaskFill.getFromCache(getPaintSurfaceType(sg2d), - sg2d.imageComp, - getSurfaceType()); + SurfaceType src = getPaintSurfaceType(sg2d); + CompositeType comp = getFillCompositeType(sg2d); + SurfaceType dst = getSurfaceType(); + return MaskFill.getFromCache(src, comp, dst); } private static RenderCache loopcache = new RenderCache(30); @@ -816,9 +851,7 @@ public abstract class SurfaceData */ public RenderLoops getRenderLoops(SunGraphics2D sg2d) { SurfaceType src = getPaintSurfaceType(sg2d); - CompositeType comp = (sg2d.compositeState == sg2d.COMP_ISCOPY - ? CompositeType.SrcNoEa - : sg2d.imageComp); + CompositeType comp = getFillCompositeType(sg2d); SurfaceType dst = sg2d.getSurfaceData().getSurfaceType(); Object o = loopcache.get(src, comp, dst); diff --git a/jdk/src/share/classes/sun/java2d/loops/CompositeType.java b/jdk/src/share/classes/sun/java2d/loops/CompositeType.java index 7c47cb3cae8..ec6d6d8064c 100644 --- a/jdk/src/share/classes/sun/java2d/loops/CompositeType.java +++ b/jdk/src/share/classes/sun/java2d/loops/CompositeType.java @@ -27,6 +27,7 @@ package sun.java2d.loops; import java.awt.image.BufferedImage; import java.awt.AlphaComposite; +import java.util.HashMap; /** * A CompositeType object provides a chained description of a type of @@ -51,6 +52,11 @@ import java.awt.AlphaComposite; * the indicated algorithm if all of the more specific searches fail. */ public final class CompositeType { + + private static int unusedUID = 1; + private static final HashMap compositeUIDMap = + new HashMap(100); + /* * CONSTANTS USED BY ALL PRIMITIVES TO DESCRIBE THE COMPOSITING * ALGORITHMS THEY CAN PERFORM @@ -152,6 +158,22 @@ public final class CompositeType { public static final CompositeType SrcOverNoEa = SrcOver.deriveSubType(DESC_SRC_OVER_NO_EA); + /* + * A special CompositeType for the case where we are filling in + * SrcOverNoEa mode with an opaque color. In that case then the + * best loop for us to use would be a SrcNoEa loop, but what if + * there is no such loop? In that case then we would end up + * backing off to a Src loop (which should still be fine) or an + * AnyAlpha loop which would be slower than a SrcOver loop in + * most cases. + * The fix is to use the following chain which looks for loops + * in the following order: + * SrcNoEa, Src, SrcOverNoEa, SrcOver, AnyAlpha + */ + public static final CompositeType + OpaqueSrcOverNoEa = SrcOverNoEa.deriveSubType(DESC_SRC) + .deriveSubType(DESC_SRC_NO_EA); + /* * END OF CompositeType OBJECTS FOR THE VARIOUS CONSTANTS */ @@ -210,7 +232,6 @@ public final class CompositeType { } } - private static int unusedUID = 1; private int uniqueID; private String desc; private CompositeType next; @@ -218,14 +239,20 @@ public final class CompositeType { private CompositeType(CompositeType parent, String desc) { next = parent; this.desc = desc; - this.uniqueID = makeUniqueID(); + this.uniqueID = makeUniqueID(desc); } - private synchronized static final int makeUniqueID() { - if (unusedUID > 255) { - throw new InternalError("composite type id overflow"); + public synchronized static final int makeUniqueID(String desc) { + Integer i = compositeUIDMap.get(desc); + + if (i == null) { + if (unusedUID > 255) { + throw new InternalError("composite type id overflow"); + } + i = unusedUID++; + compositeUIDMap.put(desc, i); } - return unusedUID++; + return i; } public int getUniqueID() { diff --git a/jdk/src/share/classes/sun/java2d/loops/MaskFill.java b/jdk/src/share/classes/sun/java2d/loops/MaskFill.java index f3807ffd8bd..557da13c848 100644 --- a/jdk/src/share/classes/sun/java2d/loops/MaskFill.java +++ b/jdk/src/share/classes/sun/java2d/loops/MaskFill.java @@ -50,6 +50,10 @@ import sun.java2d.SurfaceData; public class MaskFill extends GraphicsPrimitive { public static final String methodSignature = "MaskFill(...)".toString(); + public static final String fillPgramSignature = + "FillAAPgram(...)".toString(); + public static final String drawPgramSignature = + "DrawAAPgram(...)".toString(); public static final int primTypeID = makePrimTypeID(); @@ -92,6 +96,14 @@ public class MaskFill extends GraphicsPrimitive return fill; } + protected MaskFill(String alternateSignature, + SurfaceType srctype, + CompositeType comptype, + SurfaceType dsttype) + { + super(alternateSignature, primTypeID, srctype, comptype, dsttype); + } + protected MaskFill(SurfaceType srctype, CompositeType comptype, SurfaceType dsttype) @@ -115,6 +127,23 @@ public class MaskFill extends GraphicsPrimitive int x, int y, int w, int h, byte[] mask, int maskoff, int maskscan); + public native void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData, + Composite comp, + double x, double y, + double dx1, double dy1, + double dx2, double dy2); + + public native void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData, + Composite comp, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2); + + public boolean canDoParallelograms() { + return (getNativePrim() != 0); + } + static { GraphicsPrimitiveMgr.registerGeneral(new MaskFill(null, null, null)); } @@ -182,12 +211,22 @@ public class MaskFill extends GraphicsPrimitive private static class TraceMaskFill extends MaskFill { MaskFill target; + MaskFill fillPgramTarget; + MaskFill drawPgramTarget; public TraceMaskFill(MaskFill target) { super(target.getSourceType(), target.getCompositeType(), target.getDestType()); this.target = target; + this.fillPgramTarget = new MaskFill(fillPgramSignature, + target.getSourceType(), + target.getCompositeType(), + target.getDestType()); + this.drawPgramTarget = new MaskFill(drawPgramSignature, + target.getSourceType(), + target.getCompositeType(), + target.getDestType()); } public GraphicsPrimitive traceWrap() { @@ -203,5 +242,32 @@ public class MaskFill extends GraphicsPrimitive target.MaskFill(sg2d, sData, comp, x, y, w, h, mask, maskoff, maskscan); } + + public void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData, + Composite comp, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + tracePrimitive(fillPgramTarget); + target.FillAAPgram(sg2d, sData, comp, + x, y, dx1, dy1, dx2, dy2); + } + + public void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData, + Composite comp, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2) + { + tracePrimitive(drawPgramTarget); + target.DrawAAPgram(sg2d, sData, comp, + x, y, dx1, dy1, dx2, dy2, lw1, lw2); + } + + public boolean canDoParallelograms() { + return target.canDoParallelograms(); + } } } diff --git a/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java b/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java index 9edff382b0f..8654bede25c 100644 --- a/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java +++ b/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java @@ -28,6 +28,7 @@ package sun.java2d.pipe; import java.awt.BasicStroke; import java.awt.Rectangle; import java.awt.Shape; +import java.awt.geom.Rectangle2D; import java.awt.geom.PathIterator; import sun.awt.SunHints; import sun.java2d.SunGraphics2D; @@ -39,7 +40,9 @@ import sun.java2d.SunGraphics2D; * This class sets up the Generator and computes the alpha tiles * and then passes them on to a CompositePipe object for painting. */ -public class AAShapePipe implements ShapeDrawPipe { +public class AAShapePipe + implements ShapeDrawPipe, ParallelogramPipe +{ static RenderingEngine renderengine = RenderingEngine.getInstance(); CompositePipe outpipe; @@ -65,6 +68,59 @@ public class AAShapePipe implements ShapeDrawPipe { renderPath(sg, s, null); } + private static Rectangle2D computeBBox(double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + double lox, loy, hix, hiy; + lox = hix = x; + loy = hiy = y; + if (dx1 < 0) { lox += dx1; } else { hix += dx1; } + if (dy1 < 0) { loy += dy1; } else { hiy += dy1; } + if (dx2 < 0) { lox += dx2; } else { hix += dx2; } + if (dy2 < 0) { loy += dy2; } else { hiy += dy2; } + return new Rectangle2D.Double(lox, loy, hix-lox, hiy-loy); + } + + public void fillParallelogram(SunGraphics2D sg, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + Region clip = sg.getCompClip(); + int abox[] = new int[4]; + AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, + clip, abox); + if (aatg == null) { + // Nothing to render + return; + } + + renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox); + } + + public void drawParallelogram(SunGraphics2D sg, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2) + { + Region clip = sg.getCompClip(); + int abox[] = new int[4]; + AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, + clip, abox); + if (aatg == null) { + // Nothing to render + return; + } + + // Note that bbox is of the original shape, not the wide path. + // This is appropriate for handing to Paint methods... + renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox); + } + private static byte[] theTile; public synchronized static byte[] getAlphaTile(int len) { @@ -85,8 +141,6 @@ public class AAShapePipe implements ShapeDrawPipe { boolean adjust = (bs != null && sg.strokeHint != SunHints.INTVAL_STROKE_PURE); boolean thin = (sg.strokeState <= sg.STROKE_THINDASHED); - Object context = null; - byte alpha[] = null; Region clip = sg.getCompClip(); int abox[] = new int[4]; @@ -98,6 +152,14 @@ public class AAShapePipe implements ShapeDrawPipe { return; } + renderTiles(sg, s, aatg, abox); + } + + public void renderTiles(SunGraphics2D sg, Shape s, + AATileGenerator aatg, int abox[]) + { + Object context = null; + byte alpha[] = null; try { context = outpipe.startSequence(sg, s, new Rectangle(abox[0], abox[1], diff --git a/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java b/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java index 28c335307ba..745bdf9bc5a 100644 --- a/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java +++ b/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java @@ -34,7 +34,7 @@ import sun.java2d.SunGraphics2D; * into a destination that supports direct alpha compositing of a solid * color, according to one of the rules in the AlphaComposite class. */ -public class AlphaColorPipe implements CompositePipe { +public class AlphaColorPipe implements CompositePipe, ParallelogramPipe { public AlphaColorPipe() { } @@ -64,4 +64,23 @@ public class AlphaColorPipe implements CompositePipe { public void endSequence(Object context) { return; } + + public void fillParallelogram(SunGraphics2D sg, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + sg.alphafill.FillAAPgram(sg, sg.getSurfaceData(), sg.composite, + x, y, dx1, dy1, dx2, dy2); + } + + public void drawParallelogram(SunGraphics2D sg, + double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2) + { + sg.alphafill.DrawAAPgram(sg, sg.getSurfaceData(), sg.composite, + x, y, dx1, dy1, dx2, dy2, lw1, lw2); + } } diff --git a/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java b/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java index bda742fc6ec..171da288ba3 100644 --- a/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java +++ b/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java @@ -280,6 +280,72 @@ public abstract class RenderingEngine { boolean normalize, int bbox[]); + /** + * Construct an antialiased tile generator for the given parallelogram + * store the bounds of the tile iteration in the bbox parameter. + * The parallelogram is specified as a starting point and 2 delta + * vectors that indicate the slopes of the 2 pairs of sides of the + * parallelogram. + * The 4 corners of the parallelogram are defined by the 4 points: + *
    + *
  • {@code x}, {@code y} + *
  • {@code x+dx1}, {@code y+dy1} + *
  • {@code x+dx1+dx2}, {@code y+dy1+dy2} + *
  • {@code x+dx2}, {@code y+dy2} + *
+ * The {@code lw1} and {@code lw2} parameters provide a specification + * for an optionally stroked parallelogram if they are positive numbers. + * The {@code lw1} parameter is the ratio of the length of the {@code dx1}, + * {@code dx2} delta vector to half of the line width in that same + * direction. + * The {@code lw2} parameter provides the same ratio for the other delta + * vector. + * If {@code lw1} and {@code lw2} are both greater than zero, then + * the parallelogram figure is doubled by both expanding and contracting + * each delta vector by its corresponding {@code lw} value. + * If either (@code lw1) or {@code lw2} are also greater than 1, then + * the inner (contracted) parallelogram disappears and the figure is + * simply a single expanded parallelogram. + * The {@code clip} parameter specifies the current clip in effect + * in device coordinates and can be used to prune the data for the + * operation, but the renderer is not required to perform any + * clipping. + *

+ * Upon returning, this method will fill the {@code bbox} parameter + * with 4 values indicating the bounds of the iteration of the + * tile generator. + * The iteration order of the tiles will be as specified by the + * pseudo-code: + *

+     *     for (y = bbox[1]; y < bbox[3]; y += tileheight) {
+     *         for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
+     *         }
+     *     }
+     * 
+ * If there is no output to be rendered, this method may return + * null. + * + * @param x the X coordinate of the first corner of the parallelogram + * @param y the Y coordinate of the first corner of the parallelogram + * @param dx1 the X coordinate delta of the first leg of the parallelogram + * @param dy1 the Y coordinate delta of the first leg of the parallelogram + * @param dx2 the X coordinate delta of the second leg of the parallelogram + * @param dy2 the Y coordinate delta of the second leg of the parallelogram + * @param lw1 the line width ratio for the first leg of the parallelogram + * @param lw2 the line width ratio for the second leg of the parallelogram + * @param clip the current clip in effect in device coordinates + * @param bbox returns the bounds of the iteration + * @return the {@code AATileGenerator} instance to be consulted + * for tile coverages, or null if there is no output to render + * @since 1.7 + */ + public abstract AATileGenerator getAATileGenerator(double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2, + Region clip, + int bbox[]); + /** * Returns the minimum pen width that the antialiasing rasterizer * can represent without dropouts occuring. @@ -393,5 +459,24 @@ public abstract class RenderingEngine { bs, thin, normalize, bbox); } + public AATileGenerator getAATileGenerator(double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2, + Region clip, + int bbox[]) + { + System.out.println(name+".getAATileGenerator("+ + x+", "+y+", "+ + dx1+", "+dy1+", "+ + dx2+", "+dy2+", "+ + lw1+", "+lw2+", "+ + clip+")"); + return target.getAATileGenerator(x, y, + dx1, dy1, + dx2, dy2, + lw1, lw2, + clip, bbox); + } } } diff --git a/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java index ed6524ceb1b..634fb8e3dc3 100644 --- a/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java +++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java @@ -557,6 +557,69 @@ public class PiscesRenderingEngine extends RenderingEngine { return ptg; } + public AATileGenerator getAATileGenerator(double x, double y, + double dx1, double dy1, + double dx2, double dy2, + double lw1, double lw2, + Region clip, + int bbox[]) + { + // REMIND: Deal with large coordinates! + double ldx1, ldy1, ldx2, ldy2; + boolean innerpgram = (lw1 > 0 && lw2 > 0); + + if (innerpgram) { + ldx1 = dx1 * lw1; + ldy1 = dy1 * lw1; + ldx2 = dx2 * lw2; + ldy2 = dy2 * lw2; + x -= (ldx1 + ldx2) / 2.0; + y -= (ldy1 + ldy2) / 2.0; + dx1 += ldx1; + dy1 += ldy1; + dx2 += ldx2; + dy2 += ldy2; + if (lw1 > 1 && lw2 > 1) { + // Inner parallelogram was entirely consumed by stroke... + innerpgram = false; + } + } else { + ldx1 = ldy1 = ldx2 = ldy2 = 0; + } + + Renderer r = new Renderer(3, 3, + clip.getLoX(), clip.getLoY(), + clip.getWidth(), clip.getHeight(), + PathIterator.WIND_EVEN_ODD); + + r.moveTo((float) x, (float) y); + r.lineTo((float) (x+dx1), (float) (y+dy1)); + r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); + r.lineTo((float) (x+dx2), (float) (y+dy2)); + r.closePath(); + + if (innerpgram) { + x += ldx1 + ldx2; + y += ldy1 + ldy2; + dx1 -= 2.0 * ldx1; + dy1 -= 2.0 * ldy1; + dx2 -= 2.0 * ldx2; + dy2 -= 2.0 * ldy2; + r.moveTo((float) x, (float) y); + r.lineTo((float) (x+dx1), (float) (y+dy1)); + r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2)); + r.lineTo((float) (x+dx2), (float) (y+dy2)); + r.closePath(); + } + + r.pathDone(); + + r.endRendering(); + PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA); + ptg.getBbox(bbox); + return ptg; + } + /** * Returns the minimum pen width that the antialiasing rasterizer * can represent without dropouts occuring. diff --git a/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c b/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c index 5906e6ab605..3d43585ea6a 100644 --- a/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c +++ b/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c @@ -26,14 +26,11 @@ #include "math.h" #include "GraphicsPrimitiveMgr.h" #include "LineUtils.h" -#include "LoopMacros.h" #include "Trace.h" +#include "ParallelogramUtils.h" -#include "sun_java2d_loops_FillParallelogram.h" #include "sun_java2d_loops_DrawParallelogram.h" -DECLARE_SOLID_DRAWLINE(AnyInt); - #define HANDLE_PGRAM_EDGE(X1, Y1, X2, Y2, \ pRasInfo, pixel, pPrim, pFunc, pCompInfo) \ do { \ @@ -46,28 +43,6 @@ DECLARE_SOLID_DRAWLINE(AnyInt); ix1, iy1, ix2, iy2, JNI_TRUE); \ } while (0) -#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \ - do { \ - double vmin, vmax; \ - if (dv1 < 0) { \ - vmin = v0+dv1; \ - vmax = v0; \ - } else { \ - vmin = v0; \ - vmax = v0+dv1; \ - } \ - if (dv2 < 0) { \ - vmin -= dv2; \ - } else { \ - vmax += dv2; \ - } \ - bmin = (jint) floor(vmin + 0.5); \ - bmax = (jint) floor(vmax + 0.5); \ - } while(0) - -#define PGRAM_INIT_X(starty, x, y, slope) \ - (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1) - typedef struct { jdouble x0; jdouble y0; @@ -136,20 +111,8 @@ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram * Sort parallelogram by y values, ensure that each delta vector * has a non-negative y delta. */ - if (dy1 < 0) { - x0 += dx1; y0 += dy1; - dx1 = -dx1; dy1 = -dy1; - } - if (dy2 < 0) { - x0 += dx2; y0 += dy2; - dx2 = -dx2; dy2 = -dy2; - } - /* Sort delta vectors so dxy1 is left of dxy2. */ - if (dx1 * dy2 > dx2 * dy1) { - double v = dx1; dx1 = dx2; dx2 = v; - v = dy1; dy1 = dy2; dy2 = v; - v = lw1; lw1 = lw2; lw2 = v; - } + SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, + v = lw1; lw1 = lw2; lw2 = v;); // dx,dy for line width in the "1" and "2" directions. ldx1 = dx1 * lw1; @@ -161,7 +124,7 @@ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram ox0 = x0 - (ldx1 + ldx2) / 2.0; oy0 = y0 - (ldy1 + ldy2) / 2.0; - PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2); + PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2, JNI_FALSE); iy1 = (jint) floor(oy0 + 0.5); iy2 = (jint) floor(oy0 + dy1 + ldy1 + dy2 + ldy2 + 0.5); @@ -212,7 +175,7 @@ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram // Only need to generate 4 quads if the interior still // has a hole in it (i.e. if the line width ratios were // both less than 1.0) - if (lw1 < 1.0f && lw2 < 1.0f) { + if (lw1 < 1.0 && lw2 < 1.0) { // If the line widths are both less than a pixel wide // then we can use a drawline function instead for even // more performance. diff --git a/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c b/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c index bc55176e19b..158fba77bf1 100644 --- a/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c +++ b/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c @@ -25,31 +25,10 @@ #include "math.h" #include "GraphicsPrimitiveMgr.h" +#include "ParallelogramUtils.h" #include "sun_java2d_loops_FillParallelogram.h" -#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2) \ - do { \ - double vmin, vmax; \ - if (dv1 < 0) { \ - vmin = v0+dv1; \ - vmax = v0; \ - } else { \ - vmin = v0; \ - vmax = v0+dv1; \ - } \ - if (dv2 < 0) { \ - vmin -= dv2; \ - } else { \ - vmax += dv2; \ - } \ - bmin = (jint) floor(vmin + 0.5); \ - bmax = (jint) floor(vmax + 0.5); \ - } while(0) - -#define PGRAM_INIT_X(starty, x, y, slope) \ - (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1) - /* * Class: sun_java2d_loops_FillParallelogram * Method: FillParallelogram @@ -76,22 +55,11 @@ Java_sun_java2d_loops_FillParallelogram_FillParallelogram /* * Sort parallelogram by y values, ensure that each delta vector - * has a non-negative y delta, and eliminate degenerate parallelograms. + * has a non-negative y delta. */ - if (dy1 < 0) { - x0 += dx1; y0 += dy1; - dx1 = -dx1; dy1 = -dy1; - } - if (dy2 < 0) { - x0 += dx2; y0 += dy2; - dx2 = -dx2; dy2 = -dy2; - } - /* Sort delta vectors so dxy1 is left of dxy2. */ - if (dx1 * dy2 > dx2 * dy1) { - double v = dx1; dx1 = dx2; dx2 = v; - v = dy1; dy1 = dy2; dy2 = v; - } - PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2); + SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, ); + + PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2, JNI_FALSE); iy1 = (jint) floor(y0 + 0.5); iy2 = (jint) floor(y0 + dy1 + dy2 + 0.5); diff --git a/jdk/src/share/native/sun/java2d/loops/MaskFill.c b/jdk/src/share/native/sun/java2d/loops/MaskFill.c index c64f3190646..6691ede7a35 100644 --- a/jdk/src/share/native/sun/java2d/loops/MaskFill.c +++ b/jdk/src/share/native/sun/java2d/loops/MaskFill.c @@ -23,7 +23,11 @@ * questions. */ +#include +#include +#include #include "GraphicsPrimitiveMgr.h" +#include "ParallelogramUtils.h" #include "sun_java2d_loops_MaskFill.h" @@ -93,6 +97,967 @@ Java_sun_java2d_loops_MaskFill_MaskFill } } SurfaceData_InvokeRelease(env, sdOps, &rasInfo); + } + SurfaceData_InvokeUnlock(env, sdOps, &rasInfo); +} + +#define MASK_BUF_LEN 1024 + +#define DblToMask(v) ((unsigned char) ((v)*255.9999)) + +/* Fills an aligned rectangle with potentially translucent edges. */ +static void +fillAARect(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo, + CompositeInfo *pCompInfo, jint color, unsigned char *pMask, + void *pDst, + jdouble x1, jdouble y1, jdouble x2, jdouble y2) +{ + jint cx1 = pRasInfo->bounds.x1; + jint cy1 = pRasInfo->bounds.y1; + jint cx2 = pRasInfo->bounds.x2; + jint cy2 = pRasInfo->bounds.y2; + jint rx1 = (jint) ceil(x1); + jint ry1 = (jint) ceil(y1); + jint rx2 = (jint) floor(x2); + jint ry2 = (jint) floor(y2); + jint width = cx2 - cx1; + jint scan = pRasInfo->scanStride; + /* Convert xy12 into the edge coverage fractions for those edges. */ + x1 = rx1-x1; + y1 = ry1-y1; + x2 = x2-rx2; + y2 = y2-ry2; + if (ry2 < ry1) { + /* Accumulate bottom coverage into top coverage. */ + y1 = y1 + y2 - 1.0; + /* prevent processing of "bottom fractional row" */ + ry2 = cy2; + } + if (rx2 < rx1) { + /* Accumulate right coverage into left coverage. */ + x1 = x1 + x2 - 1.0; + /* prevent processing of "right fractional column" */ + rx2 = cx2; + } + /* Check for a visible "top fractional row" and process it */ + if (cy1 < ry1) { + unsigned char midcov = DblToMask(y1); + jint x; + for (x = 0; x < width; x++) { + pMask[x] = midcov; + } + if (cx1 < rx1) { + pMask[0] = DblToMask(y1 * x1); + } + if (cx2 > rx2) { + pMask[width-1] = DblToMask(y1 * x2); + } + (*pPrim->funcs.maskfill)(pDst, + pMask, 0, 0, + width, 1, + color, pRasInfo, + pPrim, pCompInfo); + pDst = PtrAddBytes(pDst, scan); + cy1++; + } + /* Check for a visible "left fract, solid middle, right fract" section. */ + if (cy1 < ry2 && cy1 < cy2) { + jint midh = ((ry2 < cy2) ? ry2 : cy2) - cy1; + jint midx = cx1; + void *pMid = pDst; + /* First process the left "fractional column" if it is visible. */ + if (midx < rx1) { + pMask[0] = DblToMask(x1); + /* Note: maskscan == 0 means we reuse this value for every row. */ + (*pPrim->funcs.maskfill)(pMid, + pMask, 0, 0, + 1, midh, + color, pRasInfo, + pPrim, pCompInfo); + pMid = PtrAddBytes(pMid, pRasInfo->pixelStride); + midx++; + } + /* Process the central solid section if it is visible. */ + if (midx < rx2 && midx < cx2) { + jint midw = ((rx2 < cx2) ? rx2 : cx2) - midx; + /* A NULL mask buffer means "all coverages are 0xff" */ + (*pPrim->funcs.maskfill)(pMid, + NULL, 0, 0, + midw, midh, + color, pRasInfo, + pPrim, pCompInfo); + pMid = PtrCoord(pMid, midw, pRasInfo->pixelStride, 0, 0); + midx += midw; + } + /* Finally process the right "fractional column" if it is visible. */ + if (midx < cx2) { + pMask[0] = DblToMask(x2); + /* Note: maskscan == 0 means we reuse this value for every row. */ + (*pPrim->funcs.maskfill)(pMid, + pMask, 0, 0, + 1, midh, + color, pRasInfo, + pPrim, pCompInfo); + } + cy1 += midh; + pDst = PtrCoord(pDst, 0, 0, midh, scan); + } + /* Check for a visible "bottom fractional row" and process it */ + if (cy1 < cy2) { + unsigned char midcov = DblToMask(y2); + jint x; + for (x = 0; x < width; x++) { + pMask[x] = midcov; + } + if (cx1 < rx1) { + pMask[0] = DblToMask(y2 * x1); + } + if (cx2 > rx2) { + pMask[width-1] = DblToMask(y2 * x2); + } + (*pPrim->funcs.maskfill)(pDst, + pMask, 0, 0, + width, 1, + color, pRasInfo, + pPrim, pCompInfo); + } +} + +/* + * Support code for arbitrary tracing and MaskFill filling of + * non-rectilinear (diagonal) parallelograms. + * + * This code is based upon the following model of AA coverage. + * + * Each edge of a parallelogram (for fillPgram) or a double + * parallelogram (inner and outer parallelograms for drawPgram) + * can be rasterized independently because the geometry is well + * defined in such a way that none of the sides will ever cross + * each other and they have a fixed ordering that is fairly + * well predetermined. + * + * So, for each edge we will look at the diagonal line that + * the edge makes as it passes through a row of pixels. Some + * such diagonal lines may pass entirely through the row of + * pixels in a single pixel column. Some may cut across the + * row and pass through several pixel columns before they pass + * on to the next row. + * + * As the edge passes through the row of pixels it will affect + * the coverage of the pixels it passes through as well as all + * of the pixels to the right of the edge. The coverage will + * either be increased (by a left edge of a parallelogram) or + * decreased (by a right edge) for all pixels to the right, until + * another edge passing the opposite direction is encountered. + * + * The coverage added or subtracted by an edge as it crosses a + * given pixel is calculated using a trapezoid formula in the + * following manner: + * + * / + * +-----+---/-+-----+ + * | | / | | + * | | / | | + * +-----+/----+-----+ + * / + * + * The area to the right of that edge for the pixel where it + * crosses is given as: + * + * trapheight * (topedge + bottomedge)/2 + * + * Another thing to note is that the above formula gives the + * contribution of that edge to the given pixel where it crossed, + * but in so crossing the pixel row, it also created 100% coverage + * for all of the pixels to the right. + * + * This example was simplified in that the edge depicted crossed + * the complete pixel row and it did so entirely within the bounds + * of a single pixel column. In practice, many edges may start or + * end in a given row and thus provide only partial row coverage + * (i.e. the total "trapheight" in the formula never reaches 1.0). + * And in other cases, edges may travel sideways through several + * pixel columns on a given pixel row from where they enter it to + * where the leave it (which also mans that the trapheight for a + * given pixel will be less than 1.0, but by the time the edge + * completes its journey through the pixel row the "coverage shadow" + * that it casts on all pixels to the right eventually reaches 100%). + * + * In order to simplify the calculations so that we don't have to + * keep propagating coverages we calculate for one edge "until we + * reach another edge" we will process one edge at a time and + * simply record in a buffer the amount that an edge added to + * or subtracted from the coverage for a given pixel and its + * following right-side neighbors. Thus, the true total coverage + * of a given pixel is only determined by summing the deltas for + * that pixel and all of the pixels to its left. Since we already + * have to scan the buffer to change floating point coverages into + * mask values for a MaskFill loop, it is simple enough to sum the + * values as we perform that scan from left to right. + * + * In the above example, note that 2 deltas need to be recorded even + * though the edge only intersected a single pixel. The delta recorded + * for the pixel where the edge crossed will be approximately 55% + * (guesstimating by examining the poor ascii art) which is fine for + * determining how to render that pixel, but the rest of the pixels + * to its right should have their coverage modified by a full 100% + * and the 55% delta value we recorded for the pixel that the edge + * crossed will not get them there. We adjust for this by adding + * the "remainder" of the coverage implied by the shadow to the + * pixel immediately to the right of where we record a trapezoidal + * contribution. In this case a delta of 45% will be recorded in + * the pixel immediately to the right to raise the total to 100%. + * + * As we sum these delta values as we process the line from left + * to right, these delta values will typically drive the sum from + * 0% up to 100% and back down to 0% over the course of a single + * pixel row. In the case of a drawn (double) parallelogram the + * sum will go to 100% and back to 0% twice on most scanlines. + * + * The fillAAPgram and drawAAPgram functions drive the main flow + * of the algorithm with help from the following structures, + * macros, and functions. It is probably best to start with + * those 2 functions to gain an understanding of the algorithm. + */ +typedef struct { + jdouble x; + jdouble y; + jdouble xbot; + jdouble ybot; + jdouble xnexty; + jdouble ynextx; + jdouble xnextx; + jdouble linedx; + jdouble celldx; + jdouble celldy; + jboolean isTrailing; +} EdgeInfo; + +#define MIN_DELTA (1.0/256.0) + +/* + * Calculates slopes and deltas for an edge and stores results in an EdgeInfo. + * Returns true if the edge was valid (i.e. not ignored for some reason). + */ +static jboolean +storeEdge(EdgeInfo *pEdge, + jdouble x, jdouble y, jdouble dx, jdouble dy, + jint cx1, jint cy1, jint cx2, jint cy2, + jboolean isTrailing) +{ + jdouble xbot = x + dx; + jdouble ybot = y + dy; + jboolean ret; + + pEdge->x = x; + pEdge->y = y; + pEdge->xbot = xbot; + pEdge->ybot = ybot; + + /* Note that parallelograms are sorted so dy is always non-negative */ + if (dy > MIN_DELTA && /* NaN and horizontal protection */ + ybot > cy1 && /* NaN and "OUT_ABOVE" protection */ + y < cy2 && /* NaN and "OUT_BELOW" protection */ + xbot == xbot && /* NaN protection */ + (x < cx2 || xbot < cx2)) /* "OUT_RIGHT" protection */ + /* Note: "OUT_LEFT" segments may still contribute coverage... */ + { + /* no NaNs, dy is not horizontal, and segment contributes to clip */ + if (dx < -MIN_DELTA || dx > MIN_DELTA) { + /* dx is not vertical */ + jdouble linedx; + jdouble celldy; + jdouble nextx; + + linedx = dx / dy; + celldy = dy / dx; + if (y < cy1) { + pEdge->x = x = x + (cy1 - y) * linedx; + pEdge->y = y = cy1; + } + pEdge->linedx = linedx; + if (dx < 0) { + pEdge->celldx = -1.0; + pEdge->celldy = -celldy; + pEdge->xnextx = nextx = ceil(x) - 1.0; + } else { + pEdge->celldx = +1.0; + pEdge->celldy = celldy; + pEdge->xnextx = nextx = floor(x) + 1.0; + } + pEdge->ynextx = y + (nextx - x) * celldy; + pEdge->xnexty = x + ((floor(y) + 1) - y) * linedx; + } else { + /* dx is essentially vertical */ + if (y < cy1) { + pEdge->y = y = cy1; + } + pEdge->xbot = x; + pEdge->linedx = 0.0; + pEdge->celldx = 0.0; + pEdge->celldy = 1.0; + pEdge->xnextx = x; + pEdge->xnexty = x; + pEdge->ynextx = ybot; + } + ret = JNI_TRUE; + } else { + /* There is some reason to ignore this segment, "celldy=0" omits it */ + pEdge->ybot = y; + pEdge->linedx = dx; + pEdge->celldx = dx; + pEdge->celldy = 0.0; + pEdge->xnextx = xbot; + pEdge->xnexty = xbot; + pEdge->ynextx = y; + ret = JNI_FALSE; + } + pEdge->isTrailing = isTrailing; + return ret; +} + +/* + * Calculates and stores slopes and deltas for all edges of a parallelogram. + * Returns true if at least 1 edge was valid (i.e. not ignored for some reason). + * + * The inverted flag is true for an outer parallelogram (left and right + * edges are leading and trailing) and false for an inner parallelogram + * (where the left edge is trailing and the right edge is leading). + */ +static jboolean +storePgram(EdgeInfo *pLeftEdge, EdgeInfo *pRightEdge, + jdouble x, jdouble y, + jdouble dx1, jdouble dy1, + jdouble dx2, jdouble dy2, + jint cx1, jint cy1, jint cx2, jint cy2, + jboolean inverted) +{ + jboolean ret = JNI_FALSE; + ret = (storeEdge(pLeftEdge + 0, + x , y , dx1, dy1, + cx1, cy1, cx2, cy2, inverted) || ret); + ret = (storeEdge(pLeftEdge + 1, + x+dx1, y+dy1, dx2, dy2, + cx1, cy1, cx2, cy2, inverted) || ret); + ret = (storeEdge(pRightEdge + 0, + x , y , dx2, dy2, + cx1, cy1, cx2, cy2, !inverted) || ret); + ret = (storeEdge(pRightEdge + 1, + x+dx2, y+dy2, dx1, dy1, + cx1, cy1, cx2, cy2, !inverted) || ret); + return ret; +} + +/* + * The X0,Y0,X1,Y1 values represent a trapezoidal fragment whose + * coverage must be accounted for in the accum buffer. + * + * All four values are assumed to fall within (or on the edge of) + * a single pixel. + * + * The trapezoid area is accumulated into the proper element of + * the accum buffer and the remainder of the "slice height" is + * accumulated into the element to its right. + */ +#define INSERT_ACCUM(pACCUM, IMIN, IMAX, X0, Y0, X1, Y1, CX1, CX2, MULT) \ + do { \ + jdouble xmid = ((X0) + (X1)) * 0.5; \ + if (xmid <= (CX2)) { \ + jdouble sliceh = ((Y1) - (Y0)); \ + jdouble slicearea; \ + jint i; \ + if (xmid < (CX1)) { \ + /* Accumulate the entire slice height into accum[0]. */ \ + i = 0; \ + slicearea = sliceh; \ + } else { \ + jdouble xpos = floor(xmid); \ + i = ((jint) xpos) - (CX1); \ + slicearea = (xpos+1-xmid) * sliceh; \ + } \ + if (IMIN > i) { \ + IMIN = i; \ + } \ + (pACCUM)[i++] += (jfloat) ((MULT) * slicearea); \ + (pACCUM)[i++] += (jfloat) ((MULT) * (sliceh - slicearea)); \ + if (IMAX < i) { \ + IMAX = i; \ + } \ + } \ + } while (0) + +/* + * Accumulate the contributions for a given edge crossing a given + * scan line into the corresponding entries of the accum buffer. + * CY1 is the Y coordinate of the top edge of the scanline and CY2 + * is equal to (CY1 + 1) and is the Y coordinate of the bottom edge + * of the scanline. CX1 and CX2 are the left and right edges of the + * clip (or area of interest) being rendered. + * + * The edge is processed from the top edge to the bottom edge and + * a single pixel column at a time. + */ +#define ACCUM_EDGE(pEDGE, pACCUM, IMIN, IMAX, CX1, CY1, CX2, CY2) \ + do { \ + jdouble x, y, xnext, ynext, xlast, ylast, dx, dy, mult; \ + y = (pEDGE)->y; \ + dy = (pEDGE)->celldy; \ + ylast = (pEDGE)->ybot; \ + if (ylast <= (CY1) || y >= (CY2) || dy == 0.0) { \ + break; \ + } \ + x = (pEDGE)->x; \ + dx = (pEDGE)->celldx; \ + if (ylast > (CY2)) { \ + ylast = (CY2); \ + xlast = (pEDGE)->xnexty; \ + } else { \ + xlast = (pEDGE)->xbot; \ + } \ + xnext = (pEDGE)->xnextx; \ + ynext = (pEDGE)->ynextx; \ + mult = ((pEDGE)->isTrailing) ? -1.0 : 1.0; \ + while (ynext <= ylast) { \ + INSERT_ACCUM(pACCUM, IMIN, IMAX, \ + x, y, xnext, ynext, \ + CX1, CX2, mult); \ + x = xnext; \ + y = ynext; \ + xnext += dx; \ + ynext += dy; \ + } \ + (pEDGE)->ynextx = ynext; \ + (pEDGE)->xnextx = xnext; \ + INSERT_ACCUM(pACCUM, IMIN, IMAX, \ + x, y, xlast, ylast, \ + CX1, CX2, mult); \ + (pEDGE)->x = xlast; \ + (pEDGE)->y = ylast; \ + (pEDGE)->xnexty = xlast + (pEDGE)->linedx; \ + } while(0) + +/* Main function to fill a single Parallelogram */ +static void +fillAAPgram(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo, + CompositeInfo *pCompInfo, jint color, unsigned char *pMask, + void *pDst, + jdouble x1, jdouble y1, + jdouble dx1, jdouble dy1, + jdouble dx2, jdouble dy2) +{ + jint cx1 = pRasInfo->bounds.x1; + jint cy1 = pRasInfo->bounds.y1; + jint cx2 = pRasInfo->bounds.x2; + jint cy2 = pRasInfo->bounds.y2; + jint width = cx2 - cx1; + EdgeInfo edges[4]; + jfloat localaccum[MASK_BUF_LEN + 1]; + jfloat *pAccum; + + if (!storePgram(edges + 0, edges + 2, + x1, y1, dx1, dy1, dx2, dy2, + cx1, cy1, cx2, cy2, + JNI_FALSE)) + { + return; + } + + pAccum = ((width > MASK_BUF_LEN) + ? malloc((width + 1) * sizeof(jfloat)) + : localaccum); + if (pAccum == NULL) { + return; + } + memset(pAccum, 0, (width+1) * sizeof(jfloat)); + + while (cy1 < cy2) { + jint lmin, lmax, rmin, rmax; + jint moff, x; + jdouble accum; + unsigned char lastcov; + + lmin = rmin = width + 2; + lmax = rmax = 0; + ACCUM_EDGE(&edges[0], pAccum, lmin, lmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[1], pAccum, lmin, lmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[2], pAccum, rmin, rmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[3], pAccum, rmin, rmax, + cx1, cy1, cx2, cy1+1); + if (lmax > width) { + lmax = width; /* Extra col has data we do not need. */ + } + if (rmax > width) { + rmax = width; /* Extra col has data we do not need. */ + } + /* If ranges overlap, handle both in the first pass. */ + if (rmin <= lmax) { + lmax = rmax; + } + + x = lmin; + accum = 0.0; + moff = 0; + lastcov = 0; + while (x < lmax) { + accum += pAccum[x]; + pAccum[x] = 0.0f; + pMask[moff++] = lastcov = DblToMask(accum); + x++; + } + /* Check for a solid center section. */ + if (lastcov == 0xFF) { + jint endx; + void *pRow; + + /* First process the existing partial coverage data. */ + if (moff > 0) { + pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0); + (*pPrim->funcs.maskfill)(pRow, + pMask, 0, 0, + moff, 1, + color, pRasInfo, + pPrim, pCompInfo); + moff = 0; + } + + /* Where does the center section end? */ + /* If there is no right AA edge in the accum buffer, then */ + /* the right edge was beyond the clip, so fill out to width */ + endx = (rmin < rmax) ? rmin : width; + if (x < endx) { + pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0); + (*pPrim->funcs.maskfill)(pRow, + NULL, 0, 0, + endx - x, 1, + color, pRasInfo, + pPrim, pCompInfo); + x = endx; + } + } else if (lastcov > 0 && rmin >= rmax) { + /* We are not at 0 coverage, but there is no right edge, */ + /* force a right edge so we process pixels out to width. */ + rmax = width; + } + /* The following loop will process the right AA edge and/or any */ + /* partial coverage center section not processed above. */ + while (x < rmax) { + accum += pAccum[x]; + pAccum[x] = 0.0f; + pMask[moff++] = DblToMask(accum); + x++; + } + if (moff > 0) { + void *pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0); + (*pPrim->funcs.maskfill)(pRow, + pMask, 0, 0, + moff, 1, + color, pRasInfo, + pPrim, pCompInfo); + } + pDst = PtrAddBytes(pDst, pRasInfo->scanStride); + cy1++; + } + if (pAccum != localaccum) { + free(pAccum); + } +} + +/* + * Class: sun_java2d_loops_MaskFill + * Method: FillAAPgram + * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDD)V + */ +JNIEXPORT void JNICALL +Java_sun_java2d_loops_MaskFill_FillAAPgram + (JNIEnv *env, jobject self, + jobject sg2d, jobject sData, jobject comp, + jdouble x0, jdouble y0, + jdouble dx1, jdouble dy1, + jdouble dx2, jdouble dy2) +{ + SurfaceDataOps *sdOps; + SurfaceDataRasInfo rasInfo; + NativePrimitive *pPrim; + CompositeInfo compInfo; + jint ix1, iy1, ix2, iy2; + + if ((dy1 == 0 && dx1 == 0) || (dy2 == 0 && dx2 == 0)) { + return; + } + + /* + * Sort parallelogram by y values, ensure that each delta vector + * has a non-negative y delta. + */ + SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, ); + + PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2, JNI_TRUE); + iy1 = (jint) floor(y0); + iy2 = (jint) ceil(y0 + dy1 + dy2); + + pPrim = GetNativePrim(env, self); + if (pPrim == NULL) { + return; + } + if (pPrim->pCompType->getCompInfo != NULL) { + (*pPrim->pCompType->getCompInfo)(env, &compInfo, comp); + } + + sdOps = SurfaceData_GetOps(env, sData); + if (sdOps == 0) { + return; + } + + GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds); + SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2); + if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 || + rasInfo.bounds.x2 <= rasInfo.bounds.x1) + { + return; + } + + if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) { + return; + } + + ix1 = rasInfo.bounds.x1; + iy1 = rasInfo.bounds.y1; + ix2 = rasInfo.bounds.x2; + iy2 = rasInfo.bounds.y2; + if (ix2 > ix1 && iy2 > iy1) { + jint width = ix2 - ix1; + jint color = GrPrim_Sg2dGetEaRGB(env, sg2d); + unsigned char localmask[MASK_BUF_LEN]; + unsigned char *pMask = ((width > MASK_BUF_LEN) + ? malloc(width) + : localmask); + + sdOps->GetRasInfo(env, sdOps, &rasInfo); + if (rasInfo.rasBase != NULL && pMask != NULL) { + void *pDst = PtrCoord(rasInfo.rasBase, + ix1, rasInfo.pixelStride, + iy1, rasInfo.scanStride); + if (dy1 == 0 && dx2 == 0) { + if (dx1 < 0) { + // We sorted by Y above, but not by X + x0 += dx1; + dx1 = -dx1; + } + fillAARect(pPrim, &rasInfo, &compInfo, + color, pMask, pDst, + x0, y0, x0+dx1, y0+dy2); + } else if (dx1 == 0 && dy2 == 0) { + if (dx2 < 0) { + // We sorted by Y above, but not by X + x0 += dx2; + dx2 = -dx2; + } + fillAARect(pPrim, &rasInfo, &compInfo, + color, pMask, pDst, + x0, y0, x0+dx2, y0+dy1); + } else { + fillAAPgram(pPrim, &rasInfo, &compInfo, + color, pMask, pDst, + x0, y0, dx1, dy1, dx2, dy2); + } + } + SurfaceData_InvokeRelease(env, sdOps, &rasInfo); + if (pMask != NULL && pMask != localmask) { + free(pMask); + } + } + SurfaceData_InvokeUnlock(env, sdOps, &rasInfo); +} + +/* Main function to fill a double pair of (inner and outer) parallelograms */ +static void +drawAAPgram(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo, + CompositeInfo *pCompInfo, jint color, unsigned char *pMask, + void *pDst, + jdouble ox0, jdouble oy0, + jdouble dx1, jdouble dy1, + jdouble dx2, jdouble dy2, + jdouble ldx1, jdouble ldy1, + jdouble ldx2, jdouble ldy2) +{ + jint cx1 = pRasInfo->bounds.x1; + jint cy1 = pRasInfo->bounds.y1; + jint cx2 = pRasInfo->bounds.x2; + jint cy2 = pRasInfo->bounds.y2; + jint width = cx2 - cx1; + EdgeInfo edges[8]; + jfloat localaccum[MASK_BUF_LEN + 1]; + jfloat *pAccum; + + if (!storePgram(edges + 0, edges + 6, + ox0, oy0, + dx1 + ldx1, dy1 + ldy1, + dx2 + ldx2, dy2 + ldy2, + cx1, cy1, cx2, cy2, + JNI_FALSE)) + { + /* If outer pgram does not contribute, then inner cannot either. */ + return; + } + storePgram(edges + 2, edges + 4, + ox0 + ldx1 + ldx2, oy0 + ldy1 + ldy2, + dx1 - ldx1, dy1 - ldy1, + dx2 - ldx2, dy2 - ldy2, + cx1, cy1, cx2, cy2, + JNI_TRUE); + + pAccum = ((width > MASK_BUF_LEN) + ? malloc((width + 1) * sizeof(jfloat)) + : localaccum); + if (pAccum == NULL) { + return; + } + memset(pAccum, 0, (width+1) * sizeof(jfloat)); + + while (cy1 < cy2) { + jint lmin, lmax, rmin, rmax; + jint moff, x; + jdouble accum; + unsigned char lastcov; + + lmin = rmin = width + 2; + lmax = rmax = 0; + ACCUM_EDGE(&edges[0], pAccum, lmin, lmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[1], pAccum, lmin, lmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[2], pAccum, lmin, lmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[3], pAccum, lmin, lmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[4], pAccum, rmin, rmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[5], pAccum, rmin, rmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[6], pAccum, rmin, rmax, + cx1, cy1, cx2, cy1+1); + ACCUM_EDGE(&edges[7], pAccum, rmin, rmax, + cx1, cy1, cx2, cy1+1); + if (lmax > width) { + lmax = width; /* Extra col has data we do not need. */ + } + if (rmax > width) { + rmax = width; /* Extra col has data we do not need. */ + } + /* If ranges overlap, handle both in the first pass. */ + if (rmin <= lmax) { + lmax = rmax; + } + + x = lmin; + accum = 0.0; + moff = 0; + lastcov = 0; + while (x < lmax) { + accum += pAccum[x]; + pAccum[x] = 0.0f; + pMask[moff++] = lastcov = DblToMask(accum); + x++; + } + /* Check for an empty or solidcenter section. */ + if (lastcov == 0 || lastcov == 0xFF) { + jint endx; + void *pRow; + + /* First process the existing partial coverage data. */ + if (moff > 0) { + pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0); + (*pPrim->funcs.maskfill)(pRow, + pMask, 0, 0, + moff, 1, + color, pRasInfo, + pPrim, pCompInfo); + moff = 0; + } + + /* Where does the center section end? */ + /* If there is no right AA edge in the accum buffer, then */ + /* the right edge was beyond the clip, so fill out to width */ + endx = (rmin < rmax) ? rmin : width; + if (x < endx) { + if (lastcov == 0xFF) { + pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0); + (*pPrim->funcs.maskfill)(pRow, + NULL, 0, 0, + endx - x, 1, + color, pRasInfo, + pPrim, pCompInfo); + } + x = endx; + } + } else if (rmin >= rmax) { + /* We are not at 0 coverage, but there is no right edge, */ + /* force a right edge so we process pixels out to width. */ + rmax = width; + } + /* The following loop will process the right AA edge and/or any */ + /* partial coverage center section not processed above. */ + while (x < rmax) { + accum += pAccum[x]; + pAccum[x] = 0.0f; + pMask[moff++] = lastcov = DblToMask(accum); + x++; + } + if (moff > 0) { + void *pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0); + (*pPrim->funcs.maskfill)(pRow, + pMask, 0, 0, + moff, 1, + color, pRasInfo, + pPrim, pCompInfo); + } + if (lastcov == 0xFF && x < width) { + void *pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0); + (*pPrim->funcs.maskfill)(pRow, + NULL, 0, 0, + width - x, 1, + color, pRasInfo, + pPrim, pCompInfo); + } + pDst = PtrAddBytes(pDst, pRasInfo->scanStride); + cy1++; + } + if (pAccum != localaccum) { + free(pAccum); + } +} + +/* + * Class: sun_java2d_loops_MaskFill + * Method: DrawAAPgram + * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDDDD)V + */ +JNIEXPORT void JNICALL +Java_sun_java2d_loops_MaskFill_DrawAAPgram + (JNIEnv *env, jobject self, + jobject sg2d, jobject sData, jobject comp, + jdouble x0, jdouble y0, + jdouble dx1, jdouble dy1, + jdouble dx2, jdouble dy2, + jdouble lw1, jdouble lw2) +{ + SurfaceDataOps *sdOps; + SurfaceDataRasInfo rasInfo; + NativePrimitive *pPrim; + CompositeInfo compInfo; + jint ix1, iy1, ix2, iy2; + jdouble ldx1, ldy1, ldx2, ldy2; + jdouble ox0, oy0; + + if ((dy1 == 0 && dx1 == 0) || (dy2 == 0 && dx2 == 0)) { + return; + } + + /* + * Sort parallelogram by y values, ensure that each delta vector + * has a non-negative y delta. + */ + SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, + v = lw1; lw1 = lw2; lw2 = v;); + + // dx,dy for line width in the "1" and "2" directions. + ldx1 = dx1 * lw1; + ldy1 = dy1 * lw1; + ldx2 = dx2 * lw2; + ldy2 = dy2 * lw2; + + // calculate origin of the outer parallelogram + ox0 = x0 - (ldx1 + ldx2) / 2.0; + oy0 = y0 - (ldy1 + ldy2) / 2.0; + + if (lw1 >= 1.0 || lw2 >= 1.0) { + /* Only need to fill an outer pgram if the interior no longer + * has a hole in it (i.e. if either of the line width ratios + * were greater than or equal to 1.0). + */ + Java_sun_java2d_loops_MaskFill_FillAAPgram(env, self, + sg2d, sData, comp, + ox0, oy0, + dx1 + ldx1, dy1 + ldy1, + dx2 + ldx2, dy2 + ldy2); + return; + } + + PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2, JNI_TRUE); + iy1 = (jint) floor(oy0); + iy2 = (jint) ceil(oy0 + dy1 + ldy1 + dy2 + ldy2); + + pPrim = GetNativePrim(env, self); + if (pPrim == NULL) { + return; + } + if (pPrim->pCompType->getCompInfo != NULL) { + (*pPrim->pCompType->getCompInfo)(env, &compInfo, comp); + } + + sdOps = SurfaceData_GetOps(env, sData); + if (sdOps == 0) { + return; + } + + GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds); + SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2); + if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 || + rasInfo.bounds.x2 <= rasInfo.bounds.x1) + { + return; + } + + if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) { + return; + } + + ix1 = rasInfo.bounds.x1; + iy1 = rasInfo.bounds.y1; + ix2 = rasInfo.bounds.x2; + iy2 = rasInfo.bounds.y2; + if (ix2 > ix1 && iy2 > iy1) { + jint width = ix2 - ix1; + jint color = GrPrim_Sg2dGetEaRGB(env, sg2d); + unsigned char localmask[MASK_BUF_LEN]; + unsigned char *pMask = ((width > MASK_BUF_LEN) + ? malloc(width) + : localmask); + + sdOps->GetRasInfo(env, sdOps, &rasInfo); + if (rasInfo.rasBase != NULL && pMask != NULL) { + void *pDst = PtrCoord(rasInfo.rasBase, + ix1, rasInfo.pixelStride, + iy1, rasInfo.scanStride); + /* + * NOTE: aligned rects could probably be drawn + * even faster with a little work here. + * if (dy1 == 0 && dx2 == 0) { + * drawAARect(pPrim, &rasInfo, &compInfo, + * color, pMask, pDst, + * ox0, oy0, ox0+dx1+ldx1, oy0+dy2+ldy2, ldx1, ldy2); + * } else if (dx1 == 0 && dy2 == 0) { + * drawAARect(pPrim, &rasInfo, &compInfo, + * color, pMask, pDst, + * ox0, oy0, ox0+dx2+ldx2, oy0+dy1+ldy1, ldx2, ldy1); + * } else { + */ + drawAAPgram(pPrim, &rasInfo, &compInfo, + color, pMask, pDst, + ox0, oy0, + dx1, dy1, dx2, dy2, + ldx1, ldy1, ldx2, ldy2); + /* + * } + */ + } + SurfaceData_InvokeRelease(env, sdOps, &rasInfo); + if (pMask != NULL && pMask != localmask) { + free(pMask); + } } SurfaceData_InvokeUnlock(env, sdOps, &rasInfo); } diff --git a/jdk/src/share/native/sun/java2d/loops/ParallelogramUtils.h b/jdk/src/share/native/sun/java2d/loops/ParallelogramUtils.h new file mode 100644 index 00000000000..3691abad25c --- /dev/null +++ b/jdk/src/share/native/sun/java2d/loops/ParallelogramUtils.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef ParallelogramUtils_h_Included +#define ParallelogramUtils_h_Included + +#ifdef __cplusplus +extern "C" { +#endif + +#define PGRAM_MIN_MAX(bmin, bmax, v0, dv1, dv2, AA) \ + do { \ + double vmin, vmax; \ + if (dv1 < 0) { \ + vmin = v0+dv1; \ + vmax = v0; \ + } else { \ + vmin = v0; \ + vmax = v0+dv1; \ + } \ + if (dv2 < 0) { \ + vmin += dv2; \ + } else { \ + vmax += dv2; \ + } \ + if (AA) { \ + bmin = (jint) floor(vmin); \ + bmax = (jint) ceil(vmax); \ + } else { \ + bmin = (jint) floor(vmin + 0.5); \ + bmax = (jint) floor(vmax + 0.5); \ + } \ + } while(0) + +#define PGRAM_INIT_X(starty, x, y, slope) \ + (DblToLong((x) + (slope) * ((starty)+0.5 - (y))) + LongOneHalf - 1) + +/* + * Sort parallelogram by y values, ensure that each delta vector + * has a non-negative y delta. + */ +#define SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, OTHER_SWAP_CODE) \ + do { \ + if (dy1 < 0) { \ + x0 += dx1; y0 += dy1; \ + dx1 = -dx1; dy1 = -dy1; \ + } \ + if (dy2 < 0) { \ + x0 += dx2; y0 += dy2; \ + dx2 = -dx2; dy2 = -dy2; \ + } \ + /* Sort delta vectors so dxy1 is left of dxy2. */ \ + if (dx1 * dy2 > dx2 * dy1) { \ + double v; \ + v = dx1; dx1 = dx2; dx2 = v; \ + v = dy1; dy1 = dy2; dy2 = v; \ + OTHER_SWAP_CODE \ + } \ + } while(0) + +#endif /* ParallelogramUtils_h_Included */ diff --git a/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c b/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c index 7eb84eb1e5f..2b142c46c48 100644 --- a/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c +++ b/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre_Mask.c @@ -517,13 +517,15 @@ void ADD_SUFF(IntArgbPreSrcMaskFill)(void *rasBase, ADD_SUFF(AnyIntSetRect)(pRasInfo, 0, 0, width, height, fgColor, pPrim, pCompInfo); #else + void *pBase = pRasInfo->rasBase; + pRasInfo->rasBase = rasBase; if (cnstA != 0xff) { fgColor = (cnstA << 24) | (cnstR << 16) | (cnstG << 8) | cnstB; } ADD_SUFF(AnyIntSetRect)(pRasInfo, - pRasInfo->bounds.x1, pRasInfo->bounds.y1, - pRasInfo->bounds.x2, pRasInfo->bounds.y2, + 0, 0, width, height, fgColor, pPrim, pCompInfo); + pRasInfo->rasBase = pBase; #endif return; } @@ -582,11 +584,13 @@ void ADD_SUFF(FourByteAbgrPreSrcMaskFill)(void *rasBase, } if (pMask == NULL) { + void *pBase = pRasInfo->rasBase; + pRasInfo->rasBase = rasBase; fgColor = (cnstR << 24) | (cnstG << 16) | (cnstB << 8) | cnstA; ADD_SUFF(Any4ByteSetRect)(pRasInfo, - pRasInfo->bounds.x1, pRasInfo->bounds.y1, - pRasInfo->bounds.x2, pRasInfo->bounds.y2, + 0, 0, width, height, fgColor, pPrim, pCompInfo); + pRasInfo->rasBase = pBase; return; } diff --git a/jdk/src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c b/jdk/src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c index f5bf5c46e49..170ab458d80 100644 --- a/jdk/src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c +++ b/jdk/src/solaris/native/sun/java2d/loops/vis_SrcMaskFill.c @@ -150,10 +150,12 @@ void ADD_SUFF(IntArgbSrcMaskFill)(void *rasBase, } if (pMask == NULL) { + void *pBase = pRasInfo->rasBase; + pRasInfo->rasBase = rasBase; ADD_SUFF(AnyIntSetRect)(pRasInfo, - pRasInfo->bounds.x1, pRasInfo->bounds.y1, - pRasInfo->bounds.x2, pRasInfo->bounds.y2, + 0, 0, width, height, fgColor, pPrim, pCompInfo); + pRasInfo->rasBase = pBase; return; } @@ -214,15 +216,17 @@ void ADD_SUFF(FourByteAbgrSrcMaskFill)(void *rasBase, cnstB = (fgColor ) & 0xff; if (pMask == NULL) { + void *pBase = pRasInfo->rasBase; + pRasInfo->rasBase = rasBase; if (cnstA == 0) { fgColor = 0; } else { fgColor = (fgColor << 8) | cnstA; } ADD_SUFF(Any4ByteSetRect)(pRasInfo, - pRasInfo->bounds.x1, pRasInfo->bounds.y1, - pRasInfo->bounds.x2, pRasInfo->bounds.y2, + 0, 0, width, height, fgColor, pPrim, pCompInfo); + pRasInfo->rasBase = pBase; return; } @@ -390,10 +394,12 @@ void ADD_SUFF(IntRgbSrcMaskFill)(void *rasBase, if (cnstA == 0) fgColor = 0; if (pMask == NULL) { + void *pBase = pRasInfo->rasBase; + pRasInfo->rasBase = rasBase; ADD_SUFF(AnyIntSetRect)(pRasInfo, - pRasInfo->bounds.x1, pRasInfo->bounds.y1, - pRasInfo->bounds.x2, pRasInfo->bounds.y2, + 0, 0, width, height, fgColor, pPrim, pCompInfo); + pRasInfo->rasBase = pBase; return; } @@ -458,10 +464,12 @@ void ADD_SUFF(IntBgrSrcMaskFill)(void *rasBase, } if (pMask == NULL) { + void *pBase = pRasInfo->rasBase; + pRasInfo->rasBase = rasBase; ADD_SUFF(AnyIntSetRect)(pRasInfo, - pRasInfo->bounds.x1, pRasInfo->bounds.y1, - pRasInfo->bounds.x2, pRasInfo->bounds.y2, + 0, 0, width, height, fgColor, pPrim, pCompInfo); + pRasInfo->rasBase = pBase; return; } @@ -526,10 +534,12 @@ void ADD_SUFF(ThreeByteBgrSrcMaskFill)(void *rasBase, } if (pMask == NULL) { + void *pBase = pRasInfo->rasBase; + pRasInfo->rasBase = rasBase; ADD_SUFF(Any3ByteSetRect)(pRasInfo, - pRasInfo->bounds.x1, pRasInfo->bounds.y1, - pRasInfo->bounds.x2, pRasInfo->bounds.y2, + 0, 0, width, height, fgColor, pPrim, pCompInfo); + pRasInfo->rasBase = pBase; return; } diff --git a/jdk/test/java/awt/Graphics2D/RenderClipTest/6766342.tests b/jdk/test/java/awt/Graphics2D/RenderClipTest/6766342.tests new file mode 100644 index 00000000000..17cf06850d6 --- /dev/null +++ b/jdk/test/java/awt/Graphics2D/RenderClipTest/6766342.tests @@ -0,0 +1,3 @@ +Filled AA Pure Rect(5, 29.4, 10, 10) +Stroked AA Pure Rect(5, 4.4, 10, 10) +Stroked AA Line(20, 20, -10, 20) diff --git a/jdk/test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java b/jdk/test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java new file mode 100644 index 00000000000..e920c448671 --- /dev/null +++ b/jdk/test/java/awt/Graphics2D/RenderClipTest/RenderClipTest.java @@ -0,0 +1,1634 @@ +/* + * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6766342 + * @summary Tests clipping invariance for AA rectangle and line primitives + * @run main RenderClipTest -strict -readfile 6766342.tests + * @run main RenderClipTest -rectsuite -count 10 + */ + +import java.awt.*; +import java.awt.geom.*; +import java.awt.image.*; +import java.awt.event.*; +import java.util.Vector; +import java.io.*; + +public class RenderClipTest { + public static double randDblCoord() { + return Math.random()*60 - 10; + } + + public static float randFltCoord() { + return (float) randDblCoord(); + } + + public static int randIntCoord() { + return (int) Math.round(randDblCoord()); + } + + public static int randInt(int n) { + return ((int) (Math.random() * (n*4))) >> 2; + } + + static int numtests; + static int numerrors; + static int numfillfailures; + static int numstrokefailures; + static int maxerr; + + static boolean useAA; + static boolean strokePure; + static boolean testFill; + static boolean testDraw; + static boolean silent; + static boolean verbose; + static boolean strict; + static boolean showErrors; + static float lw; + static double rot; + + static BufferedImage imgref; + static BufferedImage imgtst; + + static Graphics2D grefclear; + static Graphics2D gtstclear; + static Graphics2D grefrender; + static Graphics2D gtstrender; + + public static abstract class AnnotatedRenderOp { + public static AnnotatedRenderOp parse(String str) { + AnnotatedRenderOp ar; + if (((ar = Cubic.tryparse(str)) != null) || + ((ar = Quad.tryparse(str)) != null) || + ((ar = Poly.tryparse(str)) != null) || + ((ar = Path.tryparse(str)) != null) || + ((ar = Rect.tryparse(str)) != null) || + ((ar = Line.tryparse(str)) != null) || + ((ar = RectMethod.tryparse(str)) != null) || + ((ar = LineMethod.tryparse(str)) != null)) + { + return ar; + } + System.err.println("Unable to parse shape: "+str); + return null; + } + + public abstract void randomize(); + + public abstract void fill(Graphics2D g2d); + + public abstract void draw(Graphics2D g2d); + } + + public static abstract class AnnotatedShapeOp extends AnnotatedRenderOp { + public abstract Shape getShape(); + + public void fill(Graphics2D g2d) { + g2d.fill(getShape()); + } + + public void draw(Graphics2D g2d) { + g2d.draw(getShape()); + } + } + + public static void usage(String err) { + if (err != null) { + System.err.println(err); + } + System.err.println("usage: java RenderClipTest "+ + "[-read[file F]] [-rectsuite] [-fill] [-draw]"); + System.err.println(" "+ + "[-aa] [-pure] [-lw N] [-rot N]"); + System.err.println(" "+ + "[-rectmethod] [-linemethod] [-rect] [-line]"); + System.err.println(" "+ + "[-cubic] [-quad] [-poly] [-path]"); + System.err.println(" "+ + "[-silent] [-verbose] [-showerr] [-count N]"); + System.err.println(" "+ + "[-strict] [-usage]"); + System.err.println(" -read Read test data from stdin"); + System.err.println(" -readfile F Read test data from file F"); + System.err.println(" -rectsuite Run a suite of rect/line tests"); + System.err.println(" -fill Test g.fill*(...)"); + System.err.println(" -draw Test g.draw*(...)"); + System.err.println(" -aa Use antialiased rendering"); + System.err.println(" -pure Use STROKE_PURE hint"); + System.err.println(" -lw N Test line widths of N "+ + "(default 1.0)"); + System.err.println(" -rot N Test rotation by N degrees "+ + "(default 0.0)"); + System.err.println(" -rectmethod Test fillRect/drawRect methods"); + System.err.println(" -linemethod Test drawLine method"); + System.err.println(" -rect Test Rectangle2D shapes"); + System.err.println(" -line Test Line2D shapes"); + System.err.println(" -cubic Test CubicCurve2D shapes"); + System.err.println(" -quad Test QuadCurve2D shapes"); + System.err.println(" -poly Test Polygon shapes"); + System.err.println(" -path Test GeneralPath shapes"); + System.err.println(" -silent Do not print out error curves"); + System.err.println(" -verbose Print out progress info"); + System.err.println(" -showerr Display errors on screen"); + System.err.println(" -count N N tests per shape, then exit "+ + "(default 1000)"); + System.err.println(" -strict All failures are important"); + System.err.println(" -usage Print this help, then exit"); + System.exit((err != null) ? -1 : 0); + } + + public static void main(String argv[]) { + boolean readTests = false; + String readFile = null; + boolean rectsuite = false; + int count = 1000; + lw = 1.0f; + rot = 0.0; + Vector testOps = new Vector(); + for (int i = 0; i < argv.length; i++) { + String arg = argv[i].toLowerCase(); + if (arg.equals("-aa")) { + useAA = true; + } else if (arg.equals("-pure")) { + strokePure = true; + } else if (arg.equals("-fill")) { + testFill = true; + } else if (arg.equals("-draw")) { + testDraw = true; + } else if (arg.equals("-lw")) { + if (i+1 >= argv.length) { + usage("Missing argument: "+argv[i]); + } + lw = Float.parseFloat(argv[++i]); + } else if (arg.equals("-rot")) { + if (i+1 >= argv.length) { + usage("Missing argument: "+argv[i]); + } + rot = Double.parseDouble(argv[++i]); + } else if (arg.equals("-cubic")) { + testOps.add(new Cubic()); + } else if (arg.equals("-quad")) { + testOps.add(new Quad()); + } else if (arg.equals("-poly")) { + testOps.add(new Poly()); + } else if (arg.equals("-path")) { + testOps.add(new Path()); + } else if (arg.equals("-rect")) { + testOps.add(new Rect()); + } else if (arg.equals("-line")) { + testOps.add(new Line()); + } else if (arg.equals("-rectmethod")) { + testOps.add(new RectMethod()); + } else if (arg.equals("-linemethod")) { + testOps.add(new LineMethod()); + } else if (arg.equals("-verbose")) { + verbose = true; + } else if (arg.equals("-strict")) { + strict = true; + } else if (arg.equals("-silent")) { + silent = true; + } else if (arg.equals("-showerr")) { + showErrors = true; + } else if (arg.equals("-readfile")) { + if (i+1 >= argv.length) { + usage("Missing argument: "+argv[i]); + } + readTests = true; + readFile = argv[++i]; + } else if (arg.equals("-read")) { + readTests = true; + readFile = null; + } else if (arg.equals("-rectsuite")) { + rectsuite = true; + } else if (arg.equals("-count")) { + if (i+1 >= argv.length) { + usage("Missing argument: "+argv[i]); + } + count = Integer.parseInt(argv[++i]); + } else if (arg.equals("-usage")) { + usage(null); + } else { + usage("Unknown argument: "+argv[i]); + } + } + if (readTests) { + if (rectsuite || testDraw || testFill || + useAA || strokePure || + lw != 1.0f || rot != 0.0 || + testOps.size() > 0) + { + usage("Should not specify test types with -read options"); + } + } else if (rectsuite) { + if (testDraw || testFill || + useAA || strokePure || + lw != 1.0f || rot != 0.0 || + testOps.size() > 0) + { + usage("Should not specify test types with -rectsuite option"); + } + } else { + if (!testDraw && !testFill) { + usage("No work: Must specify one or both of "+ + "-fill or -draw"); + } + if (testOps.size() == 0) { + usage("No work: Must specify one or more of "+ + "-rect[method], -line[method], "+ + "-cubic, -quad, -poly, or -path"); + } + } + initImages(); + if (readTests) { + try { + InputStream is; + if (readFile == null) { + is = System.in; + } else { + File f = + new File(System.getProperty("test.src", "."), + readFile); + is = new FileInputStream(f); + } + parseAndRun(is); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else if (rectsuite) { + runRectSuite(count); + } else { + initGCs(); + for (int k = 0; k < testOps.size(); k++) { + AnnotatedRenderOp ar = testOps.get(k); + runRandomTests(ar, count); + } + disposeGCs(); + } + grefclear.dispose(); + gtstclear.dispose(); + grefclear = gtstclear = null; + reportStatistics(); + } + + public static int reportStatistics() { + String connector = ""; + if (numfillfailures > 0) { + System.out.print(numfillfailures+" fills "); + connector = "and "; + } + if (numstrokefailures > 0) { + System.out.print(connector+numstrokefailures+" strokes "); + } + int totalfailures = numfillfailures + numstrokefailures; + if (totalfailures == 0) { + System.out.print("0 "); + } + System.out.println("out of "+numtests+" tests failed..."); + int critical = numerrors; + if (strict) { + critical += totalfailures; + } + if (critical > 0) { + throw new RuntimeException(critical+" tests had critical errors"); + } + System.out.println("No tests had critical errors"); + return (numerrors+totalfailures); + } + + public static void runRectSuite(int count) { + AnnotatedRenderOp ops[] = { + new Rect(), + new RectMethod(), + new Line(), + new LineMethod(), + }; + // Sometimes different fill algorithms are chosen for + // thin and wide line modes, make sure we test both... + float filllinewidths[] = { 0.0f, 2.0f }; + float drawlinewidths[] = { 0.0f, 0.5f, 1.0f, + 2.0f, 2.5f, + 5.0f, 5.3f }; + double rotations[] = { 0.0, 15.0, 90.0, + 135.0, 180.0, + 200.0, 270.0, + 300.0}; + for (AnnotatedRenderOp ar: ops) { + for (double r: rotations) { + rot = r; + for (int i = 0; i < 8; i++) { + float linewidths[]; + if ((i & 1) == 0) { + if ((ar instanceof Line) || + (ar instanceof LineMethod)) + { + continue; + } + testFill = true; + testDraw = false; + linewidths = filllinewidths; + } else { + testFill = false; + testDraw = true; + linewidths = drawlinewidths; + } + useAA = ((i & 2) != 0); + strokePure = ((i & 4) != 0); + for (float w : linewidths) { + lw = w; + runSuiteTests(ar, count); + } + } + } + } + } + + public static void runSuiteTests(AnnotatedRenderOp ar, int count) { + if (verbose) { + System.out.print("Running "); + System.out.print(testFill ? "Fill " : "Draw "); + System.out.print(BaseName(ar)); + if (useAA) { + System.out.print(" AA"); + } + if (strokePure) { + System.out.print(" Pure"); + } + if (lw != 1.0f) { + System.out.print(" lw="+lw); + } + if (rot != 0.0f) { + System.out.print(" rot="+rot); + } + System.out.println(); + } + initGCs(); + runRandomTests(ar, count); + disposeGCs(); + } + + public static String BaseName(AnnotatedRenderOp ar) { + String s = ar.toString(); + int leftparen = s.indexOf('('); + if (leftparen >= 0) { + s = s.substring(0, leftparen); + } + return s; + } + + public static void runRandomTests(AnnotatedRenderOp ar, int count) { + for (int i = 0; i < count; i++) { + ar.randomize(); + if (testDraw) { + test(ar, false); + } + if (testFill) { + test(ar, true); + } + } + } + + public static void initImages() { + imgref = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB); + imgtst = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB); + grefclear = imgref.createGraphics(); + gtstclear = imgtst.createGraphics(); + grefclear.setColor(Color.white); + gtstclear.setColor(Color.white); + } + + public static void initGCs() { + grefrender = imgref.createGraphics(); + gtstrender = imgtst.createGraphics(); + gtstrender.clipRect(10, 10, 20, 20); + grefrender.setColor(Color.blue); + gtstrender.setColor(Color.blue); + if (lw != 1.0f) { + BasicStroke bs = new BasicStroke(lw); + grefrender.setStroke(bs); + gtstrender.setStroke(bs); + } + if (rot != 0.0) { + double rotrad = Math.toRadians(rot); + grefrender.rotate(rotrad, 20, 20); + gtstrender.rotate(rotrad, 20, 20); + } + if (strokePure) { + grefrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_PURE); + gtstrender.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, + RenderingHints.VALUE_STROKE_PURE); + } + if (useAA) { + grefrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + gtstrender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + maxerr = 1; + } + } + + public static void disposeGCs() { + grefrender.dispose(); + gtstrender.dispose(); + grefrender = gtstrender = null; + } + + public static void parseAndRun(InputStream in) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + String str; + while ((str = br.readLine()) != null) { + if (str.startsWith("Stroked ") || str.startsWith("Filled ")) { + parseTest(str); + continue; + } + if (str.startsWith("Running ")) { + continue; + } + if (str.startsWith("Failed: ")) { + continue; + } + if (str.indexOf(" out of ") > 0 && + str.indexOf(" tests failed...") > 0) + { + continue; + } + if (str.indexOf(" tests had critical errors") > 0) { + continue; + } + System.err.println("Unparseable line: "+str); + } + } + + public static void parseTest(String origstr) { + String str = origstr; + boolean isfill = false; + useAA = strokePure = false; + lw = 1.0f; + rot = 0.0; + if (str.startsWith("Stroked ")) { + str = str.substring(8); + isfill = false; + } else if (str.startsWith("Filled ")) { + str = str.substring(7); + isfill = true; + } else { + System.err.println("Unparseable test line: "+origstr); + } + if (str.startsWith("AA ")) { + str = str.substring(3); + useAA = true; + } + if (str.startsWith("Pure ")) { + str = str.substring(5); + strokePure = true; + } + if (str.startsWith("Lw=")) { + int index = str.indexOf(' ', 3); + if (index > 0) { + lw = Float.parseFloat(str.substring(3, index)); + str = str.substring(index+1); + } + } + if (str.startsWith("Rot=")) { + int index = str.indexOf(' ', 4); + if (index > 0) { + rot = Double.parseDouble(str.substring(4, index)); + str = str.substring(index+1); + } + } + AnnotatedRenderOp ar = AnnotatedRenderOp.parse(str); + if (ar != null) { + initGCs(); + test(ar, isfill); + disposeGCs(); + } else { + System.err.println("Unparseable test line: "+origstr); + } + } + + public static void test(AnnotatedRenderOp ar, boolean isfill) { + grefclear.fillRect(0, 0, 40, 40); + gtstclear.fillRect(0, 0, 40, 40); + if (isfill) { + ar.fill(grefrender); + ar.fill(gtstrender); + } else { + ar.draw(grefrender); + ar.draw(gtstrender); + } + check(imgref, imgtst, ar, isfill); + } + + public static int[] getData(BufferedImage img) { + Raster r = img.getRaster(); + DataBufferInt dbi = (DataBufferInt) r.getDataBuffer(); + return dbi.getData(); + } + + public static int getScan(BufferedImage img) { + Raster r = img.getRaster(); + SinglePixelPackedSampleModel sppsm = + (SinglePixelPackedSampleModel) r.getSampleModel(); + return sppsm.getScanlineStride(); + } + + public static int getOffset(BufferedImage img) { + Raster r = img.getRaster(); + SinglePixelPackedSampleModel sppsm = + (SinglePixelPackedSampleModel) r.getSampleModel(); + return sppsm.getOffset(-r.getSampleModelTranslateX(), + -r.getSampleModelTranslateY()); + } + + final static int opaque = 0xff000000; + final static int whitergb = Color.white.getRGB(); + + public static final int maxdiff(int rgb1, int rgb2) { + int maxd = 0; + for (int i = 0; i < 32; i += 8) { + int c1 = (rgb1 >> i) & 0xff; + int c2 = (rgb2 >> i) & 0xff; + int d = Math.abs(c1-c2); + if (maxd < d) { + maxd = d; + } + } + return maxd; + } + + public static void check(BufferedImage imgref, BufferedImage imgtst, + AnnotatedRenderOp ar, boolean wasfill) + { + numtests++; + int dataref[] = getData(imgref); + int datatst[] = getData(imgtst); + int scanref = getScan(imgref); + int scantst = getScan(imgtst); + int offref = getOffset(imgref); + int offtst = getOffset(imgtst); + + // We want to check for errors outside the clip at a higher + // priority than errors involving different pixels touched + // inside the clip. + + // Check above clip + if (check(ar, wasfill, + null, 0, 0, + datatst, scantst, offtst, + 0, 0, 40, 10)) + { + return; + } + // Check below clip + if (check(ar, wasfill, + null, 0, 0, + datatst, scantst, offtst, + 0, 30, 40, 40)) + { + return; + } + // Check left of clip + if (check(ar, wasfill, + null, 0, 0, + datatst, scantst, offtst, + 0, 10, 10, 30)) + { + return; + } + // Check right of clip + if (check(ar, wasfill, + null, 0, 0, + datatst, scantst, offtst, + 30, 10, 40, 30)) + { + return; + } + // Check inside clip + check(ar, wasfill, + dataref, scanref, offref, + datatst, scantst, offtst, + 10, 10, 30, 30); + } + + public static boolean check(AnnotatedRenderOp ar, boolean wasfill, + int dataref[], int scanref, int offref, + int datatst[], int scantst, int offtst, + int x0, int y0, int x1, int y1) + { + offref += scanref * y0; + offtst += scantst * y0; + for (int y = y0; y < y1; y++) { + for (int x = x0; x < x1; x++) { + boolean failed; + String reason; + int rgbref; + int rgbtst; + + rgbtst = datatst[offtst+x] | opaque; + if (dataref == null) { + /* Outside of clip, must be white, no error tolerance */ + rgbref = whitergb; + failed = (rgbtst != rgbref); + reason = "stray pixel rendered outside of clip"; + } else { + /* Inside of clip, check for maxerr delta in components */ + rgbref = dataref[offref+x] | opaque; + failed = (rgbref != rgbtst && + maxdiff(rgbref, rgbtst) > maxerr); + reason = "different pixel rendered inside clip"; + } + if (failed) { + if (dataref == null) { + numerrors++; + } + if (wasfill) { + numfillfailures++; + } else { + numstrokefailures++; + } + if (!silent) { + System.out.println("Failed: "+reason+" at "+x+", "+y+ + " ["+Integer.toHexString(rgbref)+ + " != "+Integer.toHexString(rgbtst)+ + "]"); + System.out.print(wasfill ? "Filled " : "Stroked "); + if (useAA) System.out.print("AA "); + if (strokePure) System.out.print("Pure "); + if (lw != 1) System.out.print("Lw="+lw+" "); + if (rot != 0) System.out.print("Rot="+rot+" "); + System.out.println(ar); + } + if (showErrors) { + show(imgref, imgtst); + } + return true; + } + } + offref += scanref; + offtst += scantst; + } + return false; + } + + static ErrorWindow errw; + + public static void show(BufferedImage imgref, BufferedImage imgtst) { + ErrorWindow errw = new ErrorWindow(); + errw.setImages(imgref, imgtst); + errw.setVisible(true); + errw.waitForHide(); + errw.dispose(); + } + + public static class Cubic extends AnnotatedShapeOp { + public static Cubic tryparse(String str) { + str = str.trim(); + if (!str.startsWith("Cubic(")) { + return null; + } + str = str.substring(6); + double coords[] = new double[8]; + boolean foundparen = false; + for (int i = 0; i < coords.length; i++) { + int index = str.indexOf(","); + if (index < 0) { + if (i < coords.length-1) { + return null; + } + index = str.indexOf(")"); + if (index < 0) { + return null; + } + foundparen = true; + } + String num = str.substring(0, index); + try { + coords[i] = Double.parseDouble(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + } + if (!foundparen || str.length() > 0) { + return null; + } + Cubic c = new Cubic(); + c.cubic.setCurve(coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5], + coords[6], coords[7]); + return c; + } + + private CubicCurve2D cubic = new CubicCurve2D.Double(); + + public void randomize() { + cubic.setCurve(randDblCoord(), randDblCoord(), + randDblCoord(), randDblCoord(), + randDblCoord(), randDblCoord(), + randDblCoord(), randDblCoord()); + } + + public Shape getShape() { + return cubic; + } + + public String toString() { + return ("Cubic("+ + cubic.getX1()+", "+ + cubic.getY1()+", "+ + cubic.getCtrlX1()+", "+ + cubic.getCtrlY1()+", "+ + cubic.getCtrlX2()+", "+ + cubic.getCtrlY2()+", "+ + cubic.getX2()+", "+ + cubic.getY2() + +")"); + } + } + + public static class Quad extends AnnotatedShapeOp { + public static Quad tryparse(String str) { + str = str.trim(); + if (!str.startsWith("Quad(")) { + return null; + } + str = str.substring(5); + double coords[] = new double[6]; + boolean foundparen = false; + for (int i = 0; i < coords.length; i++) { + int index = str.indexOf(","); + if (index < 0) { + if (i < coords.length-1) { + return null; + } + index = str.indexOf(")"); + if (index < 0) { + return null; + } + foundparen = true; + } + String num = str.substring(0, index); + try { + coords[i] = Double.parseDouble(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + } + if (!foundparen || str.length() > 0) { + return null; + } + Quad c = new Quad(); + c.quad.setCurve(coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5]); + return c; + } + + private QuadCurve2D quad = new QuadCurve2D.Double(); + + public void randomize() { + quad.setCurve(randDblCoord(), randDblCoord(), + randDblCoord(), randDblCoord(), + randDblCoord(), randDblCoord()); + } + + public Shape getShape() { + return quad; + } + + public String toString() { + return ("Quad("+ + quad.getX1()+", "+ + quad.getY1()+", "+ + quad.getCtrlX()+", "+ + quad.getCtrlY()+", "+ + quad.getX2()+", "+ + quad.getY2() + +")"); + } + } + + public static class Poly extends AnnotatedShapeOp { + public static Poly tryparse(String str) { + str = str.trim(); + if (!str.startsWith("Poly(")) { + return null; + } + str = str.substring(5); + Polygon p = new Polygon(); + while (true) { + int x, y; + str = str.trim(); + if (str.startsWith(")")) { + str = str.substring(1); + break; + } + if (p.npoints > 0) { + if (str.startsWith(",")) { + str = str.substring(2).trim(); + } else { + return null; + } + } + if (str.startsWith("[")) { + str = str.substring(1); + } else { + return null; + } + int index = str.indexOf(","); + if (index < 0) { + return null; + } + String num = str.substring(0, index); + try { + x = Integer.parseInt(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + index = str.indexOf("]"); + if (index < 0) { + return null; + } + num = str.substring(0, index).trim(); + try { + y = Integer.parseInt(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + p.addPoint(x, y); + } + if (str.length() > 0) { + return null; + } + if (p.npoints < 3) { + return null; + } + return new Poly(p); + } + + private Polygon poly; + + public Poly() { + this.poly = new Polygon(); + } + + private Poly(Polygon p) { + this.poly = p; + } + + public void randomize() { + poly.reset(); + poly.addPoint(randIntCoord(), randIntCoord()); + poly.addPoint(randIntCoord(), randIntCoord()); + poly.addPoint(randIntCoord(), randIntCoord()); + poly.addPoint(randIntCoord(), randIntCoord()); + poly.addPoint(randIntCoord(), randIntCoord()); + } + + public Shape getShape() { + return poly; + } + + public String toString() { + StringBuffer sb = new StringBuffer(100); + sb.append("Poly("); + for (int i = 0; i < poly.npoints; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append("["); + sb.append(poly.xpoints[i]); + sb.append(", "); + sb.append(poly.ypoints[i]); + sb.append("]"); + } + sb.append(")"); + return sb.toString(); + } + } + + public static class Path extends AnnotatedShapeOp { + public static Path tryparse(String str) { + str = str.trim(); + if (!str.startsWith("Path(")) { + return null; + } + str = str.substring(5); + GeneralPath gp = new GeneralPath(); + float coords[] = new float[6]; + int numsegs = 0; + while (true) { + int type; + int n; + str = str.trim(); + if (str.startsWith(")")) { + str = str.substring(1); + break; + } + if (str.startsWith("M[")) { + type = PathIterator.SEG_MOVETO; + n = 2; + } else if (str.startsWith("L[")) { + type = PathIterator.SEG_LINETO; + n = 2; + } else if (str.startsWith("Q[")) { + type = PathIterator.SEG_QUADTO; + n = 4; + } else if (str.startsWith("C[")) { + type = PathIterator.SEG_CUBICTO; + n = 6; + } else if (str.startsWith("E[")) { + type = PathIterator.SEG_CLOSE; + n = 0; + } else { + return null; + } + str = str.substring(2); + if (n == 0) { + if (str.startsWith("]")) { + str = str.substring(1); + } else { + return null; + } + } + for (int i = 0; i < n; i++) { + int index; + if (i < n-1) { + index = str.indexOf(","); + } else { + index = str.indexOf("]"); + } + if (index < 0) { + return null; + } + String num = str.substring(0, index); + try { + coords[i] = Float.parseFloat(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1).trim(); + } + switch (type) { + case PathIterator.SEG_MOVETO: + gp.moveTo(coords[0], coords[1]); + break; + case PathIterator.SEG_LINETO: + gp.lineTo(coords[0], coords[1]); + break; + case PathIterator.SEG_QUADTO: + gp.quadTo(coords[0], coords[1], + coords[2], coords[3]); + break; + case PathIterator.SEG_CUBICTO: + gp.curveTo(coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5]); + break; + case PathIterator.SEG_CLOSE: + gp.closePath(); + break; + } + numsegs++; + } + if (str.length() > 0) { + return null; + } + if (numsegs < 2) { + return null; + } + return new Path(gp); + } + + private GeneralPath path; + + public Path() { + this.path = new GeneralPath(); + } + + private Path(GeneralPath gp) { + this.path = gp; + } + + public void randomize() { + path.reset(); + path.moveTo(randFltCoord(), randFltCoord()); + for (int i = randInt(5)+3; i > 0; --i) { + switch(randInt(5)) { + case 0: + path.moveTo(randFltCoord(), randFltCoord()); + break; + case 1: + path.lineTo(randFltCoord(), randFltCoord()); + break; + case 2: + path.quadTo(randFltCoord(), randFltCoord(), + randFltCoord(), randFltCoord()); + break; + case 3: + path.curveTo(randFltCoord(), randFltCoord(), + randFltCoord(), randFltCoord(), + randFltCoord(), randFltCoord()); + break; + case 4: + path.closePath(); + break; + } + } + } + + public Shape getShape() { + return path; + } + + public String toString() { + StringBuffer sb = new StringBuffer(100); + sb.append("Path("); + PathIterator pi = path.getPathIterator(null); + float coords[] = new float[6]; + boolean first = true; + while (!pi.isDone()) { + int n; + char c; + switch(pi.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + c = 'M'; + n = 2; + break; + case PathIterator.SEG_LINETO: + c = 'L'; + n = 2; + break; + case PathIterator.SEG_QUADTO: + c = 'Q'; + n = 4; + break; + case PathIterator.SEG_CUBICTO: + c = 'C'; + n = 6; + break; + case PathIterator.SEG_CLOSE: + c = 'E'; + n = 0; + break; + default: + throw new InternalError("Unknown segment!"); + } + sb.append(c); + sb.append("["); + for (int i = 0; i < n; i++) { + if (i != 0) { + sb.append(","); + } + sb.append(coords[i]); + } + sb.append("]"); + pi.next(); + } + sb.append(")"); + return sb.toString(); + } + } + + public static class Rect extends AnnotatedShapeOp { + public static Rect tryparse(String str) { + str = str.trim(); + if (!str.startsWith("Rect(")) { + return null; + } + str = str.substring(5); + double coords[] = new double[4]; + boolean foundparen = false; + for (int i = 0; i < coords.length; i++) { + int index = str.indexOf(","); + if (index < 0) { + if (i < coords.length-1) { + return null; + } + index = str.indexOf(")"); + if (index < 0) { + return null; + } + foundparen = true; + } + String num = str.substring(0, index); + try { + coords[i] = Double.parseDouble(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + } + if (!foundparen || str.length() > 0) { + return null; + } + Rect r = new Rect(); + r.rect.setRect(coords[0], coords[1], + coords[2], coords[3]); + return r; + } + + private Rectangle2D rect = new Rectangle2D.Double(); + + public void randomize() { + rect.setRect(randDblCoord(), randDblCoord(), + randDblCoord(), randDblCoord()); + } + + public Shape getShape() { + return rect; + } + + public String toString() { + return ("Rect("+ + rect.getX()+", "+ + rect.getY()+", "+ + rect.getWidth()+", "+ + rect.getHeight() + +")"); + } + } + + public static class Line extends AnnotatedShapeOp { + public static Line tryparse(String str) { + str = str.trim(); + if (!str.startsWith("Line(")) { + return null; + } + str = str.substring(5); + double coords[] = new double[4]; + boolean foundparen = false; + for (int i = 0; i < coords.length; i++) { + int index = str.indexOf(","); + if (index < 0) { + if (i < coords.length-1) { + return null; + } + index = str.indexOf(")"); + if (index < 0) { + return null; + } + foundparen = true; + } + String num = str.substring(0, index); + try { + coords[i] = Double.parseDouble(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + } + if (!foundparen || str.length() > 0) { + return null; + } + Line l = new Line(); + l.line.setLine(coords[0], coords[1], + coords[2], coords[3]); + return l; + } + + private Line2D line = new Line2D.Double(); + + public void randomize() { + line.setLine(randDblCoord(), randDblCoord(), + randDblCoord(), randDblCoord()); + } + + public Shape getShape() { + return line; + } + + public String toString() { + return ("Line("+ + line.getX1()+", "+ + line.getY1()+", "+ + line.getX2()+", "+ + line.getY2() + +")"); + } + } + + public static class RectMethod extends AnnotatedRenderOp { + public static RectMethod tryparse(String str) { + str = str.trim(); + if (!str.startsWith("RectMethod(")) { + return null; + } + str = str.substring(11); + int coords[] = new int[4]; + boolean foundparen = false; + for (int i = 0; i < coords.length; i++) { + int index = str.indexOf(","); + if (index < 0) { + if (i < coords.length-1) { + return null; + } + index = str.indexOf(")"); + if (index < 0) { + return null; + } + foundparen = true; + } + String num = str.substring(0, index).trim(); + try { + coords[i] = Integer.parseInt(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + } + if (!foundparen || str.length() > 0) { + return null; + } + RectMethod rm = new RectMethod(); + rm.rect.setBounds(coords[0], coords[1], + coords[2], coords[3]); + return rm; + } + + private Rectangle rect = new Rectangle(); + + public void randomize() { + rect.setBounds(randIntCoord(), randIntCoord(), + randIntCoord(), randIntCoord()); + } + + public void fill(Graphics2D g2d) { + g2d.fillRect(rect.x, rect.y, rect.width, rect.height); + } + + public void draw(Graphics2D g2d) { + g2d.drawRect(rect.x, rect.y, rect.width, rect.height); + } + + public String toString() { + return ("RectMethod("+ + rect.x+", "+ + rect.y+", "+ + rect.width+", "+ + rect.height + +")"); + } + } + + public static class LineMethod extends AnnotatedRenderOp { + public static LineMethod tryparse(String str) { + str = str.trim(); + if (!str.startsWith("LineMethod(")) { + return null; + } + str = str.substring(11); + int coords[] = new int[4]; + boolean foundparen = false; + for (int i = 0; i < coords.length; i++) { + int index = str.indexOf(","); + if (index < 0) { + if (i < coords.length-1) { + return null; + } + index = str.indexOf(")"); + if (index < 0) { + return null; + } + foundparen = true; + } + String num = str.substring(0, index).trim(); + try { + coords[i] = Integer.parseInt(num); + } catch (NumberFormatException nfe) { + return null; + } + str = str.substring(index+1); + } + if (!foundparen || str.length() > 0) { + return null; + } + LineMethod lm = new LineMethod(); + lm.line = coords; + return lm; + } + + private int line[] = new int[4]; + + public void randomize() { + line[0] = randIntCoord(); + line[1] = randIntCoord(); + line[2] = randIntCoord(); + line[3] = randIntCoord(); + } + + public void fill(Graphics2D g2d) { + } + + public void draw(Graphics2D g2d) { + g2d.drawLine(line[0], line[1], line[2], line[3]); + } + + public String toString() { + return ("LineMethod("+ + line[0]+", "+ + line[1]+", "+ + line[2]+", "+ + line[3] + +")"); + } + } + + public static class ErrorWindow extends Frame { + ImageCanvas unclipped; + ImageCanvas reference; + ImageCanvas actual; + ImageCanvas diff; + + public ErrorWindow() { + super("Error Comparison Window"); + + unclipped = new ImageCanvas(); + reference = new ImageCanvas(); + actual = new ImageCanvas(); + diff = new ImageCanvas(); + + setLayout(new SmartGridLayout(0, 2, 5, 5)); + addImagePanel(unclipped, "Unclipped rendering"); + addImagePanel(reference, "Clipped reference"); + addImagePanel(actual, "Actual clipped"); + addImagePanel(diff, "Difference"); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + setVisible(false); + } + }); + } + + public void addImagePanel(ImageCanvas ic, String label) { + add(ic); + add(new Label(label)); + } + + public void setImages(BufferedImage imgref, BufferedImage imgtst) { + unclipped.setImage(imgref); + reference.setReference(imgref); + actual.setImage(imgtst); + diff.setDiff(reference.getImage(), imgtst); + invalidate(); + pack(); + repaint(); + } + + public void setVisible(boolean vis) { + super.setVisible(vis); + synchronized (this) { + notifyAll(); + } + } + + public synchronized void waitForHide() { + while (isShowing()) { + try { + wait(); + } catch (InterruptedException e) { + System.exit(2); + } + } + } + } + + public static class SmartGridLayout implements LayoutManager { + int rows; + int cols; + int hgap; + int vgap; + + public SmartGridLayout(int r, int c, int h, int v) { + this.rows = r; + this.cols = c; + this.hgap = h; + this.vgap = v; + } + + public void addLayoutComponent(String name, Component comp) { + } + + public void removeLayoutComponent(Component comp) { + } + + public int[][] getGridSizes(Container parent, boolean min) { + int ncomponents = parent.getComponentCount(); + int nrows = rows; + int ncols = cols; + + if (nrows > 0) { + ncols = (ncomponents + nrows - 1) / nrows; + } else { + nrows = (ncomponents + ncols - 1) / ncols; + } + int widths[] = new int[ncols+1]; + int heights[] = new int[nrows+1]; + int x = 0; + int y = 0; + for (int i = 0 ; i < ncomponents ; i++) { + Component comp = parent.getComponent(i); + Dimension d = (min + ? comp.getMinimumSize() + : comp.getPreferredSize()); + if (widths[x] < d.width) { + widths[x] = d.width; + } + if (heights[y] < d.height) { + heights[y] = d.height; + } + x++; + if (x >= ncols) { + x = 0; + y++; + } + } + for (int i = 0; i < ncols; i++) { + widths[ncols] += widths[i]; + } + for (int i = 0; i < nrows; i++) { + heights[nrows] += heights[i]; + } + return new int[][] { widths, heights }; + } + + public Dimension getSize(Container parent, boolean min) { + int sizes[][] = getGridSizes(parent, min); + int widths[] = sizes[0]; + int heights[] = sizes[1]; + int nrows = heights.length-1; + int ncols = widths.length-1; + int w = widths[ncols]; + int h = heights[nrows]; + Insets insets = parent.getInsets(); + return new Dimension(insets.left+insets.right + w+(ncols+1)*hgap, + insets.top+insets.bottom + h+(nrows+1)*vgap); + } + + public Dimension preferredLayoutSize(Container parent) { + return getSize(parent, false); + } + + public Dimension minimumLayoutSize(Container parent) { + return getSize(parent, true); + } + + public void layoutContainer(Container parent) { + int pref[][] = getGridSizes(parent, false); + int min[][] = getGridSizes(parent, true); + int minwidths[] = min[0]; + int minheights[] = min[1]; + int prefwidths[] = pref[0]; + int prefheights[] = pref[1]; + int nrows = minheights.length - 1; + int ncols = minwidths.length - 1; + Insets insets = parent.getInsets(); + int w = parent.getWidth() - insets.left - insets.right; + int h = parent.getHeight() - insets.top - insets.bottom; + w = w - (ncols+1)*hgap; + h = h - (nrows+1)*vgap; + int widths[] = calculateSizes(w, ncols, minwidths, prefwidths); + int heights[] = calculateSizes(h, nrows, minheights, prefheights); + int ncomponents = parent.getComponentCount(); + int x = insets.left + hgap; + int y = insets.top + vgap; + int r = 0; + int c = 0; + for (int i = 0; i < ncomponents; i++) { + parent.getComponent(i).setBounds(x, y, widths[c], heights[r]); + x += widths[c++] + hgap; + if (c >= ncols) { + c = 0; + x = insets.left + hgap; + y += heights[r++] + vgap; + if (r >= nrows) { + // just in case + break; + } + } + } + } + + public static int[] calculateSizes(int total, int num, + int minsizes[], int prefsizes[]) + { + if (total <= minsizes[num]) { + return minsizes; + } + if (total >= prefsizes[num]) { + return prefsizes; + } + int sizes[] = new int[total]; + int prevhappy = 0; + int nhappy = 0; + int happysize = 0; + do { + int addsize = (total - happysize) / (num - nhappy); + happysize = 0; + for (int i = 0; i < num; i++) { + if (sizes[i] >= prefsizes[i] || + minsizes[i] + addsize > prefsizes[i]) + { + happysize += (sizes[i] = prefsizes[i]); + nhappy++; + } else { + sizes[i] = minsizes[i] + addsize; + } + } + } while (nhappy < num && nhappy > prevhappy); + return sizes; + } + } + + public static class ImageCanvas extends Canvas { + BufferedImage image; + + public void setImage(BufferedImage img) { + this.image = img; + } + + public BufferedImage getImage() { + return image; + } + + public void checkImage(int w, int h) { + if (image == null || + image.getWidth() < w || + image.getHeight() < h) + { + image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + } + } + + public void setReference(BufferedImage img) { + checkImage(img.getWidth(), img.getHeight()); + Graphics g = image.createGraphics(); + g.drawImage(img, 0, 0, null); + g.setColor(Color.white); + g.fillRect(0, 0, 30, 10); + g.fillRect(30, 0, 10, 30); + g.fillRect(10, 30, 30, 10); + g.fillRect(0, 10, 10, 30); + g.dispose(); + } + + public void setDiff(BufferedImage imgref, BufferedImage imgtst) { + int w = Math.max(imgref.getWidth(), imgtst.getWidth()); + int h = Math.max(imgref.getHeight(), imgtst.getHeight()); + checkImage(w, h); + Graphics g = image.createGraphics(); + g.drawImage(imgref, 0, 0, null); + g.setXORMode(Color.white); + g.drawImage(imgtst, 0, 0, null); + g.setPaintMode(); + g.setColor(new Color(1f, 1f, 0f, 0.25f)); + g.fillRect(10, 10, 20, 20); + g.setColor(new Color(1f, 0f, 0f, 0.25f)); + g.fillRect(0, 0, 30, 10); + g.fillRect(30, 0, 10, 30); + g.fillRect(10, 30, 30, 10); + g.fillRect(0, 10, 10, 30); + g.dispose(); + } + + public Dimension getPreferredSize() { + if (image == null) { + return new Dimension(); + } else { + return new Dimension(image.getWidth(), image.getHeight()); + } + } + + public void paint(Graphics g) { + g.drawImage(image, 0, 0, null); + } + } +} From cfe2f7eb5d0d1abad7e5262091282592f1f8b62f Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 14 Dec 2010 14:17:20 -0800 Subject: [PATCH 05/94] 6999891: DefaultFileManager incorrect Reviewed-by: darcy --- .../tools/javac/file/JavacFileManager.java | 5 +- .../filer/TestValidRelativeNames.java | 136 ++++++++++++++++++ 2 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javac/processing/filer/TestValidRelativeNames.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java index 156b16d104b..230509bf3a7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -869,8 +869,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil return false; if (!path.equals(uri.getPath())) // implicitly checks for embedded . and .. return false; - char first = path.charAt(0); - return first != '.' && first != '/'; + if (path.startsWith("/") || path.startsWith("./") || path.startsWith("../")) + return false; + return true; } // Convenience method diff --git a/langtools/test/tools/javac/processing/filer/TestValidRelativeNames.java b/langtools/test/tools/javac/processing/filer/TestValidRelativeNames.java new file mode 100644 index 00000000000..67d44e27734 --- /dev/null +++ b/langtools/test/tools/javac/processing/filer/TestValidRelativeNames.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6999891 + * @summary Test valid relative names for Filer.createResource and Filer.getResource + * @library ../../lib + * @build JavacTestingAbstractProcessor + * @compile TestValidRelativeNames.java + * @compile/process -processor TestValidRelativeNames -Amode=create java.lang.Object + * @compile/process -processor TestValidRelativeNames -Amode=get java.lang.Object + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic; +import javax.tools.StandardLocation; + +@SupportedOptions("mode") +public class TestValidRelativeNames extends JavacTestingAbstractProcessor { + enum Kind { READER_WRITER, INPUT_OUTPUT_STREAM }; + + static final String[] validRelativeNames = { + "foo", "foo.bar", ".foo", ".foo.bar", "foodir/bar", "foodir/.bar" + }; + + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + String mode = options.get("mode"); + for (String relativeBase: validRelativeNames) { + for (Kind kind: Kind.values()) { + if (mode.equals("create")) + testCreate(relativeBase, kind); + else + testGet(relativeBase, kind); + } + } + } + + return true; + } + + void testCreate(String relativeBase, Kind kind) { + String relative = getRelative(relativeBase, kind); + System.out.println("test create relative path: " + relative + ", kind: " + kind); + try { + switch (kind) { + case READER_WRITER: + try (Writer writer = filer.createResource( + StandardLocation.CLASS_OUTPUT, "", relative).openWriter()) { + writer.write(relative); + } + break; + + case INPUT_OUTPUT_STREAM: + try (OutputStream out = filer.createResource( + StandardLocation.CLASS_OUTPUT, "", relative).openOutputStream()) { + out.write(relative.getBytes()); + } + break; + } + } catch (Exception e) { + messager.printMessage(Diagnostic.Kind.ERROR, + "relative path: " + relative + ", kind: " + kind + ", unexpected exception: " + e); + } + } + + void testGet(String relativeBase, Kind kind) { + String relative = getRelative(relativeBase, kind); + System.out.println("test get relative path: " + relative + ", kind: " + kind); + try { + switch (kind) { + case READER_WRITER: + try (Reader reader = new BufferedReader(filer.getResource( + StandardLocation.CLASS_OUTPUT, "", relative).openReader(true))) { + StringBuilder sb = new StringBuilder(); + char[] buf = new char[1024]; + int n; + while ((n = reader.read(buf, 0, buf.length)) > 0) + sb.append(new String(buf, 0, n)); + if (!sb.toString().equals(relative)) { + messager.printMessage(Diagnostic.Kind.ERROR, "unexpected content: " + sb); + } + } + break; + + case INPUT_OUTPUT_STREAM: + try (InputStream in = new DataInputStream(filer.getResource( + StandardLocation.CLASS_OUTPUT, "", relative).openInputStream())) { + StringBuilder sb = new StringBuilder(); + byte[] buf = new byte[1024]; + int n; + while ((n = in.read(buf, 0, buf.length)) > 0) + sb.append(new String(buf, 0, n)); + if (!sb.toString().equals(relative)) { + messager.printMessage(Diagnostic.Kind.ERROR, "unexpected content: " + sb); + } + } + break; + } + } catch (Exception e) { + messager.printMessage(Diagnostic.Kind.ERROR, + "relative path: " + relative + ", kind: " + kind + ", unexpected exception: " + e); + } + } + + String getRelative(String relativeBase, Kind kind) { + String suffix = (kind == Kind.READER_WRITER ? "RW" : "IOS"); + return relativeBase.replace("foo", "foo" + suffix); + } +} + From f58190736edebc08d7281e4b0a889063f8e5577e Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Wed, 15 Dec 2010 11:38:34 +0900 Subject: [PATCH 06/94] 6990037: font warnings in the build, missing fonts Reviewed-by: peytoia --- jdk/make/sun/awt/Makefile | 6 +- .../classes/sun/awt/FontConfiguration.java | 133 +++++++++--------- 2 files changed, 69 insertions(+), 70 deletions(-) diff --git a/jdk/make/sun/awt/Makefile b/jdk/make/sun/awt/Makefile index e62c4ebc915..15e1fd8f26b 100644 --- a/jdk/make/sun/awt/Makefile +++ b/jdk/make/sun/awt/Makefile @@ -175,6 +175,10 @@ endif include $(BUILDDIR)/common/Mapfile-vers.gmk include $(BUILDDIR)/common/Library.gmk +COMPILEFONTCONFIG_FLAGS = +ifdef ALT_COMPILEFONTCONFIG_FLAGS + COMPILEFONTCONFIG_FLAGS += $(ALT_COMPILEFONTCONFIG_FLAGS) +endif build: fontconfigs @@ -406,7 +410,7 @@ COMPILEFONTCONFIG_JARFILE = $(BUILDTOOLJARDIR)/compilefontconfig.jar $(LIBDIR)/%.bfc: $(FONTCONFIGS_SRC)/$(FONTCONFIGS_SRC_PREFIX)%.properties \ $(COMPILEFONTCONFIG_JARFILE) $(prep-target) - $(BOOT_JAVA_CMD) -jar $(COMPILEFONTCONFIG_JARFILE) $< $@ + $(BOOT_JAVA_CMD) -jar $(COMPILEFONTCONFIG_JARFILE) $(COMPILEFONTCONFIG_FLAGS) $< $@ $(install-module-file) $(call chmod-file, 444) @$(java-vm-cleanup) diff --git a/jdk/src/share/classes/sun/awt/FontConfiguration.java b/jdk/src/share/classes/sun/awt/FontConfiguration.java index a2593cc2ff5..ba8f6e56a01 100644 --- a/jdk/src/share/classes/sun/awt/FontConfiguration.java +++ b/jdk/src/share/classes/sun/awt/FontConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,10 +37,10 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; -import java.util.Iterator; import java.util.Locale; import java.util.Map.Entry; import java.util.Properties; @@ -329,6 +329,8 @@ public abstract class FontConfiguration { * tables. */ public static void saveBinary(OutputStream out) throws IOException { + sanityCheck(); + DataOutputStream dataOut = new DataOutputStream(out); writeShortTable(dataOut, head); writeShortTable(dataOut, table_scriptIDs); @@ -350,7 +352,6 @@ public abstract class FontConfiguration { if (verbose) { dump(); } - sanityCheck(); } //private static boolean loadingProperties; @@ -1343,6 +1344,11 @@ public abstract class FontConfiguration { private static short[] table_stringIDs; private static char[] table_stringTable; + /** + * Checks consistencies of complied fontconfig data. This method + * is called only at the build-time from + * build.tools.compilefontconfig.CompileFontConfig. + */ private static void sanityCheck() { int errors = 0; @@ -1358,12 +1364,20 @@ public abstract class FontConfiguration { //componentFontNameID starts from "1" for (int ii = 1; ii < table_filenames.length; ii++) { if (table_filenames[ii] == -1) { - System.out.println("\n Warning: " - + " entry is missing!!!"); - if (!osName.contains("Linux")) { + // The corresponding finename entry for a component + // font name is mandatory on Windows, but it's + // optional on Solaris and Linux. + if (osName.contains("Windows")) { + System.err.println("\n Error: entry is missing!!!"); errors++; + } else { + if (verbose && !isEmpty(table_filenames)) { + System.err.println("\n Note: 'filename' entry is undefined for \"" + + getString(table_componentFontNameIDs[ii]) + + "\""); + } } } } @@ -1382,7 +1396,7 @@ public abstract class FontConfiguration { int jj = iii * NUM_STYLES + iij; short ffid = table_scriptFonts[fid + jj]; if (ffid == 0) { - System.out.println("\n Error: <" + System.err.println("\n Error: <" + getFontName(iii) + "." + getStyleName(iij) + "." + getString(table_scriptIDs[ii]) @@ -1402,7 +1416,7 @@ public abstract class FontConfiguration { script.contains("symbol")) { continue; } - System.out.println("\nError: " + System.err.println("\nError: " + " entry is missing!!!"); @@ -1411,13 +1425,21 @@ public abstract class FontConfiguration { } } if (errors != 0) { - System.out.println("!!THERE ARE " + errors + " ERROR(S) IN " + System.err.println("!!THERE ARE " + errors + " ERROR(S) IN " + "THE FONTCONFIG FILE, PLEASE CHECK ITS CONTENT!!\n"); System.exit(1); - } } + private static boolean isEmpty(short[] a) { + for (short s : a) { + if (s != -1) { + return false; + } + } + return true; + } + //dump the fontconfig data tables private static void dump() { System.out.println("\n----Head Table------------"); @@ -1652,20 +1674,16 @@ public abstract class FontConfiguration { private static void writeShortTable(DataOutputStream out, short[] data) throws IOException { - for (int i = 0; i < data.length; i++) { - out.writeShort(data[i]); + for (short val : data) { + out.writeShort(val); } } - private static short[] toList(HashMap map) { + private static short[] toList(HashMap map) { short[] list = new short[map.size()]; - for (int i = 0; i < list.length; i++) { - list[i] = -1; - } - Iterator iterator = map.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); - list[entry.getValue().shortValue()] = getStringID(entry.getKey()); + Arrays.fill(list, (short) -1); + for (Entry entry : map.entrySet()) { + list[entry.getValue()] = getStringID(entry.getKey()); } return list; } @@ -1763,25 +1781,19 @@ public abstract class FontConfiguration { int len = table_scriptIDs.length + scriptFonts.size() * 20; table_scriptFonts = new short[len]; - Iterator iterator = scriptAllfonts.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); - table_scriptFonts[entry.getKey().intValue()] = (short)entry.getValue().shortValue(); + for (Entry entry : scriptAllfonts.entrySet()) { + table_scriptFonts[entry.getKey().intValue()] = entry.getValue(); } int off = table_scriptIDs.length; - iterator = scriptFonts.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); + for (Entry entry : scriptFonts.entrySet()) { table_scriptFonts[entry.getKey().intValue()] = (short)-off; Short[] v = entry.getValue(); - int i = 0; - while (i < 20) { + for (int i = 0; i < 20; i++) { if (v[i] != null) { - table_scriptFonts[off++] = v[i].shortValue(); + table_scriptFonts[off++] = v[i]; } else { table_scriptFonts[off++] = 0; } - i++; } } @@ -1792,9 +1804,7 @@ public abstract class FontConfiguration { //(3) sequences elcID -> XXXX[1|5] -> scriptID[] head[INDEX_sequences] = (short)(head[INDEX_elcIDs] + table_elcIDs.length); table_sequences = new short[elcIDs.size() * NUM_FONTS]; - iterator = sequences.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); + for (Entry entry : sequences.entrySet()) { //table_sequences[entry.getKey().intValue()] = (short)-off; int k = entry.getKey().intValue(); short[] v = entry.getValue(); @@ -1827,31 +1837,24 @@ public abstract class FontConfiguration { //(6)componentFontNameID -> filenameID head[INDEX_filenames] = (short)(head[INDEX_componentFontNameIDs] + table_componentFontNameIDs.length); table_filenames = new short[table_componentFontNameIDs.length]; - for (int i = 0; i < table_filenames.length; i++) { - table_filenames[i] = -1; - } - iterator = filenames.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); - table_filenames[entry.getKey().shortValue()] = entry.getValue().shortValue(); + Arrays.fill(table_filenames, (short) -1); + + for (Entry entry : filenames.entrySet()) { + table_filenames[entry.getKey()] = entry.getValue(); } //(7)scriptID-> awtfontpath //the paths are stored as scriptID -> stringID in awtfontpahts head[INDEX_awtfontpaths] = (short)(head[INDEX_filenames] + table_filenames.length); table_awtfontpaths = new short[table_scriptIDs.length]; - iterator = awtfontpaths.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); - table_awtfontpaths[entry.getKey().shortValue()] = entry.getValue().shortValue(); + for (Entry entry : awtfontpaths.entrySet()) { + table_awtfontpaths[entry.getKey()] = entry.getValue(); } //(8)exclusions head[INDEX_exclusions] = (short)(head[INDEX_awtfontpaths] + table_awtfontpaths.length); table_exclusions = new short[scriptIDs.size()]; - iterator = exclusions.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); + for (Entry entry : exclusions.entrySet()) { int[] exI = entry.getValue(); char[] exC = new char[exI.length * 2]; int j = 0; @@ -1859,17 +1862,15 @@ public abstract class FontConfiguration { exC[j++] = (char) (exI[i] >> 16); exC[j++] = (char) (exI[i] & 0xffff); } - table_exclusions[entry.getKey().shortValue()] = getStringID(new String (exC)); + table_exclusions[entry.getKey()] = getStringID(new String (exC)); } //(9)proportionals head[INDEX_proportionals] = (short)(head[INDEX_exclusions] + table_exclusions.length); table_proportionals = new short[proportionals.size() * 2]; - iterator = proportionals.entrySet().iterator(); int j = 0; - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); - table_proportionals[j++] = entry.getKey().shortValue(); - table_proportionals[j++] = entry.getValue().shortValue(); + for (Entry entry : proportionals.entrySet()) { + table_proportionals[j++] = entry.getKey(); + table_proportionals[j++] = entry.getValue(); } //(10) see (1) for info, the only difference is "xxx.motif" @@ -1878,22 +1879,18 @@ public abstract class FontConfiguration { len = table_scriptIDs.length + scriptFontsMotif.size() * 20; table_scriptFontsMotif = new short[len]; - iterator = scriptAllfontsMotif.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); + for (Entry entry : scriptAllfontsMotif.entrySet()) { table_scriptFontsMotif[entry.getKey().intValue()] = - (short)entry.getValue().shortValue(); + (short)entry.getValue(); } off = table_scriptIDs.length; - iterator = scriptFontsMotif.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); + for (Entry entry : scriptFontsMotif.entrySet()) { table_scriptFontsMotif[entry.getKey().intValue()] = (short)-off; Short[] v = entry.getValue(); int i = 0; while (i < 20) { if (v[i] != null) { - table_scriptFontsMotif[off++] = v[i].shortValue(); + table_scriptFontsMotif[off++] = v[i]; } else { table_scriptFontsMotif[off++] = 0; } @@ -1907,12 +1904,10 @@ public abstract class FontConfiguration { //(11)short[] alphabeticSuffix head[INDEX_alphabeticSuffix] = (short)(head[INDEX_scriptFontsMotif] + table_scriptFontsMotif.length); table_alphabeticSuffix = new short[alphabeticSuffix.size() * 2]; - iterator = alphabeticSuffix.entrySet().iterator(); j = 0; - while (iterator.hasNext()) { - Entry entry = (Entry )iterator.next(); - table_alphabeticSuffix[j++] = entry.getKey().shortValue(); - table_alphabeticSuffix[j++] = entry.getValue().shortValue(); + for (Entry entry : alphabeticSuffix.entrySet()) { + table_alphabeticSuffix[j++] = entry.getKey(); + table_alphabeticSuffix[j++] = entry.getValue(); } //(15)short[] fallbackScriptIDs; just put the ID in head From e738b0097aaecb4dfc40c641a22dba2697894cdd Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 14 Dec 2010 23:17:00 -0800 Subject: [PATCH 07/94] 6765546: Wrong sscanf used to parse CompilerOracle command >= 32 characters could lead to crash Reviewed-by: kvn, iveresov --- hotspot/src/share/vm/compiler/compilerOracle.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/compiler/compilerOracle.cpp b/hotspot/src/share/vm/compiler/compilerOracle.cpp index 3bc679fdd92..31464896198 100644 --- a/hotspot/src/share/vm/compiler/compilerOracle.cpp +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp @@ -332,7 +332,7 @@ static OracleCommand parse_command_name(const char * line, int* bytes_read) { "command_names size mismatch"); *bytes_read = 0; - char command[32]; + char command[33]; int result = sscanf(line, "%32[a-z]%n", command, bytes_read); for (uint i = 0; i < ARRAY_SIZE(command_names); i++) { if (strcmp(command, command_names[i]) == 0) { @@ -470,6 +470,12 @@ void CompilerOracle::parse_from_line(char* line) { OracleCommand command = parse_command_name(line, &bytes_read); line += bytes_read; + if (command == UnknownCommand) { + tty->print_cr("CompilerOracle: unrecognized line"); + tty->print_cr(" \"%s\"", original_line); + return; + } + if (command == QuietCommand) { _quiet = true; return; @@ -498,7 +504,7 @@ void CompilerOracle::parse_from_line(char* line) { line += bytes_read; // there might be a signature following the method. // signatures always begin with ( so match that by hand - if (1 == sscanf(line, "%*[ \t](%254[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) { + if (1 == sscanf(line, "%*[ \t](%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) { sig[0] = '('; line += bytes_read; signature = oopFactory::new_symbol_handle(sig, CHECK); From facb1c1b6df72b83784eef0d59143ba48be88d6a Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 15 Dec 2010 06:39:51 -0800 Subject: [PATCH 08/94] 7006564: NPE in javac running test/tools/javac/nio/compileTest/CompileTest.java Reviewed-by: mcimadamore, alanb --- .../classes/com/sun/tools/javac/nio/JavacPathFileManager.java | 3 ++- langtools/test/tools/javac/nio/compileTest/CompileTest.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java index 52672f8185a..1a129354ca2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java @@ -376,7 +376,8 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan new SimpleFileVisitor() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { - if (SourceVersion.isIdentifier(dir.getName().toString())) // JSR 292? + Path name = dir.getName(); + if (name == null || SourceVersion.isIdentifier(name.toString())) // JSR 292? return FileVisitResult.CONTINUE; else return FileVisitResult.SKIP_SUBTREE; diff --git a/langtools/test/tools/javac/nio/compileTest/CompileTest.java b/langtools/test/tools/javac/nio/compileTest/CompileTest.java index b93fbfe9ded..8ec44426c12 100644 --- a/langtools/test/tools/javac/nio/compileTest/CompileTest.java +++ b/langtools/test/tools/javac/nio/compileTest/CompileTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 6906175 6915476 6915497 + * @bug 6906175 6915476 6915497 7006564 * @summary Path-based JavaFileManager * @compile -g HelloPathWorld.java * @run main CompileTest From f5e1bc5ca8ac6b4c2d5719471038b483bf5364a8 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Wed, 15 Dec 2010 19:47:01 +0300 Subject: [PATCH 09/94] 6782574: AffineTransformOp.filter(BufferedImage, BufferedImage) fails with InternalError Reviewed-by: igor, prr --- .../image/SinglePixelPackedSampleModel.java | 34 ++---- .../native/sun/awt/image/awt_parseImage.c | 13 +- .../awt/image/IncorrectSampleMaskTest.java | 113 ++++++++++++++++++ 3 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 jdk/test/java/awt/image/IncorrectSampleMaskTest.java diff --git a/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java b/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java index e7a0f44e787..7ad01270650 100644 --- a/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java +++ b/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java @@ -92,7 +92,8 @@ public class SinglePixelPackedSampleModel extends SampleModel * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands. * Each sample is stored in a data array element in the position of * its corresponding bit mask. Each bit mask must be contiguous and - * masks must not overlap. + * masks must not overlap. Bit masks exceeding data type capacity are + * truncated. * @param dataType The data type for storing samples. * @param w The width (in pixels) of the region of the * image data described. @@ -120,7 +121,8 @@ public class SinglePixelPackedSampleModel extends SampleModel * and a scanline stride equal to scanlineStride data array elements. * Each sample is stored in a data array element in the position of * its corresponding bit mask. Each bit mask must be contiguous and - * masks must not overlap. + * masks must not overlap. Bit masks exceeding data type capacity are + * truncated. * @param dataType The data type for storing samples. * @param w The width (in pixels) of the region of * image data described. @@ -153,11 +155,13 @@ public class SinglePixelPackedSampleModel extends SampleModel this.bitOffsets = new int[numBands]; this.bitSizes = new int[numBands]; + int maxMask = (int)((1L << DataBuffer.getDataTypeSize(dataType)) - 1); + this.maxBitSize = 0; for (int i=0; i>> 1; @@ -243,30 +247,12 @@ public class SinglePixelPackedSampleModel extends SampleModel /** Returns the number of bits per sample for all bands. */ public int[] getSampleSize() { - int mask; - int sampleSize[] = new int [numBands]; - for (int i=0; i>> bitOffsets[i]; - while ((mask & 1) != 0) { - sampleSize[i] ++; - mask = mask >>> 1; - } - } - - return sampleSize; + return bitSizes.clone(); } /** Returns the number of bits per sample for the specified band. */ public int getSampleSize(int band) { - int sampleSize = 0; - int mask = bitMasks[band] >>> bitOffsets[band]; - while ((mask & 1) != 0) { - sampleSize ++; - mask = mask >>> 1; - } - - return sampleSize; + return bitSizes[band]; } /** Returns the offset (in data array elements) of pixel (x,y). diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index 0a50d19755b..b569828f5f6 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -178,7 +178,7 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { jnbits = (*env)->GetObjectField(env, rasterP->jsampleModel, g_SPPSMnBitsID); if (jmask == NULL || joffs == NULL || jnbits == NULL || - rasterP->sppsm.maxBitSize < 0 || rasterP->sppsm.maxBitSize > 8) + rasterP->sppsm.maxBitSize < 0) { JNU_ThrowInternalError(env, "Can't grab SPPSM fields"); return -1; @@ -280,6 +280,17 @@ int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { rasterP->chanOffsets); } + /* additioanl check for sppsm fields validity: make sure that + * size of raster samples doesn't exceed the data type cpacity. + */ + if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */ + rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */ + rasterP->sppsm.maxBitSize > (rasterP->dataSize * 8)) + { + JNU_ThrowInternalError(env, "Raster samples are too big"); + return -1; + } + #if 0 fprintf(stderr,"---------------------\n"); fprintf(stderr,"Width : %d\n",rasterP->width); diff --git a/jdk/test/java/awt/image/IncorrectSampleMaskTest.java b/jdk/test/java/awt/image/IncorrectSampleMaskTest.java new file mode 100644 index 00000000000..bfd88cc6607 --- /dev/null +++ b/jdk/test/java/awt/image/IncorrectSampleMaskTest.java @@ -0,0 +1,113 @@ +/* + * 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 6782574 + * @summary Test verifies that incorrect sample masks are correctly handled + * by the constructor of the SinglePixelPackedSampleModel class + * and do not cause internal error in the medialib glue code. + * + * @run main IncorrectSampleMaskTest + */ + +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImageOp; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferUShort; +import java.awt.image.Raster; +import java.awt.image.RasterOp; +import java.awt.image.WritableRaster; +import java.awt.image.SinglePixelPackedSampleModel; + +public class IncorrectSampleMaskTest { + public static void main(String[] args) { + int[] dataTypes = new int[] { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_USHORT, + DataBuffer.TYPE_INT }; + + for (int type : dataTypes) { + doTest(type); + } + } + + private static final int w = 100; + private static final int h = 100; + + private static AffineTransform at = + AffineTransform.getScaleInstance(0.5, 0.5); + + private static RasterOp op = + new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + + private static void doTest(int dataType) { + int maxSize = DataBuffer.getDataTypeSize(dataType); + System.out.println("Type size: " + maxSize); + + int theMask = (int)(1L << (maxSize + 2)) - 1; + System.out.printf("theMask=%x\n", theMask); + + SinglePixelPackedSampleModel sm = + new SinglePixelPackedSampleModel(dataType, w, h, + new int[] { theMask }); + + + int[] sampleSize = sm.getSampleSize(); + for (int s : sampleSize) { + if (s > maxSize) { + throw new RuntimeException("Test failed: sample size is too big:" + s); + } + } + + System.out.println("Test medialib..."); + DataBuffer buf = createDataBuffer(dataType); + + WritableRaster wr = Raster.createWritableRaster(sm, buf, null); + + op.filter(wr, null); + System.out.println("Test PASSED."); + } + + private static DataBuffer createDataBuffer(int type) { + switch (type) { + case DataBuffer.TYPE_BYTE: { + byte[] buf = new byte[w * h]; + return new DataBufferByte(buf, buf.length); + } + case DataBuffer.TYPE_USHORT: { + short[] buf = new short[w * h]; + return new DataBufferUShort(buf, buf.length); + } + case DataBuffer.TYPE_INT: { + int[] buf = new int[w * h]; + return new DataBufferInt(buf, buf.length); + } + default : + throw new RuntimeException("Unsupported data type."); + } + } +} From 92a7b6117113edc7ac02c71ba242092cd9e90400 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Thu, 16 Dec 2010 21:48:30 +0300 Subject: [PATCH 10/94] 6993803: Request to update SplashScreen specification 6984255: Request for java.awt.SplashScreen spec update: mention possibility of having custom "-splash" option 6992416: [Spec clarification request] Is color deviation for splash screen image allowed? 6992833: [Spec clarification request] point (0,0) in SplashScreen.createGraphics() 6993071: java.awt.SplashScreen should mention that no unnecessary distortions to the image are allowed 6993113: [Spec clarification request] getSplashScreen(): null or HeadlessException? 6996439: [Spec clarification request] Is any delay with splashscreen appearance allowed? Update SplashScreen specification Reviewed-by: art --- .../share/classes/java/awt/SplashScreen.java | 76 +++++++++++++------ 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/jdk/src/share/classes/java/awt/SplashScreen.java b/jdk/src/share/classes/java/awt/SplashScreen.java index e02a6172df7..2bbc882fc7f 100644 --- a/jdk/src/share/classes/java/awt/SplashScreen.java +++ b/jdk/src/share/classes/java/awt/SplashScreen.java @@ -33,27 +33,17 @@ import sun.util.logging.PlatformLogger; import sun.awt.image.SunWritableRaster; /** - * The splash screen can be created at application startup, before the + * The splash screen can be displayed at application startup, before the * Java Virtual Machine (JVM) starts. The splash screen is displayed as an - * undecorated window containing an image. You can use GIF, JPEG, and PNG files - * for the image. Animation (for GIF) and transparency (for GIF, PNG) are - * supported. The window is positioned at the center of the screen (the - * position on multi-monitor systems is not specified - it is platform and - * implementation dependent). - * The window is closed automatically as soon as the first window is displayed by - * Swing/AWT (may be also closed manually using the Java API, see below). + * undecorated window containing an image. You can use GIF, JPEG, or PNG files + * for the image. Animation is supported for the GIF format, while transparency + * is supported both for GIF and PNG. The window is positioned at the center + * of the screen. The position on multi-monitor systems is not specified. It is + * platform and implementation dependent. The splash screen window is closed + * automatically as soon as the first window is displayed by Swing/AWT (may be + * also closed manually using the Java API, see below). *

- * There are two ways to show the native splash screen: - *

- *

    - *
  • If your application is run from the command line or from a shortcut, - * use the "-splash:" Java application launcher option to show a splash screen. - *
    - * For example: - *
    - * java -splash:filename.gif Test
    - * 
    - *
  • If your application is packaged in a jar file, you can use the + * If your application is packaged in a jar file, you can use the * "SplashScreen-Image" option in a manifest file to show a splash screen. * Place the image in the jar archive and specify the path in the option. * The path should not have a leading slash. @@ -64,18 +54,39 @@ import sun.awt.image.SunWritableRaster; * Main-Class: Test * SplashScreen-Image: filename.gif * + *

    + * If the Java implementation provides the command-line interface and you run + * your application by using the command line or a shortcut, use the Java + * application launcher option to show a splash screen. The Oracle reference + * implementation allows you to specify the splash screen image location with + * the {@code -splash:} option. + *
    + * For example: + *

    + * java -splash:filename.gif Test
    + * 
    * The command line interface has higher precedence over the manifest * setting. - *
+ *

+ * The splash screen will be displayed as faithfully as possible to present the + * whole splash screen image given the limitations of the target platform and + * display. + *

+ * It is implied that the specified image is presented on the screen "as is", + * i.e. preserving the exact color values as specified in the image file. Under + * certain circumstances, though, the presented image may differ, e.g. when + * applying color dithering to present a 32 bits per pixel (bpp) image on a 16 + * or 8 bpp screen. The native platform display configuration may also affect + * the colors of the displayed image (e.g. color profiles, etc.) *

* The {@code SplashScreen} class provides the API for controlling the splash * screen. This class may be used to close the splash screen, change the splash - * screen image, get the image position/size and paint in the splash screen. It - * cannot be used to create the splash screen; you should use the command line or manifest - * file option for that. + * screen image, get the splash screen native window position/size, and paint + * in the splash screen. It cannot be used to create the splash screen. You + * should use the options provided by the Java implementation for that. *

* This class cannot be instantiated. Only a single instance of this class - * can exist, and it may be obtained using the {@link #getSplashScreen()} + * can exist, and it may be obtained by using the {@link #getSplashScreen()} * static method. In case the splash screen has not been created at * application startup via the command line or manifest file option, * the getSplashScreen method returns null. @@ -91,7 +102,7 @@ public final class SplashScreen { /** * Returns the {@code SplashScreen} object used for - * Java startup splash screen control. + * Java startup splash screen control on systems that support display. * * @throws UnsupportedOperationException if the splash screen feature is not * supported by the current toolkit @@ -219,6 +230,9 @@ public final class SplashScreen { *

* You cannot control the size or position of the splash screen. * The splash screen size is adjusted automatically when the image changes. + *

+ * The image may contain transparent areas, and thus the reported bounds may + * be larger than the visible splash screen image on the screen. * * @return a {@code Rectangle} containing the splash screen bounds * @throws IllegalStateException if the splash screen has already been closed @@ -237,6 +251,9 @@ public final class SplashScreen { *

* You cannot control the size or position of the splash screen. * The splash screen size is adjusted automatically when the image changes. + *

+ * The image may contain transparent areas, and thus the reported size may + * be larger than the visible splash screen image on the screen. * * @return a {@link Dimension} object indicating the splash screen size * @throws IllegalStateException if the splash screen has already been closed @@ -254,6 +271,10 @@ public final class SplashScreen { * screen window. You should call {@code update()} on the * SplashScreen when you want the splash screen to be * updated immediately. + *

+ * The pixel (0, 0) in the coordinate space of the graphics context + * corresponds to the origin of the splash screen native window bounds (see + * {@link #getBounds()}). * * @return graphics context for the splash screen overlay surface * @throws IllegalStateException if the splash screen has already been closed @@ -334,6 +355,11 @@ public final class SplashScreen { * Determines whether the splash screen is visible. The splash screen may * be hidden using {@link #close()}, it is also hidden automatically when * the first AWT/Swing window is made visible. + *

+ * Note that the native platform may delay presenting the splash screen + * native window on the screen. The return value of {@code true} for this + * method only guarantees that the conditions to hide the splash screen + * window have not occurred yet. * * @return true if the splash screen is visible (has not been closed yet), * false otherwise From b80ad03e3ffaa37532a27f16c55400455715eadc Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Thu, 16 Dec 2010 12:47:52 -0800 Subject: [PATCH 11/94] 6839888: Array overrun in vm adlc Reviewed-by: kvn, iveresov --- hotspot/src/share/vm/adlc/dict2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/adlc/dict2.cpp b/hotspot/src/share/vm/adlc/dict2.cpp index c9423df2e3c..22ec13d2c38 100644 --- a/hotspot/src/share/vm/adlc/dict2.cpp +++ b/hotspot/src/share/vm/adlc/dict2.cpp @@ -34,7 +34,7 @@ #define MAXID 20 static char initflag = 0; // True after 1st initialization static char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6}; -static short xsum[MAXID + 1]; +static short xsum[MAXID]; //------------------------------bucket--------------------------------------- class bucket { @@ -66,7 +66,7 @@ void Dict::init() { // Precompute table of null character hashes if( !initflag ) { // Not initializated yet? xsum[0] = (1<> 1); // Hash key, un-modulo'd table size } From 08bce30ea2f075e514377fe50d34fdefd980b5af Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Thu, 16 Dec 2010 13:10:45 -0800 Subject: [PATCH 12/94] 7007257: jaxp 1.4.5 jdk7 1st integration Reviewed-by: joehw --- jaxp/jaxp.properties | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jaxp/jaxp.properties b/jaxp/jaxp.properties index b900f60724e..566654c1cd2 100644 --- a/jaxp/jaxp.properties +++ b/jaxp/jaxp.properties @@ -25,13 +25,13 @@ drops.master.copy.base=${drops.dir} -jaxp_src.bundle.name=jaxp-1_4_4.zip -jaxp_src.bundle.md5.checksum=2c40a758392c4abf2d59f355240df46a +jaxp_src.bundle.name=jaxp-1_4_5-dev.zip +jaxp_src.bundle.md5.checksum=84e2c26853262c9144133c6ff7ef5dc9 jaxp_src.master.bundle.dir=${drops.master.copy.base} -jaxp_src.master.bundle.url.base=https://java.net/downloads/jaxp/jdk7 +jaxp_src.master.bundle.url.base=http://download.java.net/jaxp/1.4.5/dev -#jaxp_tests.bundle.name=jaxp-unittests-1_4_4.zip -#jaxp_tests.bundle.md5.checksum=51845e38b02920cf5374d0331ab3a4ee -#jaxp_tests.master.bundle.dir=${drops.master.copy.base} -#jaxp_tests.master.bundle.url.base=https://java.net/downloads/jaxp/jdk7 +jaxp_tests.bundle.name=jaxp-1_4_5-dev-unittests.zip +jaxp_tests.bundle.md5.checksum=0377e715fa21814cb8006768c5967dc5 +jaxp_tests.master.bundle.dir=${drops.master.copy.base} +jaxp_tests.master.bundle.url.base=http://download.java.net/jaxp/1.4.5/dev From 03dc40d75691e3decf05ae7cc29180e16e1a3aa8 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Thu, 16 Dec 2010 13:14:46 -0800 Subject: [PATCH 13/94] 7006853: Integrate JAX-WS 2.2.2 RI into JDK 7 Reviewed-by: ramap --- jaxws/jaxws.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jaxws/jaxws.properties b/jaxws/jaxws.properties index 9914d2a2620..6bbedfaf6fe 100644 --- a/jaxws/jaxws.properties +++ b/jaxws/jaxws.properties @@ -25,10 +25,10 @@ drops.master.copy.base=${drops.dir} -jaxws_src.bundle.name= jdk7-jaxws2_2-2010_08_19.zip -jaxws_src.bundle.md5.checksum=8775ccefd3b4fa2dde5155ec4b7e4ceb +jaxws_src.bundle.name=jdk7-jaxws2_2_2-2010_12_14.zip +jaxws_src.bundle.md5.checksum=fee9ac72fabc96719eefc66ecaff4bc3 jaxws_src.master.bundle.dir=${drops.master.copy.base} -jaxws_src.master.bundle.url.base=https://java.net/downloads/jax-ws/JDK7 +jaxws_src.master.bundle.url.base=http://download.java.net/glassfish/components/jax-ws/openjdk/jdk7 jaf_src.bundle.name=jdk7-jaf-2010_08_19.zip jaf_src.bundle.md5.checksum=18d15dfd71117daadb332af003d08212 From 9fd396ce55253cd03b09e00ce1133cf9e44058f6 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 16 Dec 2010 14:15:12 -0800 Subject: [PATCH 14/94] 7006505: Use kstat info to identify SPARC processor Read Solaris kstat data to get more precise CPU information Reviewed-by: iveresov, never, twisti, dholmes --- hotspot/make/solaris/makefiles/buildtree.make | 2 +- hotspot/make/solaris/makefiles/vm.make | 4 + hotspot/src/cpu/sparc/vm/sparc.ad | 10 +-- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 49 ++++++------- hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp | 36 ++++++--- hotspot/src/os/solaris/vm/os_solaris.cpp | 2 +- .../vm/vm_version_solaris_sparc.cpp | 73 ++++++++++++++++++- hotspot/src/share/vm/memory/universe.cpp | 11 +-- 8 files changed, 136 insertions(+), 51 deletions(-) diff --git a/hotspot/make/solaris/makefiles/buildtree.make b/hotspot/make/solaris/makefiles/buildtree.make index c0c7831e02f..2dbeac167f1 100644 --- a/hotspot/make/solaris/makefiles/buildtree.make +++ b/hotspot/make/solaris/makefiles/buildtree.make @@ -61,7 +61,7 @@ include $(GAMMADIR)/make/scm.make QUIETLY$(MAKE_VERBOSE) = @ # For now, until the compiler is less wobbly: -TESTFLAGS = -Xbatch -showversion +TESTFLAGS = -Xbatch -Xmx32m -showversion ### maye ARCH_XXX instead? ifdef USE_GCC diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make index 508b1d878ce..fb7a1db8687 100644 --- a/hotspot/make/solaris/makefiles/vm.make +++ b/hotspot/make/solaris/makefiles/vm.make @@ -119,6 +119,10 @@ else LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc endif # sparcWorks +ifeq ("${Platform_arch}", "sparc") +LIBS += -lkstat +endif + # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 1909d010b08..25117f205b2 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -3556,7 +3556,7 @@ operand immP() %{ #ifdef _LP64 // Pointer Immediate: 64-bit operand immP_set() %{ - predicate(!VM_Version::is_niagara1_plus()); + predicate(!VM_Version::is_niagara_plus()); match(ConP); op_cost(5); @@ -3568,7 +3568,7 @@ operand immP_set() %{ // Pointer Immediate: 64-bit // From Niagara2 processors on a load should be better than materializing. operand immP_load() %{ - predicate(VM_Version::is_niagara1_plus() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3))); + predicate(VM_Version::is_niagara_plus() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3))); match(ConP); op_cost(5); @@ -3579,7 +3579,7 @@ operand immP_load() %{ // Pointer Immediate: 64-bit operand immP_no_oop_cheap() %{ - predicate(VM_Version::is_niagara1_plus() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3)); + predicate(VM_Version::is_niagara_plus() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3)); match(ConP); op_cost(5); @@ -3686,7 +3686,7 @@ operand immL_32bits() %{ // Long Immediate: cheap (materialize in <= 3 instructions) operand immL_cheap() %{ - predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::insts_for_set64(n->get_long()) <= 3); + predicate(!VM_Version::is_niagara_plus() || MacroAssembler::insts_for_set64(n->get_long()) <= 3); match(ConL); op_cost(0); @@ -3696,7 +3696,7 @@ operand immL_cheap() %{ // Long Immediate: expensive (materialize in > 3 instructions) operand immL_expensive() %{ - predicate(VM_Version::is_niagara1_plus() && MacroAssembler::insts_for_set64(n->get_long()) > 3); + predicate(VM_Version::is_niagara_plus() && MacroAssembler::insts_for_set64(n->get_long()) > 3); match(ConL); op_cost(0); diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 9e192861926..6db8c7ad1ce 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -38,12 +38,6 @@ int VM_Version::_features = VM_Version::unknown_m; const char* VM_Version::_features_str = ""; -bool VM_Version::is_niagara1_plus() { - // This is a placeholder until the real test is determined. - return is_niagara1() && - (os::processor_count() > maximum_niagara1_processor_count()); -} - void VM_Version::initialize() { _features = determine_features(); PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes(); @@ -69,11 +63,21 @@ void VM_Version::initialize() { _supports_cx8 = has_v9(); - if (is_niagara1()) { + if (is_niagara()) { // Indirect branch is the same cost as direct if (FLAG_IS_DEFAULT(UseInlineCaches)) { FLAG_SET_DEFAULT(UseInlineCaches, false); } + // Align loops on a single instruction boundary. + if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { + FLAG_SET_DEFAULT(OptoLoopAlignment, 4); + } + // When using CMS, we cannot use memset() in BOT updates because + // the sun4v/CMT version in libc_psr uses BIS which exposes + // "phantom zeros" to concurrent readers. See 6948537. + if (FLAG_IS_DEFAULT(UseMemSetInBOT) && UseConcMarkSweepGC) { + FLAG_SET_DEFAULT(UseMemSetInBOT, false); + } #ifdef _LP64 // 32-bit oops don't make sense for the 64-bit VM on sparc // since the 32-bit VM has the same registers and smaller objects. @@ -89,7 +93,7 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) { FLAG_SET_DEFAULT(InteriorEntryAlignment, 4); } - if (is_niagara1_plus()) { + if (is_niagara_plus()) { if (has_blk_init() && AllocatePrefetchStyle > 0 && FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { // Use BIS instruction for allocation prefetch. @@ -105,15 +109,6 @@ void VM_Version::initialize() { } } #endif - if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { - FLAG_SET_DEFAULT(OptoLoopAlignment, 4); - } - // When using CMS, we cannot use memset() in BOT updates because - // the sun4v/CMT version in libc_psr uses BIS which exposes - // "phantom zeros" to concurrent readers. See 6948537. - if (FLAG_IS_DEFAULT(UseMemSetInBOT) && UseConcMarkSweepGC) { - FLAG_SET_DEFAULT(UseMemSetInBOT, false); - } } // Use hardware population count instruction if available. @@ -129,17 +124,18 @@ void VM_Version::initialize() { #endif char buf[512]; - jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (has_v8() ? ", has_v8" : ""), (has_v9() ? ", has_v9" : ""), (has_hardware_popc() ? ", popc" : ""), (has_vis1() ? ", has_vis1" : ""), (has_vis2() ? ", has_vis2" : ""), + (has_vis3() ? ", has_vis3" : ""), (has_blk_init() ? ", has_blk_init" : ""), (is_ultra3() ? ", is_ultra3" : ""), (is_sun4v() ? ", is_sun4v" : ""), - (is_niagara1() ? ", is_niagara1" : ""), - (is_niagara1_plus() ? ", is_niagara1_plus" : ""), + (is_niagara() ? ", is_niagara" : ""), + (is_niagara_plus() ? ", is_niagara_plus" : ""), (is_sparc64() ? ", is_sparc64" : ""), (!has_hardware_mul32() ? ", no-mul32" : ""), (!has_hardware_div32() ? ", no-div32" : ""), @@ -190,17 +186,18 @@ int VM_Version::determine_features() { warning("Cannot recognize SPARC version. Default to V9"); } - if (UseNiagaraInstrs) { - if (is_niagara1(features)) { + assert(is_T_family(features) == is_niagara(features), "Niagara should be T series"); + if (UseNiagaraInstrs) { // Force code generation for Niagara + if (is_T_family(features)) { // Happy to accomodate... } else { NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Niagara");) - features = niagara1_m; + features |= T_family_m; } } else { - if (is_niagara1(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) { + if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) { NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Not-Niagara");) - features &= ~niagara1_unique_m; + features &= ~(T_family_m | T1_model_m); } else { // Happy to accomodate... } @@ -222,7 +219,7 @@ void VM_Version::revert() { unsigned int VM_Version::calc_parallel_worker_threads() { unsigned int result; - if (is_niagara1_plus()) { + if (is_niagara_plus()) { result = nof_parallel_worker_threads(5, 16, 8); } else { result = nof_parallel_worker_threads(5, 8, 8); diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index 5ae1fcbc30c..c83d2de9920 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -41,7 +41,12 @@ protected: vis2_instructions = 7, sun4v_instructions = 8, blk_init_instructions = 9, - fmaf_instructions = 10 + fmaf_instructions = 10, + fmau_instructions = 11, + vis3_instructions = 12, + sparc64_family = 13, + T_family = 14, + T1_model = 15 }; enum Feature_Flag_Set { @@ -59,6 +64,11 @@ protected: sun4v_m = 1 << sun4v_instructions, blk_init_instructions_m = 1 << blk_init_instructions, fmaf_instructions_m = 1 << fmaf_instructions, + fmau_instructions_m = 1 << fmau_instructions, + vis3_instructions_m = 1 << vis3_instructions, + sparc64_family_m = 1 << sparc64_family, + T_family_m = 1 << T_family, + T1_model_m = 1 << T1_model, generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m, generic_v9_m = generic_v8_m | v9_instructions_m, @@ -76,8 +86,13 @@ protected: static int determine_features(); static int platform_features(int features); - static bool is_niagara1(int features) { return (features & sun4v_m) != 0; } - static bool is_sparc64(int features) { return (features & fmaf_instructions_m) != 0; } + // Returns true if the platform is in the niagara line (T series) + static bool is_T_family(int features) { return (features & T_family_m) != 0; } + static bool is_niagara() { return is_T_family(_features); } + DEBUG_ONLY( static bool is_niagara(int features) { return (features & sun4v_m) != 0; } ) + + // Returns true if it is niagara1 (T1). + static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); } static int maximum_niagara1_processor_count() { return 32; } @@ -94,6 +109,7 @@ public: static bool has_hardware_popc() { return (_features & hardware_popc_m) != 0; } static bool has_vis1() { return (_features & vis1_instructions_m) != 0; } static bool has_vis2() { return (_features & vis2_instructions_m) != 0; } + static bool has_vis3() { return (_features & vis3_instructions_m) != 0; } static bool has_blk_init() { return (_features & blk_init_instructions_m) != 0; } static bool supports_compare_and_exchange() @@ -101,14 +117,14 @@ public: static bool is_ultra3() { return (_features & ultra3_m) == ultra3_m; } static bool is_sun4v() { return (_features & sun4v_m) != 0; } - static bool is_niagara1() { return is_niagara1(_features); } - // Returns true if the platform is in the niagara line and - // newer than the niagara1. - static bool is_niagara1_plus(); - static bool is_sparc64() { return is_sparc64(_features); } + // Returns true if the platform is in the niagara line (T series) + // and newer than the niagara1. + static bool is_niagara_plus() { return is_T_family(_features) && !is_T1_model(_features); } + // Fujitsu SPARC64 + static bool is_sparc64() { return (_features & sparc64_family_m) != 0; } - static bool has_fast_fxtof() { return has_v9() && !is_ultra3(); } - static bool has_fast_idiv() { return is_niagara1_plus() || is_sparc64(); } + static bool has_fast_fxtof() { return is_niagara() || is_sparc64() || has_v9() && !is_ultra3(); } + static bool has_fast_idiv() { return is_niagara_plus() || is_sparc64(); } static const char* cpu_features() { return _features_str; } diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index f9898d33246..4d5673f54ca 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -3065,7 +3065,7 @@ char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) { if (addr == NULL) { jio_snprintf(buf, sizeof(buf), ": %s", strerror(err)); } - warning("attempt_reserve_memory_at: couldn't reserve %d bytes at " + warning("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT "%s", bytes, requested_addr, addr, buf); } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 982f987c3d7..855e9a965f1 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -29,6 +29,7 @@ # include # include # include +# include // We need to keep these here as long as we have to build on Solaris // versions before 10. @@ -95,12 +96,24 @@ int VM_Version::platform_features(int features) { // but Solaris 8 is used for jdk6 update builds. #ifndef AV_SPARC_ASI_BLK_INIT #define AV_SPARC_ASI_BLK_INIT 0x0080 /* ASI_BLK_INIT_xxx ASI */ -#endif -#ifndef AV_SPARC_FMAF -#define AV_SPARC_FMAF 0x0100 /* Sparc64 Fused Multiply-Add */ #endif if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m; + +#ifndef AV_SPARC_FMAF +#define AV_SPARC_FMAF 0x0100 /* Fused Multiply-Add */ +#endif if (av & AV_SPARC_FMAF) features |= fmaf_instructions_m; + +#ifndef AV_SPARC_FMAU +#define AV_SPARC_FMAU 0x0200 /* Unfused Multiply-Add */ +#endif + if (av & AV_SPARC_FMAU) features |= fmau_instructions_m; + +#ifndef AV_SPARC_VIS3 +#define AV_SPARC_VIS3 0x0400 /* VIS3 instruction set extensions */ +#endif + if (av & AV_SPARC_VIS3) features |= vis3_instructions_m; + } else { // getisax(2) failed, use the old legacy code. #ifndef PRODUCT @@ -140,5 +153,59 @@ int VM_Version::platform_features(int features) { // Determine the machine type. do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); + { + // Using kstat to determine the machine type. + kstat_ctl_t* kc = kstat_open(); + kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL); + const char* implementation = "UNKNOWN"; + if (ksp != NULL) { + if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) { + kstat_named_t* knm = (kstat_named_t *)ksp->ks_data; + for (int i = 0; i < ksp->ks_ndata; i++) { + if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { +#ifndef KSTAT_DATA_STRING +#define KSTAT_DATA_STRING 9 +#endif + if (knm[i].data_type == KSTAT_DATA_CHAR) { + // VM is running on Solaris 8 which does not have value.str. + implementation = &(knm[i].value.c[0]); + } else if (knm[i].data_type == KSTAT_DATA_STRING) { + // VM is running on Solaris 10. +#ifndef KSTAT_NAMED_STR_PTR + // Solaris 8 was used to build VM, define the structure it misses. + struct str_t { + union { + char *ptr; /* NULL-term string */ + char __pad[8]; /* 64-bit padding */ + } addr; + uint32_t len; /* # bytes for strlen + '\0' */ + }; +#define KSTAT_NAMED_STR_PTR(knptr) (( (str_t*)&((knptr)->value) )->addr.ptr) +#endif + implementation = KSTAT_NAMED_STR_PTR(&knm[i]); + } +#ifndef PRODUCT + if (PrintMiscellaneous && Verbose) { + tty->print_cr("cpu_info.implementation: %s", implementation); + } +#endif + if (strncmp(implementation, "SPARC64", 7) == 0) { + features |= sparc64_family_m; + } else if (strncmp(implementation, "UltraSPARC-T", 12) == 0) { + features |= T_family_m; + if (strncmp(implementation, "UltraSPARC-T1", 13) == 0) { + features |= T1_model_m; + } + } + break; + } + } // for( + } + } + assert(strcmp(implementation, "UNKNOWN") != 0, + "unknown cpu info (changed kstat interface?)"); + kstat_close(kc); + } + return features; } diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 9909e8035d9..9d5af98fdfb 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -934,7 +934,8 @@ jint Universe::initialize_heap() { // See needs_explicit_null_check. // Only set the heap base for compressed oops because it indicates // compressed oops for pstack code. - if (PrintCompressedOopsMode) { + bool verbose = PrintCompressedOopsMode || (PrintMiscellaneous && Verbose); + if (verbose) { tty->cr(); tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M); @@ -943,12 +944,12 @@ jint Universe::initialize_heap() { // Can't reserve heap below 32Gb. Universe::set_narrow_oop_base(Universe::heap()->base() - os::vm_page_size()); Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); - if (PrintCompressedOopsMode) { + if (verbose) { tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base()); } } else { Universe::set_narrow_oop_base(0); - if (PrintCompressedOopsMode) { + if (verbose) { tty->print(", zero based Compressed Oops"); } #ifdef _WIN64 @@ -963,12 +964,12 @@ jint Universe::initialize_heap() { Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); } else { Universe::set_narrow_oop_shift(0); - if (PrintCompressedOopsMode) { + if (verbose) { tty->print(", 32-bits Oops"); } } } - if (PrintCompressedOopsMode) { + if (verbose) { tty->cr(); tty->cr(); } From 8f82f506b85bda657cd87b4f495d7b7864b0fe6a Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Fri, 17 Dec 2010 16:56:13 +0900 Subject: [PATCH 15/94] 7007583: (tz) Windows-only: update tzmappings for KB2443685 Reviewed-by: peytoia --- jdk/src/windows/lib/tzmappings | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/src/windows/lib/tzmappings b/jdk/src/windows/lib/tzmappings index bbc3ca09ce2..7f6f0d36052 100644 --- a/jdk/src/windows/lib/tzmappings +++ b/jdk/src/windows/lib/tzmappings @@ -188,5 +188,6 @@ UTC-02:920,920::GMT-0200: UTC-11:921,921::GMT-1100: Ulaanbaatar Standard Time:922,922::Asia/Ulaanbaatar: Venezuela Standard Time:923,923::America/Caracas: -Western Brazilian Standard Time:924,924:BR:America/Rio_Branco: -Armenian Standard Time:925,925:AM:Asia/Yerevan: +Magadan Standard Time:924,924::Asia/Magadan: +Western Brazilian Standard Time:925,925:BR:America/Rio_Branco: +Armenian Standard Time:926,926:AM:Asia/Yerevan: From c1d0a22eac9fc6d54a7cebf32bff4378fedefe70 Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Fri, 17 Dec 2010 17:13:43 +0900 Subject: [PATCH 16/94] 6644493: [Fmt-Da] SimpleDateFormat parsing RFC822 time offset is slow Reviewed-by: peytoia --- .../classes/java/text/SimpleDateFormat.java | 362 +++++++----------- .../Format/DateFormat/ISO8601ZoneTest.java | 99 +++-- 2 files changed, 199 insertions(+), 262 deletions(-) diff --git a/jdk/src/share/classes/java/text/SimpleDateFormat.java b/jdk/src/share/classes/java/text/SimpleDateFormat.java index 9ae84f828d0..fd2876aca05 100644 --- a/jdk/src/share/classes/java/text/SimpleDateFormat.java +++ b/jdk/src/share/classes/java/text/SimpleDateFormat.java @@ -1662,6 +1662,81 @@ public class SimpleDateFormat extends DateFormat { return 0; } + /** + * Parses numeric forms of time zone offset, such as "hh:mm", and + * sets calb to the parsed value. + * + * @param text the text to be parsed + * @param start the character position to start parsing + * @param sign 1: positive; -1: negative + * @param count 0: 'Z' or "GMT+hh:mm" parsing; 1 - 3: the number of 'X's + * @param colon true - colon required between hh and mm; false - no colon required + * @param calb a CalendarBuilder in which the parsed value is stored + * @return updated parsed position, or its negative value to indicate a parsing error + */ + private int subParseNumericZone(String text, int start, int sign, int count, + boolean colon, CalendarBuilder calb) { + int index = start; + + parse: + try { + char c = text.charAt(index++); + // Parse hh + int hours; + if (!isDigit(c)) { + break parse; + } + hours = c - '0'; + c = text.charAt(index++); + if (isDigit(c)) { + hours = hours * 10 + (c - '0'); + } else { + // If no colon in RFC 822 or 'X' (ISO), two digits are + // required. + if (count > 0 || !colon) { + break parse; + } + --index; + } + if (hours > 23) { + break parse; + } + int minutes = 0; + if (count != 1) { + // Proceed with parsing mm + c = text.charAt(index++); + if (colon) { + if (c != ':') { + break parse; + } + c = text.charAt(index++); + } + if (!isDigit(c)) { + break parse; + } + minutes = c - '0'; + c = text.charAt(index++); + if (!isDigit(c)) { + break parse; + } + minutes = minutes * 10 + (c - '0'); + if (minutes > 59) { + break parse; + } + } + minutes += hours * 60; + calb.set(Calendar.ZONE_OFFSET, minutes * MILLIS_PER_MINUTE * sign) + .set(Calendar.DST_OFFSET, 0); + return index; + } catch (IndexOutOfBoundsException e) { + } + return 1 - index; // -(index - 1) + } + + private boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + /** * Private member function that converts the parsed date strings into * timeFields. Returns -start (for ParsePosition) if failed. @@ -1907,248 +1982,95 @@ public class SimpleDateFormat extends DateFormat { case PATTERN_ZONE_NAME: // 'z' case PATTERN_ZONE_VALUE: // 'Z' - // First try to parse generic forms such as GMT-07:00. Do this first - // in case localized TimeZoneNames contains the string "GMT" - // for a zone; in that case, we don't want to match the first three - // characters of GMT+/-hh:mm etc. { int sign = 0; - int offset; - - // For time zones that have no known names, look for strings - // of the form: - // GMT[+-]hours:minutes or - // GMT. - if ((text.length() - start) >= GMT.length() && - text.regionMatches(true, start, GMT, 0, GMT.length())) { - int num; - calb.set(Calendar.DST_OFFSET, 0); - pos.index = start + GMT.length(); - - try { // try-catch for "GMT" only time zone string - char c = text.charAt(pos.index); - if (c == '+') { - sign = 1; - } else if (c == '-') { - sign = -1; - } + try { + char c = text.charAt(pos.index); + if (c == '+') { + sign = 1; + } else if (c == '-') { + sign = -1; } - catch(StringIndexOutOfBoundsException e) {} + if (sign == 0) { + // Try parsing a custom time zone "GMT+hh:mm" or "GMT". + if ((c == 'G' || c == 'g') + && (text.length() - start) >= GMT.length() + && text.regionMatches(true, start, GMT, 0, GMT.length())) { + pos.index = start + GMT.length(); - if (sign == 0) { /* "GMT" without offset */ - calb.set(Calendar.ZONE_OFFSET, 0); - return pos.index; - } - - // Look for hours. - try { - char c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - num = c - '0'; - - if (text.charAt(++pos.index) != ':') { - c = text.charAt(pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; + if ((text.length() - pos.index) > 0) { + c = text.charAt(pos.index); + if (c == '+') { + sign = 1; + } else if (c == '-') { + sign = -1; + } } - num *= 10; - num += c - '0'; - pos.index++; - } - if (num > 23) { - --pos.index; - break parsing; - } - if (text.charAt(pos.index) != ':') { - break parsing; - } - // Look for minutes. - offset = num * 60; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - num = c - '0'; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - num *= 10; - num += c - '0'; + if (sign == 0) { /* "GMT" without offset */ + calb.set(Calendar.ZONE_OFFSET, 0) + .set(Calendar.DST_OFFSET, 0); + return pos.index; + } - if (num > 59) { - break parsing; - } - } catch (StringIndexOutOfBoundsException e) { - break parsing; - } - offset += num; - // Fall through for final processing below of 'offset' and 'sign'. - } else { - // If the first character is a sign, look for numeric timezones of - // the form [+-]hhmm as specified by RFC 822. Otherwise, check - // for named time zones by looking through the locale data from - // the TimeZoneNames strings. - try { - char c = text.charAt(pos.index); - if (c == '+') { - sign = 1; - } else if (c == '-') { - sign = -1; - } else { - // Try parsing the text as a time zone name (abbr). - int i = subParseZoneString(text, pos.index, calb); - if (i != 0) { + // Parse the rest as "hh:mm" + int i = subParseNumericZone(text, ++pos.index, + sign, 0, true, calb); + if (i > 0) { return i; } - break parsing; + pos.index = -i; + } else { + // Try parsing the text as a time zone + // name or abbreviation. + int i = subParseZoneString(text, pos.index, calb); + if (i > 0) { + return i; + } + pos.index = -i; } - - // Parse the text as an RFC 822 time zone string. This code is - // actually a little more permissive than RFC 822. It will - // try to do its best with numbers that aren't strictly 4 - // digits long. - - // Look for hh. - int hours = 0; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; + } else { + // Parse the rest as "hhmm" (RFC 822) + int i = subParseNumericZone(text, ++pos.index, + sign, 0, false, calb); + if (i > 0) { + return i; } - hours = c - '0'; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - hours *= 10; - hours += c - '0'; - - if (hours > 23) { - break parsing; - } - - // Look for mm. - int minutes = 0; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - minutes = c - '0'; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - minutes *= 10; - minutes += c - '0'; - - if (minutes > 59) { - break parsing; - } - - offset = hours * 60 + minutes; - } catch (StringIndexOutOfBoundsException e) { - break parsing; + pos.index = -i; } - } - - // Do the final processing for both of the above cases. We only - // arrive here if the form GMT+/-... or an RFC 822 form was seen. - if (sign != 0) { - offset *= MILLIS_PER_MINUTE * sign; - calb.set(Calendar.ZONE_OFFSET, offset).set(Calendar.DST_OFFSET, 0); - return ++pos.index; + } catch (IndexOutOfBoundsException e) { } } break parsing; case PATTERN_ISO_ZONE: // 'X' { - int sign = 0; - int offset = 0; - - iso8601: { - try { - char c = text.charAt(pos.index); - if (c == 'Z') { - calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0); - return ++pos.index; - } - - // parse text as "+/-hh[[:]mm]" based on count - if (c == '+') { - sign = 1; - } else if (c == '-') { - sign = -1; - } - // Look for hh. - int hours = 0; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - hours = c - '0'; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - hours *= 10; - hours += c - '0'; - if (hours > 23) { - break parsing; - } - - if (count == 1) { // "X" - offset = hours * 60; - break iso8601; - } - - c = text.charAt(++pos.index); - // Skip ':' if "XXX" - if (c == ':') { - if (count == 2) { - break parsing; - } - c = text.charAt(++pos.index); - } else { - if (count == 3) { - // missing ':' - break parsing; - } - } - - // Look for mm. - int minutes = 0; - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - minutes = c - '0'; - c = text.charAt(++pos.index); - if (c < '0' || c > '9') { /* must be from '0' to '9'. */ - break parsing; - } - minutes *= 10; - minutes += c - '0'; - - if (minutes > 59) { - break parsing; - } - - offset = hours * 60 + minutes; - } catch (StringIndexOutOfBoundsException e) { - break parsing; - } + if ((text.length() - pos.index) <= 0) { + break parsing; } - // Do the final processing for both of the above cases. We only - // arrive here if the form GMT+/-... or an RFC 822 form was seen. - if (sign != 0) { - offset *= MILLIS_PER_MINUTE * sign; - calb.set(Calendar.ZONE_OFFSET, offset).set(Calendar.DST_OFFSET, 0); + int sign = 0; + char c = text.charAt(pos.index); + if (c == 'Z') { + calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0); return ++pos.index; } + + // parse text as "+/-hh[[:]mm]" based on count + if (c == '+') { + sign = 1; + } else if (c == '-') { + sign = -1; + } else { + ++pos.index; + break parsing; + } + int i = subParseNumericZone(text, ++pos.index, sign, count, + count == 3, calb); + if (i > 0) { + return i; + } + pos.index = -i; } break parsing; diff --git a/jdk/test/java/text/Format/DateFormat/ISO8601ZoneTest.java b/jdk/test/java/text/Format/DateFormat/ISO8601ZoneTest.java index 2179948a849..2a5c2412585 100644 --- a/jdk/test/java/text/Format/DateFormat/ISO8601ZoneTest.java +++ b/jdk/test/java/text/Format/DateFormat/ISO8601ZoneTest.java @@ -60,48 +60,51 @@ public class ISO8601ZoneTest { "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", }; + // badData[][0] - format + // badData[][1] - (bad) text to be parsed + // badData[][2] - subtext at the end of which a parse error is detected static final String[][] badData = { - { "X", "1" }, - { "X", "+1" }, - { "X", "-2" }, - { "X", "-24" }, - { "X", "+24" }, + { "X", "1", "1" }, + { "X", "+1", "+1" }, + { "X", "-2", "-2" }, + { "X", "-24", "-2" }, + { "X", "+24", "+2" }, - { "XX", "9" }, - { "XX", "23" }, - { "XX", "234" }, - { "XX", "3456" }, - { "XX", "23456" }, - { "XX", "+1" }, - { "XX", "-12" }, - { "XX", "+123" }, - { "XX", "-12:34" }, - { "XX", "+12:34" }, - { "XX", "-2423" }, - { "XX", "+2423" }, - { "XX", "-1260" }, - { "XX", "+1260" }, + { "XX", "9", "9" }, + { "XX", "23", "2" }, + { "XX", "234", "2" }, + { "XX", "3456", "3" }, + { "XX", "23456", "2" }, + { "XX", "+1", "+1" }, + { "XX", "-12", "-12" }, + { "XX", "+123", "+123" }, + { "XX", "-12:34", "-12" }, + { "XX", "+12:34", "+12" }, + { "XX", "-2423", "-2" }, + { "XX", "+2423", "+2" }, + { "XX", "-1260", "-126" }, + { "XX", "+1260", "+126" }, - { "XXX", "9" }, - { "XXX", "23" }, - { "XXX", "234" }, - { "XXX", "3456" }, - { "XXX", "23456" }, - { "XXX", "2:34" }, - { "XXX", "12:4" }, - { "XXX", "12:34" }, - { "XXX", "-1" }, - { "XXX", "+1" }, - { "XXX", "-12" }, - { "XXX", "+12" }, - { "XXX", "-123" }, - { "XXX", "+123" }, - { "XXX", "-1234" }, - { "XXX", "+1234" }, - { "XXX", "+24:23" }, - { "XXX", "+12:60" }, - { "XXX", "+1:23" }, - { "XXX", "+12:3" }, + { "XXX", "9", "9" }, + { "XXX", "23", "2" }, + { "XXX", "234", "2" }, + { "XXX", "3456", "3" }, + { "XXX", "23456", "2" }, + { "XXX", "2:34", "2" }, + { "XXX", "12:4", "1" }, + { "XXX", "12:34", "1" }, + { "XXX", "-1", "-1" }, + { "XXX", "+1", "+1" }, + { "XXX", "-12", "-12" }, + { "XXX", "+12", "+12" }, + { "XXX", "-123", "-12" }, + { "XXX", "+123", "+12" }, + { "XXX", "-1234", "-12" }, + { "XXX", "+1234", "+12" }, + { "XXX", "+24:23", "+2" }, + { "XXX", "+12:60", "+12:6" }, + { "XXX", "+1:23", "+1" }, + { "XXX", "+12:3", "+12:3" }, }; static String[] badFormats = { @@ -110,6 +113,8 @@ public class ISO8601ZoneTest { public static void main(String[] args) throws Exception { TimeZone tz = TimeZone.getDefault(); + Locale loc = Locale.getDefault(); + Locale.setDefault(Locale.US); try { for (int i = 0; i < formatData.length; i++) { @@ -128,7 +133,7 @@ public class ISO8601ZoneTest { } for (String[] d : badData) { - badDataParsing(d[0], d[1]); + badDataParsing(d[0], d[1], d[2].length()); } for (String fmt : badFormats) { @@ -136,6 +141,7 @@ public class ISO8601ZoneTest { } } finally { TimeZone.setDefault(tz); + Locale.setDefault(loc); } } @@ -188,15 +194,24 @@ public class ISO8601ZoneTest { } - static void badDataParsing(String fmt, String text) { + static void badDataParsing(String fmt, String text, int expectedErrorIndex) { + SimpleDateFormat sdf = new SimpleDateFormat(fmt); try { - SimpleDateFormat sdf = new SimpleDateFormat(fmt); sdf.parse(text); throw new RuntimeException("didn't throw an exception: fmt=" + fmt + ", text=" + text); } catch (ParseException e) { // OK } + + ParsePosition pos = new ParsePosition(0); + Date d = sdf.parse(text, pos); + int errorIndex = pos.getErrorIndex(); + if (d != null || errorIndex != expectedErrorIndex) { + throw new RuntimeException("Bad error index=" + errorIndex + + ", expected=" + expectedErrorIndex + + ", fmt=" + fmt + ", text=" + text); + } } static void badFormat(String fmt) { From 62f4413b7b0ba52ebb2c242e28f9592da44328ba Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Fri, 17 Dec 2010 18:06:28 +0900 Subject: [PATCH 17/94] 6983207: API: MessageFormat quote handling discrepancy Reviewed-by: peytoia --- .../classes/java/text/MessageFormat.java | 132 +++++++++--------- 1 file changed, 64 insertions(+), 68 deletions(-) diff --git a/jdk/src/share/classes/java/text/MessageFormat.java b/jdk/src/share/classes/java/text/MessageFormat.java index ec5c7ff0d65..41623c48ed0 100644 --- a/jdk/src/share/classes/java/text/MessageFormat.java +++ b/jdk/src/share/classes/java/text/MessageFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,73 +93,65 @@ import java.util.Locale; * currency * percent * SubformatPattern - * - * String: - * StringPartopt - * String StringPart - * - * StringPart: - * '' - * ' QuotedString ' - * UnquotedString - * - * SubformatPattern: - * SubformatPatternPartopt - * SubformatPattern SubformatPatternPart - * - * SubFormatPatternPart: - * ' QuotedPattern ' - * UnquotedPattern * * - *

- * Within a String, "''" represents a single - * quote. A QuotedString can contain arbitrary characters - * except single quotes; the surrounding single quotes are removed. - * An UnquotedString can contain arbitrary characters - * except single quotes and left curly brackets. Thus, a string that - * should result in the formatted message "'{0}'" can be written as - * "'''{'0}''" or "'''{0}'''". - *

- * Within a SubformatPattern, different rules apply. - * A QuotedPattern can contain arbitrary characters - * except single quotes; but the surrounding single quotes are - * not removed, so they may be interpreted by the - * subformat. For example, "{1,number,$'#',##}" will - * produce a number format with the pound-sign quoted, with a result - * such as: "$#31,45". - * An UnquotedPattern can contain arbitrary characters - * except single quotes, but curly braces within it must be balanced. - * For example, "ab {0} de" and "ab '}' de" - * are valid subformat patterns, but "ab {0'}' de" and - * "ab } de" are not. + *

Within a String, a pair of single quotes can be used to + * quote any arbitrary characters except single quotes. For example, + * pattern string "'{0}'" represents string + * "{0}", not a FormatElement. A single quote itself + * must be represented by doubled single quotes {@code ''} throughout a + * String. For example, pattern string "'{''}'" is + * interpreted as a sequence of '{ (start of quoting and a + * left curly brace), '' (a single quote), and + * }' (a right curly brace and end of quoting), + * not '{' and '}' (quoted left and + * right curly braces): representing string "{'}", + * not "{}". + * + *

A SubformatPattern is interpreted by its corresponding + * subformat, and subformat-dependent pattern rules apply. For example, + * pattern string "{1,number,$'#',##}" + * (SubformatPattern with underline) will produce a number format + * with the pound-sign quoted, with a result such as: {@code + * "$#31,45"}. Refer to each {@code Format} subclass documentation for + * details. + * + *

Any unmatched quote is treated as closed at the end of the given + * pattern. For example, pattern string {@code "'{0}"} is treated as + * pattern {@code "'{0}'"}. + * + *

Any curly braces within an unquoted pattern must be balanced. For + * example, "ab {0} de" and "ab '}' de" are + * valid patterns, but "ab {0'}' de", "ab } de" + * and "''{''" are not. + * *

*

Warning:
The rules for using quotes within message * format patterns unfortunately have shown to be somewhat confusing. * In particular, it isn't always obvious to localizers whether single * quotes need to be doubled or not. Make sure to inform localizers about * the rules, and tell them (for example, by using comments in resource - * bundle source files) which strings will be processed by MessageFormat. + * bundle source files) which strings will be processed by {@code MessageFormat}. * Note that localizers may need to use single quotes in translated * strings where the original version doesn't have them. *
*

* The ArgumentIndex value is a non-negative integer written - * using the digits '0' through '9', and represents an index into the - * arguments array passed to the format methods - * or the result array returned by the parse methods. + * using the digits {@code '0'} through {@code '9'}, and represents an index into the + * {@code arguments} array passed to the {@code format} methods + * or the result array returned by the {@code parse} methods. *

* The FormatType and FormatStyle values are used to create - * a Format instance for the format element. The following - * table shows how the values map to Format instances. Combinations not + * a {@code Format} instance for the format element. The following + * table shows how the values map to {@code Format} instances. Combinations not * shown in the table are illegal. A SubformatPattern must - * be a valid pattern string for the Format subclass used. + * be a valid pattern string for the {@code Format} subclass used. *

* * - * * * * * * * * * * * * * * * * * * * *
Format Type - * Format Style - * Subformat Created + * FormatType + * FormatStyle + * Subformat Created *
(none) * (none) @@ -167,61 +159,61 @@ import java.util.Locale; *
number * (none) - * NumberFormat.getInstance(getLocale()) + * {@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())} *
integer - * NumberFormat.getIntegerInstance(getLocale()) + * {@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())} *
currency - * NumberFormat.getCurrencyInstance(getLocale()) + * {@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())} *
percent - * NumberFormat.getPercentInstance(getLocale()) + * {@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())} *
SubformatPattern - * new DecimalFormat(subformatPattern, DecimalFormatSymbols.getInstance(getLocale())) + * {@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))} *
date * (none) - * DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()) + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} *
short - * DateFormat.getDateInstance(DateFormat.SHORT, getLocale()) + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} *
medium - * DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()) + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} *
long - * DateFormat.getDateInstance(DateFormat.LONG, getLocale()) + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} *
full - * DateFormat.getDateInstance(DateFormat.FULL, getLocale()) + * {@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} *
SubformatPattern - * new SimpleDateFormat(subformatPattern, getLocale()) + * {@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} *
time * (none) - * DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()) + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} *
short - * DateFormat.getTimeInstance(DateFormat.SHORT, getLocale()) + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} *
medium - * DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()) + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} *
long - * DateFormat.getTimeInstance(DateFormat.LONG, getLocale()) + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} *
full - * DateFormat.getTimeInstance(DateFormat.FULL, getLocale()) + * {@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} *
SubformatPattern - * new SimpleDateFormat(subformatPattern, getLocale()) + * {@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} *
choice * SubformatPattern - * new ChoiceFormat(subformatPattern) + * {@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)} *
*

* @@ -321,7 +313,7 @@ import java.util.Locale; * * *

- * Likewise, parsing with a MessageFormat object using patterns containing + * Likewise, parsing with a {@code MessageFormat} object using patterns containing * multiple occurrences of the same argument would return the last match. For * example, *

@@ -343,7 +335,11 @@ import java.util.Locale;
  * @see          Format
  * @see          NumberFormat
  * @see          DecimalFormat
+ * @see          DecimalFormatSymbols
  * @see          ChoiceFormat
+ * @see          DateFormat
+ * @see          SimpleDateFormat
+ *
  * @author       Mark Davis
  */
 

From dbef654a2cc3cca718852080eb7359be34f55371 Mon Sep 17 00:00:00 2001
From: Andrew Brygin 
Date: Fri, 17 Dec 2010 13:18:08 +0300
Subject: [PATCH 18/94] 7006948: FindBugs warning in IndexColorModel class

Reviewed-by: igor, prr
---
 jdk/src/share/classes/java/awt/image/IndexColorModel.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/jdk/src/share/classes/java/awt/image/IndexColorModel.java b/jdk/src/share/classes/java/awt/image/IndexColorModel.java
index 969d524f9ab..a76f2d5ff50 100644
--- a/jdk/src/share/classes/java/awt/image/IndexColorModel.java
+++ b/jdk/src/share/classes/java/awt/image/IndexColorModel.java
@@ -625,7 +625,7 @@ public class IndexColorModel extends ColorModel {
             }
             nBits[0] = nBits[1] = nBits[2] = 8;
         }
-        return nBits;
+        return nBits.clone();
     }
 
     /**

From 2540ccd05fe080d6d06f633524c8a3bcaff36205 Mon Sep 17 00:00:00 2001
From: Kevin Walls 
Date: Fri, 17 Dec 2010 12:14:48 +0000
Subject: [PATCH 19/94] 7003487: clhsdbproc stacktrace fails on x64

Reviewed-by: phh
---
 .../classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
index 49c101fe6a0..759e6d101e8 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
@@ -30,6 +30,7 @@ import sun.jvm.hotspot.asm.*;
 import sun.jvm.hotspot.asm.sparc.*;
 import sun.jvm.hotspot.asm.x86.*;
 import sun.jvm.hotspot.asm.ia64.*;
+import sun.jvm.hotspot.asm.amd64.*;
 import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.compiler.*;
 import sun.jvm.hotspot.debugger.*;
@@ -198,6 +199,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
          cpuHelper = new SPARCHelper();
       } else if (cpu.equals("x86")) {
          cpuHelper = new X86Helper();
+      } else if (cpu.equals("amd64")) {
+         cpuHelper = new AMD64Helper();
       } else if (cpu.equals("ia64")) {
          cpuHelper = new IA64Helper();
       } else {

From 33b174749a733ab31d32241838f4912910e78b5c Mon Sep 17 00:00:00 2001
From: Jennifer Godinez 
Date: Fri, 17 Dec 2010 09:39:54 -0800
Subject: [PATCH 20/94] 6635462: D3D: REGRESSION: XOR rendering is extremly
 slow

Reviewed-by: igor, prr
---
 .../javax/swing/DefaultDesktopManager.java    | 26 ++++++++++-
 .../sun/awt/windows/WComponentPeer.java       | 21 +++++++++
 .../sun/java2d/d3d/D3DSurfaceData.java        | 45 ++++++++++++++++++-
 3 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java
index d531526265c..aae1e51ef0c 100644
--- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java
+++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java
@@ -359,7 +359,22 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab
                         f.getWidth()-1, f.getHeight()-1);
               }
               g.drawRect( newX, newY, f.getWidth()-1, f.getHeight()-1);
-              currentLoc = new Point (newX, newY);
+              /* Work around for 6635462: XOR mode may cause a SurfaceLost on first use.
+              * Swing doesn't expect that its XOR drawRect did
+              * not complete, so believes that on re-entering at
+              * the next update location, that there is an XOR rect
+              * to draw out at "currentLoc". But in fact
+              * its now got a new clean surface without that rect,
+              * so drawing it "out" in fact draws it on, leaving garbage.
+              * So only update/set currentLoc if the draw completed.
+              */
+              sun.java2d.SurfaceData sData =
+                  ((sun.java2d.SunGraphics2D)g).getSurfaceData();
+
+              if (!sData.isSurfaceLost()) {
+                  currentLoc = new Point (newX, newY);
+              }
+;
               g.dispose();
             }
         } else if (dragMode == FASTER_DRAG_MODE) {
@@ -412,7 +427,14 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab
                 g.drawRect( currentBounds.x, currentBounds.y, currentBounds.width-1, currentBounds.height-1);
               }
               g.drawRect( newX, newY, newWidth-1, newHeight-1);
-              currentBounds = new Rectangle (newX, newY, newWidth, newHeight);
+
+              // Work around for 6635462, see comment in dragFrame()
+              sun.java2d.SurfaceData sData =
+                  ((sun.java2d.SunGraphics2D)g).getSurfaceData();
+              if (!sData.isSurfaceLost()) {
+                  currentBounds = new Rectangle (newX, newY, newWidth, newHeight);
+              }
+
               g.setPaintMode();
               g.dispose();
             }
diff --git a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java
index 5a3cd2ddd87..8dc99ed60f2 100644
--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java
@@ -999,6 +999,8 @@ public abstract class WComponentPeer extends WObjectPeer
     public void setBoundsOperation(int operation) {
     }
 
+    private volatile boolean isAccelCapable = true;
+
     /**
      * Returns whether this component is capable of being hw accelerated.
      * More specifically, whether rendering to this component or a
@@ -1009,11 +1011,22 @@ public abstract class WComponentPeer extends WObjectPeer
      * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
      * PERPIXEL_TRANSLUCENT}.
      *
+     * Another condition is if Xor paint mode was detected when rendering
+     * to an on-screen accelerated surface associated with this peer.
+     * in this case both on- and off-screen acceleration for this peer is
+     * disabled.
+     *
      * @return {@code true} if this component is capable of being hw
      * accelerated, {@code false} otherwise
      * @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
      */
     public boolean isAccelCapable() {
+        if (!isAccelCapable ||
+            !isContainingTopLevelAccelCapable((Component)target))
+        {
+            return false;
+        }
+
         boolean isTranslucent =
             SunToolkit.isContainingTopLevelTranslucent((Component)target);
         // D3D/OGL and translucent windows interacted poorly in Windows XP;
@@ -1021,6 +1034,14 @@ public abstract class WComponentPeer extends WObjectPeer
         return !isTranslucent || Win32GraphicsEnvironment.isVistaOS();
     }
 
+    /**
+     * Disables acceleration for this peer.
+     */
+    public void disableAcceleration() {
+        isAccelCapable = false;
+    }
+
+
     native void setRectangularShape(int lox, int loy, int hix, int hiy,
                      Region region);
 
diff --git a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
index 553d84156b2..bc7dfd8631a 100644
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
@@ -437,6 +437,10 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
         protected int getElem(final int x, final int y,
                               final SurfaceData sData)
         {
+            if (sData.isSurfaceLost()) {
+                return 0;
+            }
+
             int retPixel;
             D3DRenderQueue rq = D3DRenderQueue.getInstance();
             rq.lock();
@@ -456,6 +460,10 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
         protected void setElem(final int x, final int y, final int pixel,
                                final SurfaceData sData)
         {
+            if (sData.isSurfaceLost()) {
+                  return;
+            }
+
             D3DRenderQueue rq = D3DRenderQueue.getInstance();
             rq.lock();
             try {
@@ -512,15 +520,32 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
             sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;
     }
 
+    /**
+     * If acceleration should no longer be used for this surface.
+     * This implementation flags to the manager that it should no
+     * longer attempt to re-create a D3DSurface.
+     */
+    void disableAccelerationForSurface() {
+        if (offscreenImage != null) {
+            SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
+            if (sm instanceof D3DVolatileSurfaceManager) {
+                setSurfaceLost(true);
+                ((D3DVolatileSurfaceManager)sm).setAccelerationEnabled(false);
+            }
+        }
+    }
+
     public void validatePipe(SunGraphics2D sg2d) {
         TextPipe textpipe;
         boolean validated = false;
 
         // REMIND: the D3D pipeline doesn't support XOR!, more
-        // fixes will be needed below
+        // fixes will be needed below. For now we disable D3D rendering
+        // for the surface which had any XOR rendering done to.
         if (sg2d.compositeState >= sg2d.COMP_XOR) {
             super.validatePipe(sg2d);
             sg2d.imagepipe = d3dImagePipe;
+            disableAccelerationForSurface();
             return;
         }
 
@@ -894,8 +919,26 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
             return peer.getTarget();
         }
 
+        @Override
+        void disableAccelerationForSurface() {
+            // for on-screen surfaces we need to make sure a backup GDI surface is
+            // is used until a new one is set (which may happen during a resize). We
+            // don't want the screen update maanger to replace the surface right way
+            // because it causes repainting issues in Swing, so we invalidate it,
+            // this will prevent SUM from issuing a replaceSurfaceData call.
+            setSurfaceLost(true);
+            invalidate();
+            flush();
+            peer.disableAcceleration();
+            ScreenUpdateManager.getInstance().dropScreenSurface(this);
+        }
+
         @Override
         void restoreSurface() {
+            if (!peer.isAccelCapable()) {
+                throw new InvalidPipeException("Onscreen acceleration " +
+                                               "disabled for this surface");
+            }
             Window fsw = graphicsDevice.getFullScreenWindow();
             if (fsw != null && fsw != peer.getTarget()) {
                 throw new InvalidPipeException("Can't restore onscreen surface"+

From ecddc15f7cb5a9bb8e08cabd66f1b03cc2b01485 Mon Sep 17 00:00:00 2001
From: Tom Rodriguez 
Date: Fri, 17 Dec 2010 15:55:32 -0800
Subject: [PATCH 21/94] 6579789: Internal error "c1_LinearScan.cpp:1429 Error:
 assert(false,"")" in debuggee with fastdebug VM

Reviewed-by: kvn, iveresov
---
 hotspot/src/share/vm/c1/c1_LinearScan.cpp     | 23 ++++++++-
 hotspot/src/share/vm/c1/c1_LinearScan.hpp     |  1 +
 .../test/compiler/6579789/Test6579789.java    | 49 +++++++++++++++++++
 3 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 hotspot/test/compiler/6579789/Test6579789.java

diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp
index fe118944a02..7419f9e8fac 100644
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp
@@ -90,6 +90,7 @@ LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
  , _intervals(0)   // initialized later with correct length
  , _new_intervals_from_allocation(new IntervalList())
  , _sorted_intervals(NULL)
+ , _needs_full_resort(false)
  , _lir_ops(0)     // initialized later with correct length
  , _block_of_op(0) // initialized later with correct length
  , _has_info(0)
@@ -1520,6 +1521,14 @@ void LinearScan::create_unhandled_lists(Interval** list1, Interval** list2, bool
 void LinearScan::sort_intervals_before_allocation() {
   TIME_LINEAR_SCAN(timer_sort_intervals_before);
 
+  if (_needs_full_resort) {
+    // There is no known reason why this should occur but just in case...
+    assert(false, "should never occur");
+    // Re-sort existing interval list because an Interval::from() has changed
+    _sorted_intervals->sort(interval_cmp);
+    _needs_full_resort = false;
+  }
+
   IntervalList* unsorted_list = &_intervals;
   int unsorted_len = unsorted_list->length();
   int sorted_len = 0;
@@ -1559,11 +1568,18 @@ void LinearScan::sort_intervals_before_allocation() {
     }
   }
   _sorted_intervals = sorted_list;
+  assert(is_sorted(_sorted_intervals), "intervals unsorted");
 }
 
 void LinearScan::sort_intervals_after_allocation() {
   TIME_LINEAR_SCAN(timer_sort_intervals_after);
 
+  if (_needs_full_resort) {
+    // Re-sort existing interval list because an Interval::from() has changed
+    _sorted_intervals->sort(interval_cmp);
+    _needs_full_resort = false;
+  }
+
   IntervalArray* old_list      = _sorted_intervals;
   IntervalList*  new_list      = _new_intervals_from_allocation;
   int old_len = old_list->length();
@@ -1571,6 +1587,7 @@ void LinearScan::sort_intervals_after_allocation() {
 
   if (new_len == 0) {
     // no intervals have been added during allocation, so sorted list is already up to date
+    assert(is_sorted(_sorted_intervals), "intervals unsorted");
     return;
   }
 
@@ -1593,6 +1610,7 @@ void LinearScan::sort_intervals_after_allocation() {
   }
 
   _sorted_intervals = combined_list;
+  assert(is_sorted(_sorted_intervals), "intervals unsorted");
 }
 
 
@@ -1825,6 +1843,8 @@ void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveRes
       interval = interval->split(from_op_id);
       interval->assign_reg(reg, regHi);
       append_interval(interval);
+    } else {
+      _needs_full_resort = true;
     }
     assert(interval->from() == from_op_id, "must be true now");
 
@@ -4492,7 +4512,8 @@ void Interval::print(outputStream* out) const {
     }
   } else {
     type_name = type2name(type());
-    if (assigned_reg() != -1) {
+    if (assigned_reg() != -1 &&
+        (LinearScan::num_physical_regs(type()) == 1 || assigned_regHi() != -1)) {
       opr = LinearScan::calc_operand_for_interval(this);
     }
   }
diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.hpp b/hotspot/src/share/vm/c1/c1_LinearScan.hpp
index 97f4043c18a..018570f9c56 100644
--- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp
@@ -148,6 +148,7 @@ class LinearScan : public CompilationResourceObj {
   IntervalList              _intervals;         // mapping from register number to interval
   IntervalList*             _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split
   IntervalArray*            _sorted_intervals;  // intervals sorted by Interval::from()
+  bool                      _needs_full_resort; // set to true if an Interval::from() is changed and _sorted_intervals must be resorted
 
   LIR_OpArray               _lir_ops;           // mapping from LIR_Op id to LIR_Op node
   BlockBeginArray           _block_of_op;       // mapping from LIR_Op id to the BlockBegin containing this instruction
diff --git a/hotspot/test/compiler/6579789/Test6579789.java b/hotspot/test/compiler/6579789/Test6579789.java
new file mode 100644
index 00000000000..344a08fae28
--- /dev/null
+++ b/hotspot/test/compiler/6579789/Test6579789.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6579789
+ * @summary Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
+ * @run main/othervm -Xcomp -XX:UseSSE=0 -XX:CompileOnly=Test6579789.bug Test6579789
+ */
+
+public class Test6579789 {
+    public static void main(String[] args) {
+        bug(4);
+    }
+    public static void bug(int n) {
+        float f = 1;
+        int i = 1;
+        try {
+            int x = 1 / n; // instruction that can trap
+            f = 2;
+            i = 2;
+            int y = 2 / n; // instruction that can trap
+        } catch (Exception ex) {
+            f++;
+            i++;
+        }
+    }
+}

From 135eaf7e21958be0b37a22281497002fae1b6f94 Mon Sep 17 00:00:00 2001
From: Christian Thalinger 
Date: Sat, 18 Dec 2010 01:15:01 -0800
Subject: [PATCH 22/94] 6990933: assert(sender_cb) failed: sanity in
 frame::sender_for_interpreter_frame

Reviewed-by: never
---
 hotspot/src/share/vm/code/nmethod.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp
index 089586bac66..3f5d66f8568 100644
--- a/hotspot/src/share/vm/code/nmethod.cpp
+++ b/hotspot/src/share/vm/code/nmethod.cpp
@@ -811,9 +811,11 @@ nmethod::nmethod(
     _stub_offset             = content_offset()      + code_buffer->total_offset_of(code_buffer->stubs());
 
     // Exception handler and deopt handler are in the stub section
+    assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set");
+    assert(offsets->value(CodeOffsets::Deopt     ) != -1, "must be set");
     _exception_offset        = _stub_offset          + offsets->value(CodeOffsets::Exceptions);
     _deoptimize_offset       = _stub_offset          + offsets->value(CodeOffsets::Deopt);
-    if (has_method_handle_invokes()) {
+    if (offsets->value(CodeOffsets::DeoptMH) != -1) {
       _deoptimize_mh_offset  = _stub_offset          + offsets->value(CodeOffsets::DeoptMH);
     } else {
       _deoptimize_mh_offset  = -1;
@@ -1909,6 +1911,7 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) {
       break;
     }
   }
+  assert(has_method_handle_invokes() == (_deoptimize_mh_offset != -1), "must have deopt mh handler");
 
   int size = count * sizeof(PcDesc);
   assert(scopes_pcs_size() >= size, "oob");

From 5032fcd7b5e8ae13a2d97cf138d4b08569f2a299 Mon Sep 17 00:00:00 2001
From: Kumar Srinivasan 
Date: Sat, 18 Dec 2010 09:38:39 -0800
Subject: [PATCH 23/94] 6567415: Neverending loop in ClassReader

Reviewed-by: jjg
---
 .../com/sun/tools/javac/jvm/ClassReader.java  |  14 +-
 .../test/tools/javac/6567415/T6567415.java    | 146 ++++++++++++++++++
 2 files changed, 157 insertions(+), 3 deletions(-)
 create mode 100644 langtools/test/tools/javac/6567415/T6567415.java

diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
index 2d09c795743..0024f2fb5bf 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,6 +77,8 @@ public class ClassReader implements Completer {
     protected static final Context.Key classReaderKey =
         new Context.Key();
 
+    public static final int INITIAL_BUFFER_SIZE = 0x0fff0;
+
     Annotate annotate;
 
     /** Switch: verbose output.
@@ -185,7 +187,7 @@ public class ClassReader implements Completer {
 
     /** The buffer containing the currently read class file.
      */
-    byte[] buf = new byte[0x0fff0];
+    byte[] buf = new byte[INITIAL_BUFFER_SIZE];
 
     /** The current input pointer.
      */
@@ -2419,8 +2421,14 @@ public class ClassReader implements Completer {
                 }
             }
         }
+        /*
+         * ensureCapacity will increase the buffer as needed, taking note that
+         * the new buffer will always be greater than the needed and never
+         * exactly equal to the needed size or bp. If equal then the read (above)
+         * will infinitely loop as buf.length - bp == 0.
+         */
         private static byte[] ensureCapacity(byte[] buf, int needed) {
-            if (buf.length < needed) {
+            if (buf.length <= needed) {
                 byte[] old = buf;
                 buf = new byte[Integer.highestOneBit(needed) << 1];
                 System.arraycopy(old, 0, buf, 0, old.length);
diff --git a/langtools/test/tools/javac/6567415/T6567415.java b/langtools/test/tools/javac/6567415/T6567415.java
new file mode 100644
index 00000000000..683197e6e84
--- /dev/null
+++ b/langtools/test/tools/javac/6567415/T6567415.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6567415
+ * @summary Test to ensure javac does not go into an infinite loop, while
+ *               reading a classfile of a specific length.
+ * @compile -XDignore.symbol.file T6567415.java
+ * @run main T6567415
+ * @author ksrini
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+
+/*
+ * this test compiles Bar.java into a classfile and enlarges the file to the
+ * magic file length, then use this mutated file on the classpath to compile
+ * Foo.java which references Bar.java and Ka-boom. QED.
+ */
+public class T6567415 {
+    final static String TEST_FILE_NAME = "Bar";
+    final static String TEST_JAVA = TEST_FILE_NAME + ".java";
+    final static String TEST_CLASS = TEST_FILE_NAME + ".class";
+
+    final static String TEST2_FILE_NAME = "Foo";
+    final static String TEST2_JAVA = TEST2_FILE_NAME + ".java";
+
+    /*
+     * the following is the initial buffer length set in ClassReader.java
+     * thus this value needs to change if ClassReader buf length changes.
+     */
+
+    final static int BAD_FILE_LENGTH =
+            com.sun.tools.javac.jvm.ClassReader.INITIAL_BUFFER_SIZE;
+
+    static void createClassFile() throws IOException {
+        FileOutputStream fos = null;
+        try {
+            fos = new FileOutputStream(TEST_JAVA);
+            PrintStream ps = new PrintStream(fos);
+            ps.println("public class " + TEST_FILE_NAME + " {}");
+        } finally {
+            fos.close();
+        }
+        String cmds[] = {TEST_JAVA};
+        com.sun.tools.javac.Main.compile(cmds);
+    }
+
+    static void enlargeClassFile() throws IOException {
+        File f = new File(TEST_CLASS);
+        if (!f.exists()) {
+            System.out.println("file not found: " + TEST_CLASS);
+            System.exit(1);
+        }
+        File tfile = new File(f.getAbsolutePath() + ".tmp");
+        f.renameTo(tfile);
+
+        RandomAccessFile raf = null;
+        FileChannel wfc = null;
+
+        FileInputStream fis = null;
+        FileChannel rfc = null;
+
+        try {
+            raf =  new RandomAccessFile(f, "rw");
+            wfc = raf.getChannel();
+
+            fis = new FileInputStream(tfile);
+            rfc = fis.getChannel();
+
+            ByteBuffer bb = MappedByteBuffer.allocate(BAD_FILE_LENGTH);
+            rfc.read(bb);
+            bb.rewind();
+            wfc.write(bb);
+            wfc.truncate(BAD_FILE_LENGTH);
+        } finally {
+            wfc.close();
+            raf.close();
+            rfc.close();
+            fis.close();
+        }
+        System.out.println("file length = " + f.length());
+    }
+
+    static void createJavaFile() throws IOException {
+        FileOutputStream fos = null;
+        try {
+            fos = new FileOutputStream(TEST2_JAVA);
+            PrintStream ps = new PrintStream(fos);
+            ps.println("public class " + TEST2_FILE_NAME +
+                    " {" + TEST_FILE_NAME + " b = new " +
+                    TEST_FILE_NAME  + " ();}");
+        } finally {
+            fos.close();
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        createClassFile();
+        enlargeClassFile();
+        createJavaFile();
+        Thread t = new Thread () {
+            @Override
+            public void run() {
+                String cmds[] = {"-verbose", "-cp", ".", TEST2_JAVA};
+                int ret = com.sun.tools.javac.Main.compile(cmds);
+                System.out.println("test compilation returns: " + ret);
+            }
+        };
+        t.start();
+        t.join(1000*10);
+        System.out.println(t.getState());
+        if (t.isAlive()) {
+            throw new RuntimeException("Error: compilation is looping");
+        }
+    }
+}

From 66b5a3c0ed41fccaca0c354b429096c064e7289c Mon Sep 17 00:00:00 2001
From: Andrew Brygin 
Date: Mon, 20 Dec 2010 10:38:55 +0300
Subject: [PATCH 24/94] 6736178: java.awt.image.SampleModel constructor
 unexpectedly throws IllegalArgumentException

Reviewed-by: jgodinez, prr
---
 jdk/src/share/classes/java/awt/image/SampleModel.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/jdk/src/share/classes/java/awt/image/SampleModel.java b/jdk/src/share/classes/java/awt/image/SampleModel.java
index 0bdb6a5ba97..9e66a763b7c 100644
--- a/jdk/src/share/classes/java/awt/image/SampleModel.java
+++ b/jdk/src/share/classes/java/awt/image/SampleModel.java
@@ -121,7 +121,7 @@ public abstract class SampleModel
      */
     public SampleModel(int dataType, int w, int h, int numBands)
     {
-        float size = (float)w*h;
+        long size = (long)w * h;
         if (w <= 0 || h <= 0) {
             throw new IllegalArgumentException("Width ("+w+") and height ("+
                                                h+") must be > 0");

From 178b7bb4c1d523cc6215a9dd73777f40aea92d37 Mon Sep 17 00:00:00 2001
From: Bob Vandette 
Date: Mon, 20 Dec 2010 14:30:24 -0500
Subject: [PATCH 25/94] 7007769: VM crashes with SIGBUS writing PerfData if tmp
 space is full

Fill perfdata file with zeros to verify available disk space

Reviewed-by: coleenp, kamg
---
 hotspot/src/os/linux/vm/perfMemory_linux.cpp | 24 +++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
index db5340f9d7c..1cd430cfbc7 100644
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
@@ -635,7 +635,29 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
     return -1;
   }
 
-  return fd;
+  // Verify that we have enough disk space for this file.
+  // We'll get random SIGBUS crashes on memory accesses if
+  // we don't.
+
+  for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) {
+    int zero_int = 0;
+    result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
+    if (result == -1 ) break;
+    RESTARTABLE(::write(fd, &zero_int, 1), result);
+    if (result != 1) {
+      if (errno == ENOSPC) {
+        warning("Insufficient space for shared memory file:\n   %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
+      }
+      break;
+    }
+  }
+
+  if (result != -1) {
+    return fd;
+  } else {
+    RESTARTABLE(::close(fd), result);
+    return -1;
+  }
 }
 
 // open the shared memory file for the given user and vmid. returns

From b1df6e0d01be81fb0f24b0ac11f664187c8652ff Mon Sep 17 00:00:00 2001
From: Masayoshi Okutsu 
Date: Tue, 21 Dec 2010 10:58:23 +0900
Subject: [PATCH 26/94] 6943959: NumericShaper API doc doesn't describe
 ARABIC/EASTERN_ARABIC precedence

Reviewed-by: peytoia
---
 .../classes/java/awt/font/NumericShaper.java  | 57 ++++++++++++++-----
 1 file changed, 44 insertions(+), 13 deletions(-)

diff --git a/jdk/src/share/classes/java/awt/font/NumericShaper.java b/jdk/src/share/classes/java/awt/font/NumericShaper.java
index 0c57c299fb6..c8100bfb0de 100644
--- a/jdk/src/share/classes/java/awt/font/NumericShaper.java
+++ b/jdk/src/share/classes/java/awt/font/NumericShaper.java
@@ -58,20 +58,20 @@ import java.util.Set;
  * It is also possible to perform numeric shaping explicitly using instances
  * of NumericShaper, as this code snippet demonstrates:
*
- *   char[] text = ...;
- *   // shape all EUROPEAN digits (except zero) to ARABIC digits
- *   NumericShaper shaper = NumericShaper.getShaper(NumericShaper.ARABIC);
- *   shaper.shape(text, start, count);
+ * char[] text = ...;
+ * // shape all EUROPEAN digits (except zero) to ARABIC digits
+ * NumericShaper shaper = NumericShaper.getShaper(NumericShaper.ARABIC);
+ * shaper.shape(text, start, count);
  *
- *   // shape European digits to ARABIC digits if preceding text is Arabic, or
- *   // shape European digits to TAMIL digits if preceding text is Tamil, or
- *   // leave European digits alone if there is no preceding text, or
- *   // preceding text is neither Arabic nor Tamil
- *   NumericShaper shaper =
- *      NumericShaper.getContextualShaper(NumericShaper.ARABIC |
- *                                              NumericShaper.TAMIL,
- *                                              NumericShaper.EUROPEAN);
- *   shaper.shape(text, start, count);
+ * // shape European digits to ARABIC digits if preceding text is Arabic, or
+ * // shape European digits to TAMIL digits if preceding text is Tamil, or
+ * // leave European digits alone if there is no preceding text, or
+ * // preceding text is neither Arabic nor Tamil
+ * NumericShaper shaper =
+ *     NumericShaper.getContextualShaper(NumericShaper.ARABIC |
+ *                                         NumericShaper.TAMIL,
+ *                                       NumericShaper.EUROPEAN);
+ * shaper.shape(text, start, count);
  * 
* *

Bit mask- and enum-based Unicode ranges

@@ -99,6 +99,37 @@ import java.util.Set; * values are specified, such as {@code NumericShaper.Range.BALINESE}, * those ranges are ignored. * + *

Decimal Digits Precedence

+ * + *

A Unicode range may have more than one set of decimal digits. If + * multiple decimal digits sets are specified for the same Unicode + * range, one of the sets will take precedence as follows. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Unicode RangeNumericShaper ConstantsPrecedence
Arabic{@link NumericShaper#ARABIC NumericShaper.ARABIC}
+ * {@link NumericShaper#EASTERN_ARABIC NumericShaper.EASTERN_ARABIC}
{@link NumericShaper#EASTERN_ARABIC NumericShaper.EASTERN_ARABIC}
{@link NumericShaper.Range#ARABIC}
+ * {@link NumericShaper.Range#EASTERN_ARABIC}
{@link NumericShaper.Range#EASTERN_ARABIC}
Tai Tham{@link NumericShaper.Range#TAI_THAM_HORA}
+ * {@link NumericShaper.Range#TAI_THAM_THAM}
{@link NumericShaper.Range#TAI_THAM_THAM}
+ * * @since 1.4 */ From 6d0bcba475c1124791ad5ecc9c5bd6ccdc6ee9eb Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Tue, 21 Dec 2010 11:20:32 +0900 Subject: [PATCH 27/94] 7007905: javazic produces wrong line numbers Reviewed-by: peytoia --- jdk/make/tools/src/build/tools/javazic/Zoneinfo.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java b/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java index 143c687d51b..872cc1144c8 100644 --- a/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java +++ b/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java @@ -222,6 +222,7 @@ class Zoneinfo { boolean continued = false; Zone zone = null; String l; + lineNum = 0; try { while ((line = in.readLine()) != null) { From e970ef61829c220eb09eedfbe8aedf9a567a6ed1 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 21 Dec 2010 04:37:30 -0800 Subject: [PATCH 28/94] 7008165: Garbage in ClassFormatError message When bootstrap_method_ref in BootstrapMethods attribute points to a wrong CP entry (non-MethodHandle), JVM throws ClassFormatError with a message, where method index and class file name is garbage. Reviewed-by: iveresov --- hotspot/src/share/vm/classfile/classFileParser.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 3712c8ae479..3779fc7d67a 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -2386,19 +2386,21 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHa valid_cp_range(bootstrap_method_index, cp_size) && cp->tag_at(bootstrap_method_index).is_method_handle(), "bootstrap_method_index %u has bad constant type in class file %s", + bootstrap_method_index, CHECK); operands->short_at_put(operand_fill_index++, bootstrap_method_index); operands->short_at_put(operand_fill_index++, argument_count); cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc] for (int j = 0; j < argument_count; j++) { - u2 arg_index = cfs->get_u2_fast(); + u2 argument_index = cfs->get_u2_fast(); check_property( - valid_cp_range(arg_index, cp_size) && - cp->tag_at(arg_index).is_loadable_constant(), + valid_cp_range(argument_index, cp_size) && + cp->tag_at(argument_index).is_loadable_constant(), "argument_index %u has bad constant type in class file %s", + argument_index, CHECK); - operands->short_at_put(operand_fill_index++, arg_index); + operands->short_at_put(operand_fill_index++, argument_index); } } From 85dd27928359295a2f5e1000199ffa5335dcb5a4 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 21 Dec 2010 13:56:40 -0800 Subject: [PATCH 29/94] 7003130: assert(iterations Date: Tue, 21 Dec 2010 16:14:14 -0800 Subject: [PATCH 30/94] 4940539: Constructor of java.util.Locale should handle ISO 639-2 Language Codes Reviewed-by: okutsu --- jdk/src/share/classes/java/util/Locale.java | 9 +++++-- jdk/test/java/util/Locale/LocaleTest.java | 26 +++++++++++++++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/jdk/src/share/classes/java/util/Locale.java b/jdk/src/share/classes/java/util/Locale.java index ecaa9cca68a..1f0fbba1eae 100644 --- a/jdk/src/share/classes/java/util/Locale.java +++ b/jdk/src/share/classes/java/util/Locale.java @@ -1449,10 +1449,15 @@ public final class Locale implements Cloneable, Serializable { * three-letter language abbreviation is not available for this locale. */ public String getISO3Language() throws MissingResourceException { - String language3 = getISO3Code(_baseLocale.getLanguage(), LocaleISOData.isoLanguageTable); + String lang = _baseLocale.getLanguage(); + if (lang.length() == 3) { + return lang; + } + + String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable); if (language3 == null) { throw new MissingResourceException("Couldn't find 3-letter language code for " - + _baseLocale.getLanguage(), "FormatData_" + toString(), "ShortLanguage"); + + lang, "FormatData_" + toString(), "ShortLanguage"); } return language3; } diff --git a/jdk/test/java/util/Locale/LocaleTest.java b/jdk/test/java/util/Locale/LocaleTest.java index af00c6bba6c..0c21a8ef354 100644 --- a/jdk/test/java/util/Locale/LocaleTest.java +++ b/jdk/test/java/util/Locale/LocaleTest.java @@ -24,7 +24,8 @@ * @test * @bug 4052404 4052440 4084688 4092475 4101316 4105828 4107014 4107953 4110613 * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951 - * 4147315 4147317 4147552 4335196 4778440 5010672 6475525 6544471 6627549 6786276 + * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549 + * 6786276 * @summary test Locales */ /* @@ -895,17 +896,28 @@ test commented out pending API-change approval } /** - * @bug 4147317 - * java.util.Locale.getISO3Language() works wrong for non ISO-3166 codes. - * Should throw an exception for unknown locales + * @bug 4147317 4940539 + * java.util.Locale.getISO3Language() works wrong for non ISO-639 codes. + * Should throw an exception for unknown locales, except they have three + * letter language codes. */ public void Test4147317() { - // Try with codes that are the wrong length but happen to match text - // at a valid offset in the mapping table + // Try a three letter language code, and check whether it is + // returned as is. Locale locale = new Locale("aaa", "CCC"); + String result = locale.getISO3Language(); + if (!result.equals("aaa")) { + errln("ERROR: getISO3Language() returns: " + result + + " for locale '" + locale + "' rather than returning it as is" ); + } + + // Try an invalid two letter language code, and check whether it + // throws a MissingResourceException. + locale = new Locale("zz", "CCC"); + try { - String result = locale.getISO3Language(); + result = locale.getISO3Language(); errln("ERROR: getISO3Language() returns: " + result + " for locale '" + locale + "' rather than exception" ); From 97663382e1311193ecbeafe734772ac89caf1618 Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Tue, 21 Dec 2010 16:29:10 -0800 Subject: [PATCH 31/94] 7008378: javac bootstrap launcher fails on cygwin when called via an absolute path Use cygpath if it is cygwin Reviewed-by: ksrini --- langtools/make/Makefile | 2 +- langtools/make/build.xml | 6 ++++++ langtools/src/share/bin/launcher.sh-template | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/langtools/make/Makefile b/langtools/make/Makefile index 1ee42703ee6..bea2afa8141 100644 --- a/langtools/make/Makefile +++ b/langtools/make/Makefile @@ -187,7 +187,7 @@ all: build clobber: clean # All ant targets of interest -ANT_TARGETS = build clean sanity post-sanity diagnostics # for now +ANT_TARGETS = build clean sanity post-sanity diagnostics build-all-tools # for now # Create diagnostics log (careful, ant 1.8.0 -diagnostics always does an exit 1) $(OUTPUTDIR)/build/ant-diagnostics.log: diff --git a/langtools/make/build.xml b/langtools/make/build.xml index ec3aaf8763e..0ab91613c65 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -327,6 +327,7 @@ + + + + + + Date: Tue, 21 Dec 2010 23:39:42 -0500 Subject: [PATCH 32/94] 7008444: Remove unnecessary include of stdint.h in java_md.c Remove unnecessary include of stdint.h in java_md.c Reviewed-by: brutisso, kvn --- hotspot/src/os/posix/launcher/java_md.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hotspot/src/os/posix/launcher/java_md.c b/hotspot/src/os/posix/launcher/java_md.c index 78a1ca33a8f..3ee0f20a77d 100644 --- a/hotspot/src/os/posix/launcher/java_md.c +++ b/hotspot/src/os/posix/launcher/java_md.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include From ef4ac58dde52f2bd3c3bbdc870e022747bd46def Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Tue, 21 Dec 2010 22:57:17 -0800 Subject: [PATCH 33/94] 7008466: Tiered: Enable testing of tiered compilation in JPRT Add running specjvm98 and specjbb2005 with tiered compilation enabled with JPRT. Reviewed-by: kvn --- hotspot/make/jprt.properties | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index 04554aabe92..cea29d4b585 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -150,6 +150,7 @@ jprt.build.targets= \ jprt.my.solaris.sparc.test.targets= \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jvm98, \ + ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \ ${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \ @@ -168,6 +169,7 @@ jprt.my.solaris.sparc.test.targets= \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_G1, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParOldGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_default, \ + ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jbb_default_tiered, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \ @@ -176,6 +178,7 @@ jprt.my.solaris.sparc.test.targets= \ jprt.my.solaris.sparcv9.test.targets= \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.sparcv9}-product-c2-runThese, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default, \ @@ -193,6 +196,7 @@ jprt.my.solaris.sparcv9.test.targets= \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default, \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default_tiered, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_CMS, \ @@ -201,6 +205,7 @@ jprt.my.solaris.sparcv9.test.targets= \ jprt.my.solaris.x64.test.targets= \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98, \ + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.x64}-product-c2-runThese, \ ${jprt.my.solaris.x64}-product-c2-runThese_Xcomp, \ @@ -219,6 +224,7 @@ jprt.my.solaris.x64.test.targets= \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default, \ + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_SerialGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \ @@ -227,6 +233,7 @@ jprt.my.solaris.x64.test.targets= \ jprt.my.solaris.i586.test.targets= \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ + ${jprt.my.solaris.i586}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \ ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp, \ @@ -253,6 +260,7 @@ jprt.my.solaris.i586.test.targets= \ ${jprt.my.solaris.i586}-product-c1-GCOld_G1, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParOldGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default, \ + ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default_tiered, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_G1, \ @@ -260,6 +268,7 @@ jprt.my.solaris.i586.test.targets= \ jprt.my.linux.i586.test.targets = \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ + ${jprt.my.linux.i586}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.linux.i586}-product-c1-runThese_Xcomp, \ ${jprt.my.linux.i586}-fastdebug-c1-runThese_Xshare, \ @@ -279,6 +288,7 @@ jprt.my.linux.i586.test.targets = \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_G1, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParOldGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_default, \ + ${jprt.my.linux.i586}-{product|fastdebug}-c2-jbb_default_tiered, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_G1, \ @@ -286,6 +296,7 @@ jprt.my.linux.i586.test.targets = \ jprt.my.linux.x64.test.targets = \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \ + ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ @@ -302,12 +313,14 @@ jprt.my.linux.x64.test.targets = \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default, \ + ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_G1, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParOldGC jprt.my.windows.i586.test.targets = \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ + ${jprt.my.windows.i586}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.windows.i586}-product-{c1|c2}-runThese, \ ${jprt.my.windows.i586}-product-{c1|c2}-runThese_Xcomp, \ @@ -327,6 +340,7 @@ jprt.my.windows.i586.test.targets = \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_G1, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParOldGC, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jbb_default, \ + ${jprt.my.windows.i586}-{product|fastdebug}-c2-jbb_default_tiered, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParallelGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_G1, \ @@ -334,6 +348,7 @@ jprt.my.windows.i586.test.targets = \ jprt.my.windows.x64.test.targets = \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98, \ + ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98_tiered, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.windows.x64}-product-c2-runThese, \ ${jprt.my.windows.x64}-product-c2-runThese_Xcomp, \ @@ -351,6 +366,7 @@ jprt.my.windows.x64.test.targets = \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default, \ + ${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ ${jprt.my.windows.x64}-product-c2-jbb_CMS, \ ${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \ ${jprt.my.windows.x64}-product-c2-jbb_G1, \ From a8a98509e7859f2e9ca89f810c8b0157dd5909b6 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Wed, 22 Dec 2010 02:02:53 -0800 Subject: [PATCH 34/94] 7007377: JSR 292 MethodHandlesTest.testCastFailure fails on SPARC with -Xcomp +DeoptimizeALot Reviewed-by: kvn, jrose --- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 70 ++++++------ hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 104 ++++++++++-------- hotspot/src/share/vm/prims/methodHandles.cpp | 13 ++- hotspot/src/share/vm/prims/methodHandles.hpp | 6 +- hotspot/src/share/vm/runtime/init.cpp | 3 - 5 files changed, 99 insertions(+), 97 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 699f9151b8c..2fb2e56d8b3 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -395,18 +395,23 @@ int MethodHandles::adapter_conversion_ops_supported_mask() { // // Generate an "entry" field for a method handle. // This determines how the method handle will respond to calls. -void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { +void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) { // Here is the register state during an interpreted call, // as set up by generate_method_handle_interpreter_entry(): // - G5: garbage temp (was MethodHandle.invoke methodOop, unused) // - G3: receiver method handle // - O5_savedSP: sender SP (must preserve) - Register O0_argslot = O0; - Register O1_scratch = O1; - Register O2_scratch = O2; - Register O3_scratch = O3; - Register G5_index = G5; + const Register O0_argslot = O0; + const Register O1_scratch = O1; + const Register O2_scratch = O2; + const Register O3_scratch = O3; + const Register G5_index = G5; + + // Argument registers for _raise_exception. + const Register O0_code = O0; + const Register O1_actual = O1; + const Register O2_required = O2; guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); @@ -439,48 +444,36 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan case _raise_exception: { // Not a real MH entry, but rather shared code for raising an - // exception. Extra local arguments are passed in scratch - // registers, as required type in O3, failing object (or NULL) - // in O2, failing bytecode type in O1. + // exception. Since we use a C2I adapter to set up the + // interpreter state, arguments are expected in compiler + // argument registers. + methodHandle mh(raise_exception_method()); + address c2i_entry = methodOopDesc::make_adapters(mh, CATCH); __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. - // Push arguments as if coming from the interpreter. - Register O0_scratch = O0_argslot; - int stackElementSize = Interpreter::stackElementSize; - - // Make space on the stack for the arguments and set Gargs - // correctly. - __ sub(SP, 4*stackElementSize, SP); // Keep stack aligned. - __ add(SP, (frame::varargs_offset)*wordSize - 1*Interpreter::stackElementSize + STACK_BIAS + BytesPerWord, Gargs); - - // void raiseException(int code, Object actual, Object required) - __ st( O1_scratch, Address(Gargs, 2*stackElementSize)); // code - __ st_ptr(O2_scratch, Address(Gargs, 1*stackElementSize)); // actual - __ st_ptr(O3_scratch, Address(Gargs, 0*stackElementSize)); // required - - Label no_method; + Label L_no_method; // FIXME: fill in _raise_exception_method with a suitable sun.dyn method __ set(AddressLiteral((address) &_raise_exception_method), G5_method); __ ld_ptr(Address(G5_method, 0), G5_method); __ tst(G5_method); - __ brx(Assembler::zero, false, Assembler::pn, no_method); + __ brx(Assembler::zero, false, Assembler::pn, L_no_method); __ delayed()->nop(); - int jobject_oop_offset = 0; + const int jobject_oop_offset = 0; __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method); __ tst(G5_method); - __ brx(Assembler::zero, false, Assembler::pn, no_method); + __ brx(Assembler::zero, false, Assembler::pn, L_no_method); __ delayed()->nop(); __ verify_oop(G5_method); - __ jump_indirect_to(G5_method_fie, O1_scratch); + __ jump_to(AddressLiteral(c2i_entry), O3_scratch); __ delayed()->nop(); // If we get here, the Java runtime did not do its job of creating the exception. // Do something that is at least causes a valid throw from the interpreter. - __ bind(no_method); - __ unimplemented("_raise_exception no method"); + __ bind(L_no_method); + __ unimplemented("call throw_WrongMethodType_entry"); } break; @@ -570,10 +563,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // Throw an exception. // For historical reasons, it will be IncompatibleClassChangeError. __ unimplemented("not tested yet"); - __ ld_ptr(Address(O1_intf, java_mirror_offset), O3_scratch); // required interface - __ mov(O0_klass, O2_scratch); // bad receiver - __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); - __ delayed()->mov(Bytecodes::_invokeinterface, O1_scratch); // who is complaining? + __ ld_ptr(Address(O1_intf, java_mirror_offset), O2_required); // required interface + __ mov( O0_klass, O1_actual); // bad receiver + __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch); + __ delayed()->mov(Bytecodes::_invokeinterface, O0_code); // who is complaining? } break; @@ -663,11 +656,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ check_klass_subtype(O1_scratch, G5_klass, O0_argslot, O2_scratch, done); // If we get here, the type check failed! - __ ldsw(G3_amh_vmargslot, O0_argslot); // reload argslot field - __ load_heap_oop(G3_amh_argument, O3_scratch); // required class - __ ld_ptr(vmarg, O2_scratch); // bad object - __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); - __ delayed()->mov(Bytecodes::_checkcast, O1_scratch); // who is complaining? + __ load_heap_oop(G3_amh_argument, O2_required); // required class + __ ld_ptr( vmarg, O1_actual); // bad object + __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch); + __ delayed()->mov(Bytecodes::_checkcast, O0_code); // who is complaining? __ bind(done); // Get the new MH: diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 5c707fec000..f92beb4839f 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -385,9 +385,12 @@ int MethodHandles::adapter_conversion_ops_supported_mask() { // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS. } +//------------------------------------------------------------------------------ +// MethodHandles::generate_method_handle_stub +// // Generate an "entry" field for a method handle. // This determines how the method handle will respond to calls. -void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { +void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) { // Here is the register state during an interpreted call, // as set up by generate_method_handle_interpreter_entry(): // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused) @@ -396,14 +399,21 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) // - rdx: garbage temp, can blow away - Register rcx_recv = rcx; - Register rax_argslot = rax; - Register rbx_temp = rbx; - Register rdx_temp = rdx; + const Register rcx_recv = rcx; + const Register rax_argslot = rax; + const Register rbx_temp = rbx; + const Register rdx_temp = rdx; // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls) // and gen_c2i_adapter (from compiled calls): - Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); + const Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); + + // Argument registers for _raise_exception. + // 32-bit: Pass first two oop/int args in registers ECX and EDX. + const Register rarg0_code = LP64_ONLY(j_rarg0) NOT_LP64(rcx); + const Register rarg1_actual = LP64_ONLY(j_rarg1) NOT_LP64(rdx); + const Register rarg2_required = LP64_ONLY(j_rarg2) NOT_LP64(rdi); + assert_different_registers(rarg0_code, rarg1_actual, rarg2_required, saved_last_sp); guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); @@ -437,47 +447,41 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan switch ((int) ek) { case _raise_exception: { - // Not a real MH entry, but rather shared code for raising an exception. - // Extra local arguments are pushed on stack, as required type at TOS+8, - // failing object (or NULL) at TOS+4, failing bytecode type at TOS. - // Beyond those local arguments are the PC, of course. - Register rdx_code = rdx_temp; - Register rcx_fail = rcx_recv; - Register rax_want = rax_argslot; - Register rdi_pc = rdi; - __ pop(rdx_code); // TOS+0 - __ pop(rcx_fail); // TOS+4 - __ pop(rax_want); // TOS+8 - __ pop(rdi_pc); // caller PC + // Not a real MH entry, but rather shared code for raising an + // exception. Since we use a C2I adapter to set up the + // interpreter state, arguments are expected in compiler + // argument registers. + methodHandle mh(raise_exception_method()); + address c2i_entry = methodOopDesc::make_adapters(mh, CHECK); - __ mov(rsp, rsi); // cut the stack back to where the caller started - - // Repush the arguments as if coming from the interpreter. - __ push(rdx_code); - __ push(rcx_fail); - __ push(rax_want); + const Register rdi_pc = rax; + __ pop(rdi_pc); // caller PC + __ mov(rsp, saved_last_sp); // cut the stack back to where the caller started Register rbx_method = rbx_temp; - Label no_method; + Label L_no_method; // FIXME: fill in _raise_exception_method with a suitable sun.dyn method __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); __ testptr(rbx_method, rbx_method); - __ jccb(Assembler::zero, no_method); - int jobject_oop_offset = 0; + __ jccb(Assembler::zero, L_no_method); + + const int jobject_oop_offset = 0; __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject __ testptr(rbx_method, rbx_method); - __ jccb(Assembler::zero, no_method); + __ jccb(Assembler::zero, L_no_method); __ verify_oop(rbx_method); - __ push(rdi_pc); // and restore caller PC - __ jmp(rbx_method_fie); + + // 32-bit: push remaining arguments as if coming from the compiler. + NOT_LP64(__ push(rarg2_required)); + + __ push(rdi_pc); // restore caller PC + __ jump(ExternalAddress(c2i_entry)); // do C2I transition // If we get here, the Java runtime did not do its job of creating the exception. // Do something that is at least causes a valid throw from the interpreter. - __ bind(no_method); - __ pop(rax_want); - __ pop(rcx_fail); - __ push(rax_want); - __ push(rcx_fail); + __ bind(L_no_method); + __ push(rarg2_required); + __ push(rarg1_actual); __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); } break; @@ -572,9 +576,11 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ bind(no_such_interface); // Throw an exception. // For historical reasons, it will be IncompatibleClassChangeError. - __ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface - __ push(rcx_recv); // bad receiver - __ push((int)Bytecodes::_invokeinterface); // who is complaining? + __ mov(rbx_temp, rcx_recv); // rarg2_required might be RCX + assert_different_registers(rarg2_required, rbx_temp); + __ movptr(rarg2_required, Address(rdx_intf, java_mirror_offset)); // required interface + __ mov( rarg1_actual, rbx_temp); // bad receiver + __ movl( rarg0_code, (int) Bytecodes::_invokeinterface); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); } break; @@ -669,10 +675,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field __ movptr(rdx_temp, vmarg); - __ load_heap_oop(rbx_klass, rcx_amh_argument); // required class - __ push(rbx_klass); - __ push(rdx_temp); // bad object - __ push((int)Bytecodes::_checkcast); // who is complaining? + assert_different_registers(rarg2_required, rdx_temp); + __ load_heap_oop(rarg2_required, rcx_amh_argument); // required class + __ mov( rarg1_actual, rdx_temp); // bad object + __ movl( rarg0_code, (int) Bytecodes::_checkcast); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ bind(done); @@ -1189,16 +1195,18 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan __ bind(bad_array_klass); UNPUSH_RSI_RDI; - __ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type - __ pushptr(vmarg); // bad array - __ push((int)Bytecodes::_aaload); // who is complaining? + assert(!vmarg.uses(rarg2_required), "must be different registers"); + __ movptr(rarg2_required, Address(rdx_array_klass, java_mirror_offset)); // required type + __ movptr(rarg1_actual, vmarg); // bad array + __ movl( rarg0_code, (int) Bytecodes::_aaload); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ bind(bad_array_length); UNPUSH_RSI_RDI; - __ push(rcx_recv); // AMH requiring a certain length - __ pushptr(vmarg); // bad array - __ push((int)Bytecodes::_arraylength); // who is complaining? + assert(!vmarg.uses(rarg2_required), "must be different registers"); + __ mov (rarg2_required, rcx_recv); // AMH requiring a certain length + __ movptr(rarg1_actual, vmarg); // bad array + __ movl( rarg0_code, (int) Bytecodes::_arraylength); // who is complaining? __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); #undef UNPUSH_RSI_RDI diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 6c33186561b..1b2c3c60d4a 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -111,7 +111,7 @@ bool MethodHandles::spot_check_entry_names() { //------------------------------------------------------------------------------ // MethodHandles::generate_adapters // -void MethodHandles::generate_adapters() { +void MethodHandles::generate_adapters(TRAPS) { if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; assert(_adapter_code == NULL, "generate only once"); @@ -123,20 +123,20 @@ void MethodHandles::generate_adapters() { vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters"); CodeBuffer code(_adapter_code); MethodHandlesAdapterGenerator g(&code); - g.generate(); + g.generate(CHECK); } //------------------------------------------------------------------------------ // MethodHandlesAdapterGenerator::generate // -void MethodHandlesAdapterGenerator::generate() { +void MethodHandlesAdapterGenerator::generate(TRAPS) { // Generate generic method handle adapters. for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; ek < MethodHandles::_EK_LIMIT; ek = MethodHandles::EntryKind(1 + (int)ek)) { StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek); + MethodHandles::generate_method_handle_stub(_masm, ek, CHECK); } } @@ -2645,5 +2645,10 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) MethodHandles::set_enabled(true); } } + + // Generate method handles adapters if enabled. + if (MethodHandles::enabled()) { + MethodHandles::generate_adapters(CHECK); + } } JVM_END diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 351dc33f6e7..f66f0e026d2 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -294,11 +294,11 @@ class MethodHandles: AllStatic { enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; // Generate MethodHandles adapters. - static void generate_adapters(); + static void generate_adapters(TRAPS); // Called from InterpreterGenerator and MethodHandlesAdapterGenerator. static address generate_method_handle_interpreter_entry(MacroAssembler* _masm); - static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek); + static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek, TRAPS); // argument list parsing static int argument_slot(oop method_type, int arg); @@ -530,7 +530,7 @@ class MethodHandlesAdapterGenerator : public StubCodeGenerator { public: MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} - void generate(); + void generate(TRAPS); }; #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp index 7c190469341..1f09c368365 100644 --- a/hotspot/src/share/vm/runtime/init.cpp +++ b/hotspot/src/share/vm/runtime/init.cpp @@ -125,9 +125,6 @@ jint init_globals() { javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init - // Generate MethodHandles adapters. - MethodHandles::generate_adapters(); - // Although we'd like to, we can't easily do a heap verify // here because the main thread isn't yet a JavaThread, so // its TLAB may not be made parseable from the usual interfaces. From 2ee20ffcdb29dbc25119ab2a3c069179aee60c60 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Wed, 22 Dec 2010 17:37:34 +0300 Subject: [PATCH 35/94] 6998323: Unexpected color change after invoking SplashScreen.update() Fix the blendRGB() function Reviewed-by: art, dcherepanov --- .../awt/splashscreen/splashscreen_gfx_impl.h | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h index f2f367c6dfa..a0fd446e94a 100644 --- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h +++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h @@ -88,27 +88,18 @@ ditherColor(rgbquad_t value, ImageFormat * format, int row, int col) /* blend (lerp between) two rgb quads src and dst alpha is ignored the algorithm: src*alpha+dst*(1-alpha)=(src-dst)*alpha+dst, rb and g are done separately - it's possible to verify that it's almost accurate indeed */ - +*/ INLINE rgbquad_t blendRGB(rgbquad_t dst, rgbquad_t src, rgbquad_t alpha) { - const rgbquad_t dstrb = dst & 0xFF00FF; - const rgbquad_t dstg = dst & 0xFF00; - const rgbquad_t srcrb = src & 0xFF00FF; - const rgbquad_t srcg = src & 0xFF00; + const rgbquad_t a = alpha; + const rgbquad_t a1 = 0xFF - alpha; - rgbquad_t drb = srcrb - dstrb; - rgbquad_t dg = srcg - dstg; - - alpha += 1; - - drb *= alpha; - dg *= alpha; - drb >>= 8; - dg >>= 8; - - return ((drb + dstrb) & 0xFF00FF) | ((dg + dstg) & 0xFF00); + return MAKE_QUAD( + (rgbquad_t)((QUAD_RED(src) * a + QUAD_RED(dst) * a1) / 0xFF), + (rgbquad_t)((QUAD_GREEN(src) * a + QUAD_GREEN(dst) * a1) / 0xFF), + (rgbquad_t)((QUAD_BLUE(src) * a + QUAD_BLUE(dst) * a1) / 0xFF), + 0); } /* scales rgb quad by alpha. basically similar to what's above. src alpha is retained. From 7098ab98d5139bb1b80c102ab2bc0767f6d6be91 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Wed, 22 Dec 2010 11:24:21 -0500 Subject: [PATCH 36/94] 6961186: Better VM handling of unexpected exceptions from application native code Trap uncaught C++ exception on Windows and Solaris and generate hs_err report. Reviewed-by: coleenp, bobv, dholmes --- hotspot/src/os/solaris/vm/os_solaris.cpp | 9 +++++++++ hotspot/src/os/windows/vm/os_windows.cpp | 20 ++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 0141763216a..7b08e979d2f 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -80,6 +80,7 @@ // put OS-includes here # include # include +# include # include # include # include @@ -1475,6 +1476,13 @@ sigset_t* os::Solaris::allowdebug_blocked_signals() { return &allowdebug_blocked_sigs; } + +void _handle_uncaught_cxx_exception() { + VMError err("An uncaught C++ exception"); + err.report_and_die(); +} + + // First crack at OS-specific initialization, from inside the new thread. void os::initialize_thread() { int r = thr_main() ; @@ -1564,6 +1572,7 @@ void os::initialize_thread() { // use the dynamic check for T2 libthread. os::Solaris::init_thread_fpu_state(); + std::set_terminate(_handle_uncaught_cxx_exception); } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 1cc90f7b642..e6fd1a6b223 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * CopyrighT (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2007,6 +2007,16 @@ struct siglabel { int number; }; +// All Visual C++ exceptions thrown from code generated by the Microsoft Visual +// C++ compiler contain this error code. Because this is a compiler-generated +// error, the code is not listed in the Win32 API header files. +// The code is actually a cryptic mnemonic device, with the initial "E" +// standing for "exception" and the final 3 bytes (0x6D7363) representing the +// ASCII values of "msc". + +#define EXCEPTION_UNCAUGHT_CXX_EXCEPTION 0xE06D7363 + + struct siglabel exceptlabels[] = { def_excpt(EXCEPTION_ACCESS_VIOLATION), def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT), @@ -2031,6 +2041,7 @@ struct siglabel exceptlabels[] = { def_excpt(EXCEPTION_INVALID_DISPOSITION), def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), + def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), NULL, 0 }; @@ -2264,7 +2275,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } } - if (t != NULL && t->is_Java_thread()) { JavaThread* thread = (JavaThread*) t; bool in_java = thread->thread_state() == _thread_in_Java; @@ -2468,8 +2478,9 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } // switch } #ifndef _WIN64 - if ((thread->thread_state() == _thread_in_Java) || - (thread->thread_state() == _thread_in_native) ) + if (((thread->thread_state() == _thread_in_Java) || + (thread->thread_state() == _thread_in_native)) && + exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION) { LONG result=Handle_FLT_Exception(exceptionInfo); if (result==EXCEPTION_CONTINUE_EXECUTION) return result; @@ -2493,6 +2504,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { case EXCEPTION_ILLEGAL_INSTRUCTION_2: case EXCEPTION_INT_OVERFLOW: case EXCEPTION_INT_DIVIDE_BY_ZERO: + case EXCEPTION_UNCAUGHT_CXX_EXCEPTION: { report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); } From decbe031fc2bb6e09a6d8a26a901de7da8f5b108 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 22 Dec 2010 13:32:58 -0800 Subject: [PATCH 37/94] 7007299: FileFontStrike appears not to be threadsafe? Reviewed-by: igor, jgodinez --- .../share/classes/sun/font/FileFontStrike.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/sun/font/FileFontStrike.java b/jdk/src/share/classes/sun/font/FileFontStrike.java index ce4d87c2a99..ca72867f8cc 100644 --- a/jdk/src/share/classes/sun/font/FileFontStrike.java +++ b/jdk/src/share/classes/sun/font/FileFontStrike.java @@ -58,7 +58,7 @@ public class FileFontStrike extends PhysicalStrike { private static final int SEGINTARRAY = 3; private static final int SEGLONGARRAY = 4; - private int glyphCacheFormat = UNINITIALISED; + private volatile int glyphCacheFormat = UNINITIALISED; /* segmented arrays are blocks of 256 */ private static final int SEGSHIFT = 8; @@ -522,32 +522,33 @@ public class FileFontStrike extends PhysicalStrike { } /* Called only from synchronized code or constructor */ - private void initGlyphCache() { + private synchronized void initGlyphCache() { int numGlyphs = mapper.getNumGlyphs(); - + int tmpFormat = UNINITIALISED; if (segmentedCache) { int numSegments = (numGlyphs + SEGSIZE-1)/SEGSIZE; if (longAddresses) { - glyphCacheFormat = SEGLONGARRAY; + tmpFormat = SEGLONGARRAY; segLongGlyphImages = new long[numSegments][]; this.disposer.segLongGlyphImages = segLongGlyphImages; } else { - glyphCacheFormat = SEGINTARRAY; + tmpFormat = SEGINTARRAY; segIntGlyphImages = new int[numSegments][]; this.disposer.segIntGlyphImages = segIntGlyphImages; } } else { if (longAddresses) { - glyphCacheFormat = LONGARRAY; + tmpFormat = LONGARRAY; longGlyphImages = new long[numGlyphs]; this.disposer.longGlyphImages = longGlyphImages; } else { - glyphCacheFormat = INTARRAY; + tmpFormat = INTARRAY; intGlyphImages = new int[numGlyphs]; this.disposer.intGlyphImages = intGlyphImages; } } + glyphCacheFormat = tmpFormat; } float getGlyphAdvance(int glyphCode) { From 01d8aee41bc19f38909b65a629a8613c148b06bc Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 22 Dec 2010 13:49:23 -0800 Subject: [PATCH 38/94] 6996867: Garbage rendering of LCD text with SRC composite mode Reviewed-by: igor, jgodinez --- .../share/classes/sun/java2d/SurfaceData.java | 2 +- .../Graphics2D/DrawString/LCDTextSrcEa.java | 93 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/Graphics2D/DrawString/LCDTextSrcEa.java diff --git a/jdk/src/share/classes/sun/java2d/SurfaceData.java b/jdk/src/share/classes/sun/java2d/SurfaceData.java index 827a2e78517..ed0d3e01ad5 100644 --- a/jdk/src/share/classes/sun/java2d/SurfaceData.java +++ b/jdk/src/share/classes/sun/java2d/SurfaceData.java @@ -644,7 +644,7 @@ public abstract class SurfaceData sg2d.drawpipe = converter; sg2d.fillpipe = converter; sg2d.shapepipe = converter; - if (sg2d.paintState > sg2d.PAINT_OPAQUECOLOR || + if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR || sg2d.compositeState > sg2d.COMP_ISCOPY) { sg2d.textpipe = colorText; diff --git a/jdk/test/java/awt/Graphics2D/DrawString/LCDTextSrcEa.java b/jdk/test/java/awt/Graphics2D/DrawString/LCDTextSrcEa.java new file mode 100644 index 00000000000..74c228eab67 --- /dev/null +++ b/jdk/test/java/awt/Graphics2D/DrawString/LCDTextSrcEa.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6996867 + * @summary Render as LCD Text in SrcEa composite mode. + */ + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; + +public class LCDTextSrcEa extends Component { + + static int SZ=150; + BufferedImage target = + new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB); + + public static void main(String args[]) { + Frame f = new Frame("LCD Text SrcEa Test"); + f.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + LCDTextSrcEa td = new LCDTextSrcEa(); + f.add("Center", td); + f.pack(); + f.setVisible(true); + } + + public Dimension getPreferredSize() { + return new Dimension(SZ,SZ); + } + + public void paint(Graphics gx) { + + Graphics2D g2d = (Graphics2D) target.getGraphics(); + g2d.setColor(Color.white); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 0.01f)); + g2d.setRenderingHint( + RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR); + g2d.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setColor(Color.black); + g2d.drawString("Some sample text.", 10, 20); + gx.drawImage(target, 0, 0, null); + boolean nongrey = false; + //Test BI: should be some non-greyscale color + for (int px=0;px> 16; + int g = (rgb & 0x00ff00) >> 8; + int b = (rgb & 0x0000ff); + if (r != g || r !=b || g != b) { + nongrey=true; + break; + } + } + } + if (!nongrey) { + throw new RuntimeException("No LCD text found"); + } + } +} From 154dedcd106f8305a865b77f60ed28d3a3335bf2 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Thu, 23 Dec 2010 14:27:32 +0300 Subject: [PATCH 39/94] 7002627: JNI Critical Arrays should be released with the original (unmodified) pointer Reviewed-by: jgodinez, prr --- jdk/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c b/jdk/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c index 1c5b99b250d..ccfeab5cafd 100644 --- a/jdk/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c +++ b/jdk/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c @@ -119,7 +119,8 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile PtrCoord(srcInfo.rasBase, srcInfo.bounds.x1, srcInfo.pixelStride, srcInfo.bounds.y1, srcInfo.scanStride); - unsigned char *pMask = + unsigned char *pMask, *pMaskAlloc; + pMask = pMaskAlloc = (*env)->GetPrimitiveArrayCritical(env, maskArray, 0); if (pMask == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -274,7 +275,7 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile bpos += width * height * sizeof(jint); (*env)->ReleasePrimitiveArrayCritical(env, maskArray, - pMask, JNI_ABORT); + pMaskAlloc, JNI_ABORT); } SurfaceData_InvokeRelease(env, srcOps, &srcInfo); } From 25eeccff380067c07540c94b8a7b9e8bc7d53584 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Thu, 23 Dec 2010 17:39:18 +0300 Subject: [PATCH 40/94] 6973773: JCK manual case JSliderTests.html#JSlider fails in jdk7 b100 Reviewed-by: alexp --- jdk/src/share/classes/javax/swing/JSlider.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/javax/swing/JSlider.java b/jdk/src/share/classes/javax/swing/JSlider.java index 156b9e4fb99..8d188b95bf8 100644 --- a/jdk/src/share/classes/javax/swing/JSlider.java +++ b/jdk/src/share/classes/javax/swing/JSlider.java @@ -40,7 +40,8 @@ import java.beans.*; /** * A component that lets the user graphically select a value by sliding - * a knob within a bounded interval. + * a knob within a bounded interval. The knob is always positioned + * at the points that match integer values within the specified interval. *

* The slider can show both * major tick marks, and minor tick marks between the major ones. The number of From f6993442af869bb85b694350a83dca1d15e937eb Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Thu, 23 Dec 2010 18:25:35 +0300 Subject: [PATCH 41/94] 7007708: TEST: javax/swing/JScrollBar/6542335/bug6542335.java failes agaisnt jdk7 on solaris/linux Reviewed-by: alexp --- .../swing/JScrollBar/6542335/bug6542335.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/jdk/test/javax/swing/JScrollBar/6542335/bug6542335.java b/jdk/test/javax/swing/JScrollBar/6542335/bug6542335.java index 33e95d8ecac..d4ed4736e34 100644 --- a/jdk/test/javax/swing/JScrollBar/6542335/bug6542335.java +++ b/jdk/test/javax/swing/JScrollBar/6542335/bug6542335.java @@ -40,11 +40,13 @@ public class bug6542335 { private static MyScrollBarUI ui; public static void main(String[] args) throws Exception { - Robot robot = new Robot(); + final Robot robot = new Robot(); robot.setAutoDelay(10); SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + final Rectangle[] thumbBounds = new Rectangle[1]; + SwingUtilities.invokeAndWait(new Runnable() { public void run() { final JFrame frame = new JFrame("bug6542335"); @@ -63,25 +65,39 @@ public class bug6542335 { rangeModel.setValue(50); sb.setModel(rangeModel); - frame.add(sb); + frame.add(sb, BorderLayout.NORTH); frame.setSize(200, 100); frame.setVisible(true); + + thumbBounds[0] = new Rectangle(ui.getThumbBounds()); } }); - Rectangle thumbBounds = new Rectangle(ui.getThumbBounds()); - - toolkit.realSync(); - Point l = sb.getLocationOnScreen(); - robot.mouseMove(l.x + (int) (0.75 * sb.getWidth()), l.y + sb.getHeight()/2); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.mouseRelease(InputEvent.BUTTON1_MASK); toolkit.realSync(); - if (!thumbBounds.equals(ui.getThumbBounds())) { - throw new RuntimeException("Test failed"); - } + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Point l = sb.getLocationOnScreen(); + + robot.mouseMove(l.x + (int) (0.75 * sb.getWidth()), l.y + sb.getHeight() / 2); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Rectangle newThumbBounds = ui.getThumbBounds(); + + if (!thumbBounds[0].equals(newThumbBounds)) { + throw new RuntimeException("Test failed.\nOld bounds: " + thumbBounds[0] + + "\nNew bounds: " + newThumbBounds); + } + } + }); } static class MyScrollBarUI extends BasicScrollBarUI { From 336f6c2576fd58ae7b6c3bc637df046340cfe213 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Thu, 23 Dec 2010 07:58:35 -0800 Subject: [PATCH 42/94] 6987812: 2/3 SAJDI: "gHotSpotVMTypes was not initialized properly in the remote process" Change ExportDirectoryTableImpl to return the 'Export RVA' field without modification. Read 'Base Of Data' field in optional header when PE32 format COFF file is read. Refine search for dbgeng.dll and dbghelp.dll. Other cleanups. Reviewed-by: swamyv, poonam --- .../sun/jvm/hotspot/HotSpotTypeDataBase.java | 21 +- .../debugger/win32/coff/COFFFileParser.java | 59 ++++-- .../debugger/win32/coff/DumpExports.java | 57 +++-- .../debugger/win32/coff/TestParser.java | 6 +- .../debugger/windbg/WindbgDebuggerLocal.java | 195 ++++++++++++------ 5 files changed, 221 insertions(+), 117 deletions(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java index 967f8a4f100..9cf6122c761 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,15 +99,8 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { long typeEntrySizeOffset; long typeEntryArrayStride; - typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); - typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); - typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); - typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); - typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); - typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); - typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); - - // Fetch the address of the VMTypeEntry* + // Fetch the address of the VMTypeEntry*. We get this symbol first + // and try to use it to make sure that symbol lookup is working. Address entryAddr = lookupInProcess("gHotSpotVMTypes"); // System.err.println("gHotSpotVMTypes address = " + entryAddr); // Dereference this once to get the pointer to the first VMTypeEntry @@ -118,6 +111,14 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); } + typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); + typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); + typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); + typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); + typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); + typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); + typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); + // Start iterating down it until we find an entry with no name Address typeNameAddr = null; do { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java index b2c988224fd..d29a626598b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,10 +122,14 @@ public class COFFFileParser { private MemoizedObject[] sectionHeaders; private MemoizedObject[] symbols; + // Init stringTable at decl time since other fields init'ed in the + // constructor need the String Table. private MemoizedObject stringTable = new MemoizedObject() { public Object computeValue() { + // the String Table follows the Symbol Table int ptr = getPointerToSymbolTable(); if (ptr == 0) { + // no Symbol Table so no String Table return new StringTable(0); } else { return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols()); @@ -140,6 +144,8 @@ public class COFFFileParser { timeDateStamp = readInt(); pointerToSymbolTable = readInt(); numberOfSymbols = readInt(); + // String Table can be accessed at this point because + // pointerToSymbolTable and numberOfSymbols fields are set. sizeOfOptionalHeader = readShort(); characteristics = readShort(); @@ -222,6 +228,8 @@ public class COFFFileParser { private MemoizedObject windowsSpecificFields; private MemoizedObject dataDirectories; + // We use an offset of 2 because OptionalHeaderStandardFieldsImpl doesn't + // include the 'magic' field. private static final int STANDARD_FIELDS_OFFSET = 2; private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28; private static final int PE32_DATA_DIRECTORIES_OFFSET = 96; @@ -288,7 +296,7 @@ public class COFFFileParser { private int sizeOfUninitializedData; private int addressOfEntryPoint; private int baseOfCode; - private int baseOfData; + private int baseOfData; // only set in PE32 OptionalHeaderStandardFieldsImpl(int offset, boolean isPE32Plus) { @@ -301,7 +309,8 @@ public class COFFFileParser { sizeOfUninitializedData = readInt(); addressOfEntryPoint = readInt(); baseOfCode = readInt(); - if (isPE32Plus) { + if (!isPE32Plus) { + // only available in PE32 baseOfData = readInt(); } } @@ -433,7 +442,10 @@ public class COFFFileParser { if (dir.getRVA() == 0 || dir.getSize() == 0) { return null; } - return new ExportDirectoryTableImpl(rvaToFileOffset(dir.getRVA()), dir.getSize()); + // ExportDirectoryTableImpl needs both the RVA and the + // RVA converted to a file offset. + return new + ExportDirectoryTableImpl(dir.getRVA(), dir.getSize()); } }; @@ -526,6 +538,7 @@ public class COFFFileParser { } class ExportDirectoryTableImpl implements ExportDirectoryTable { + private int exportDataDirRVA; private int offset; private int size; @@ -548,8 +561,9 @@ public class COFFFileParser { private MemoizedObject exportOrdinalTable; private MemoizedObject exportAddressTable; - ExportDirectoryTableImpl(int offset, int size) { - this.offset = offset; + ExportDirectoryTableImpl(int exportDataDirRVA, int size) { + this.exportDataDirRVA = exportDataDirRVA; + offset = rvaToFileOffset(exportDataDirRVA); this.size = size; seek(offset); exportFlags = readInt(); @@ -595,6 +609,7 @@ public class COFFFileParser { exportOrdinalTable = new MemoizedObject() { public Object computeValue() { + // number of ordinals is same as the number of name pointers short[] ordinals = new short[getNumberOfNamePointers()]; seek(rvaToFileOffset(getOrdinalTableRVA())); for (int i = 0; i < ordinals.length; i++) { @@ -608,14 +623,18 @@ public class COFFFileParser { public Object computeValue() { int[] addresses = new int[getNumberOfAddressTableEntries()]; seek(rvaToFileOffset(getExportAddressTableRVA())); - // Must make two passes to avoid rvaToFileOffset - // destroying seek() position + // The Export Address Table values are a union of two + // possible values: + // Export RVA - The address of the exported symbol when + // loaded into memory, relative to the image base. + // This value doesn't get converted into a file offset. + // Forwarder RVA - The pointer to a null-terminated ASCII + // string in the export section. This value gets + // converted into a file offset because we have to + // fetch the string. for (int i = 0; i < addresses.length; i++) { addresses[i] = readInt(); } - for (int i = 0; i < addresses.length; i++) { - addresses[i] = rvaToFileOffset(addresses[i]); - } return addresses; } }; @@ -648,11 +667,12 @@ public class COFFFileParser { public boolean isExportAddressForwarder(short ordinal) { int addr = getExportAddress(ordinal); - return ((offset <= addr) && (addr < (offset + size))); + return ((exportDataDirRVA <= addr) && + (addr < (exportDataDirRVA + size))); } public String getExportAddressForwarder(short ordinal) { - seek(getExportAddress(ordinal)); + seek(rvaToFileOffset(getExportAddress(ordinal))); return readCString(); } @@ -3371,10 +3391,17 @@ public class COFFFileParser { throw new COFFException(e); } // Look up in string table + // FIXME: this index value is assumed to be in the valid range name = getStringTable().get(index); } else { try { - name = new String(tmpName, US_ASCII); + int length = 0; + // find last non-NULL + for (; length < tmpName.length && tmpName[length] != '\0';) { + length++; + } + // don't include NULL chars in returned name String + name = new String(tmpName, 0, length, US_ASCII); } catch (UnsupportedEncodingException e) { throw new COFFException(e); } @@ -3487,6 +3514,7 @@ public class COFFFileParser { tmpName[5] << 16 | tmpName[6] << 8 | tmpName[7]); + // FIXME: stringOffset is assumed to be in the valid range name = getStringTable().getAtOffset(stringOffset); } @@ -3698,12 +3726,13 @@ public class COFFFileParser { StringTable(int offset) { if (offset == 0) { + // no String Table strings = new COFFString[0]; return; } seek(offset); - int length = readInt(); + int length = readInt(); // length includes itself byte[] data = new byte[length - 4]; int numBytesRead = readBytes(data); if (numBytesRead != data.length) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java index ec563f1d626..fd9d39aa5c5 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,35 +37,48 @@ public class DumpExports { String filename = args[0]; COFFFile file = COFFFileParser.getParser().parse(filename); - ExportDirectoryTable exports = - file.getHeader(). - getOptionalHeader(). - getDataDirectories(). - getExportDirectoryTable(); + + // get common point for both things we want to dump + OptionalHeaderDataDirectories dataDirs = file.getHeader().getOptionalHeader(). + getDataDirectories(); + + // dump the header data directory for the Export Table: + DataDirectory dir = dataDirs.getExportTable(); + System.out.println("Export table: RVA = " + dir.getRVA() + "/0x" + + Integer.toHexString(dir.getRVA()) + ", size = " + dir.getSize() + "/0x" + + Integer.toHexString(dir.getSize())); + + System.out.println(file.getHeader().getNumberOfSections() + " sections in file"); + for (int i = 1; i <= file.getHeader().getNumberOfSections(); i++) { + SectionHeader sec = file.getHeader().getSectionHeader(i); + System.out.println(" Section " + i + ":"); + System.out.println(" Name = '" + sec.getName() + "'"); + System.out.println(" VirtualSize = " + sec.getSize() + "/0x" + + Integer.toHexString(sec.getSize())); + System.out.println(" VirtualAddress = " + sec.getVirtualAddress() + "/0x" + + Integer.toHexString(sec.getVirtualAddress())); + System.out.println(" SizeOfRawData = " + sec.getSizeOfRawData() + "/0x" + + Integer.toHexString(sec.getSizeOfRawData())); + System.out.println(" PointerToRawData = " + sec.getPointerToRawData() + "/0x" + + Integer.toHexString(sec.getPointerToRawData())); + } + + ExportDirectoryTable exports = dataDirs.getExportDirectoryTable(); if (exports == null) { System.out.println("No exports found."); } else { - System.out.println(file.getHeader().getNumberOfSections() + " sections in file"); - for (int i = 0; i < file.getHeader().getNumberOfSections(); i++) { - System.out.println(" Section " + i + ": " + file.getHeader().getSectionHeader(1 + i).getName()); - } - - DataDirectory dir = file.getHeader().getOptionalHeader().getDataDirectories().getExportTable(); - System.out.println("Export table: RVA = 0x" + Integer.toHexString(dir.getRVA()) + - ", size = 0x" + Integer.toHexString(dir.getSize())); - System.out.println("DLL name: " + exports.getDLLName()); System.out.println("Time/date stamp 0x" + Integer.toHexString(exports.getTimeDateStamp())); System.out.println("Major version 0x" + Integer.toHexString(exports.getMajorVersion() & 0xFFFF)); System.out.println("Minor version 0x" + Integer.toHexString(exports.getMinorVersion() & 0xFFFF)); - System.out.println(exports.getNumberOfNamePointers() + " functions found"); + System.out.println(exports.getNumberOfNamePointers() + " exports found"); for (int i = 0; i < exports.getNumberOfNamePointers(); i++) { - System.out.println(" 0x" + - Integer.toHexString(exports.getExportAddress(exports.getExportOrdinal(i))) + - " " + - (exports.isExportAddressForwarder(exports.getExportOrdinal(i)) ? - ("Forwarded to " + exports.getExportAddressForwarder(exports.getExportOrdinal(i))) : - exports.getExportName(i))); + short ordinal = exports.getExportOrdinal(i); + System.out.print("[" + i + "] '" + exports.getExportName(i) + "': [" + + ordinal + "] = 0x" + Integer.toHexString(exports.getExportAddress(ordinal))); + System.out.println(exports.isExportAddressForwarder(ordinal) + ? " Forwarded to '" + exports.getExportAddressForwarder(ordinal) + "'" + : ""); } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java index 6f026838d58..e6f42df3ac9 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,8 +42,8 @@ public class TestParser { COFFHeader header = file.getHeader(); int numSections = header.getNumberOfSections(); System.out.println(numSections + " sections detected."); - for (int i = 0; i < numSections; i++) { - SectionHeader secHeader = header.getSectionHeader(1 + i); + for (int i = 1; i <= numSections; i++) { + SectionHeader secHeader = header.getSectionHeader(i); System.out.println(secHeader.getName()); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java index 53141a6d2d1..3e5a6aa96b6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -506,7 +506,6 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger throw new DebuggerException("Unimplemented"); } - private static String DTFWHome; private static String imagePath; private static String symbolPath; private static boolean useNativeLookup; @@ -514,81 +513,143 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger static { /* - * sawindbg.dll depends on dbgeng.dll which - * itself depends on dbghelp.dll. dbgeng.dll and dbghelp.dll. - * On systems newer than Windows 2000, these two .dlls are - * in the standard system directory so we will find them there. - * On Windows 2000 and earlier, these files do not exist. - * The user must download Debugging Tools For Windows (DTFW) - * and install it in order to use SA. + * sawindbg.dll depends on dbgeng.dll which itself depends on + * dbghelp.dll. We have to make sure that the dbgeng.dll and + * dbghelp.dll that we load are compatible with each other. We + * load both of those libraries from the same directory based + * on the theory that co-located libraries are compatible. * - * We have to make sure we use the two files from the same directory - * in case there are more than one copy on the system because - * one version of dbgeng.dll might not be compatible with a - * different version of dbghelp.dll. - * We first look for them in the directory pointed at by - * env. var. DEBUGGINGTOOLSFORWINDOWS, next in the default - * installation dir for DTFW, and lastly in the standard - * system directory. We expect that that we will find - * them in the standard system directory on all systems - * newer than Windows 2000. + * On Windows 2000 and earlier, dbgeng.dll and dbghelp.dll were + * not included as part of the standard system directory. On + * systems newer than Windows 2000, dbgeng.dll and dbghelp.dll + * are included in the standard system directory. However, the + * versions included in the standard system directory may not + * be able to handle symbol information for the newer compilers. + * + * We search for and explicitly load the libraries using the + * following directory search order: + * + * - java.home/bin (same as $JAVA_HOME/jre/bin) + * - dir named by DEBUGGINGTOOLSFORWINDOWS environment variable + * - various "Debugging Tools For Windows" program directories + * - the system directory ($SYSROOT/system32) + * + * If SA is invoked with -Dsun.jvm.hotspot.loadLibrary.DEBUG=1, + * then debug messages about library loading are printed to + * System.err. */ - String dirName = null; - DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS"); - if (DTFWHome == null) { - // See if we have the files in the default location. - String sysRoot = System.getenv("SYSTEMROOT"); - DTFWHome = sysRoot + File.separator + - ".." + File.separator + "Program Files" + - File.separator + "Debugging Tools For Windows"; - } + String dbgengPath = null; + String dbghelpPath = null; + String sawindbgPath = null; + List searchList = new ArrayList(); + + boolean loadLibraryDEBUG = + System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null; { - String dbghelp = DTFWHome + File.separator + "dbghelp.dll"; - String dbgeng = DTFWHome + File.separator + "dbgeng.dll"; - File fhelp = new File(dbghelp); - File feng = new File(dbgeng); - if (fhelp.exists() && feng.exists()) { - // found both, we are happy. - // NOTE: The order of loads is important! If we load dbgeng.dll - // first, then the dependency - dbghelp.dll - will be loaded - // from usual DLL search thereby defeating the purpose! - System.load(dbghelp); - System.load(dbgeng); - } else if (! fhelp.exists() && ! feng.exists()) { - // neither exist. We will ignore this dir and assume - // they are in the system dir. - DTFWHome = null; - } else { - // one exists but not the other - //System.err.println("Error: Both files dbghelp.dll and dbgeng.dll " - // "must exist in directory " + DTFWHome); - throw new UnsatisfiedLinkError("Both files dbghelp.dll and " + - "dbgeng.dll must exist in " + - "directory " + DTFWHome); - } - } - if (DTFWHome == null) { - // The files better be in the system dir. - String sysDir = System.getenv("SYSTEMROOT") + - File.separator + "system32"; + // First place to search is co-located with sawindbg.dll in + // $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre): + searchList.add(System.getProperty("java.home") + File.separator + "bin"); + sawindbgPath = (String) searchList.get(0) + File.separator + + "sawindbg.dll"; - File feng = new File(sysDir + File.separator + "dbgeng.dll"); - if (!feng.exists()) { - throw new UnsatisfiedLinkError("File dbgeng.dll does not exist in " + - sysDir + ". Please search microsoft.com " + - "for Debugging Tools For Windows, and " + - "either download it to the default " + - "location, or download it to a custom " + - "location and set environment variable " + - " DEBUGGINGTOOLSFORWINDOWS " + - "to the pathname of that location."); + // second place to search is specified by an environment variable: + String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS"); + if (DTFWHome != null) { + searchList.add(DTFWHome); } + + // The third place to search is the install directory for the + // "Debugging Tools For Windows" package; so far there are three + // name variations that we know of: + String sysRoot = System.getenv("SYSTEMROOT"); + DTFWHome = sysRoot + File.separator + ".." + File.separator + + "Program Files" + File.separator + "Debugging Tools For Windows"; + searchList.add(DTFWHome); + searchList.add(DTFWHome + " (x86)"); + searchList.add(DTFWHome + " (x64)"); + + // The last place to search is the system directory: + searchList.add(sysRoot + File.separator + "system32"); } + for (int i = 0; i < searchList.size(); i++) { + File dir = new File((String) searchList.get(i)); + if (!dir.exists()) { + if (loadLibraryDEBUG) { + System.err.println("DEBUG: '" + searchList.get(i) + + "': directory does not exist."); + } + // this search directory doesn't exist so skip it + continue; + } + + dbgengPath = (String) searchList.get(i) + File.separator + "dbgeng.dll"; + dbghelpPath = (String) searchList.get(i) + File.separator + "dbghelp.dll"; + + File feng = new File(dbgengPath); + File fhelp = new File(dbghelpPath); + if (feng.exists() && fhelp.exists()) { + // both files exist so we have a match + break; + } + + // At least one of the files does not exist; no warning if both + // don't exist. If just one doesn't exist then we don't check + // loadLibraryDEBUG because we have a mis-configured system. + if (feng.exists()) { + System.err.println("WARNING: found '" + dbgengPath + + "' but did not find '" + dbghelpPath + "'; ignoring '" + + dbgengPath + "'."); + } else if (fhelp.exists()) { + System.err.println("WARNING: found '" + dbghelpPath + + "' but did not find '" + dbgengPath + "'; ignoring '" + + dbghelpPath + "'."); + } else if (loadLibraryDEBUG) { + System.err.println("DEBUG: searched '" + searchList.get(i) + + "': dbgeng.dll and dbghelp.dll were not found."); + } + dbgengPath = null; + dbghelpPath = null; + } + + if (dbgengPath == null || dbghelpPath == null) { + // at least one of the files wasn't found anywhere we searched + String mesg = null; + + if (dbgengPath == null && dbghelpPath == null) { + mesg = "dbgeng.dll and dbghelp.dll cannot be found. "; + } else if (dbgengPath == null) { + mesg = "dbgeng.dll cannot be found (dbghelp.dll was found). "; + } else { + mesg = "dbghelp.dll cannot be found (dbgeng.dll was found). "; + } + throw new UnsatisfiedLinkError(mesg + + "Please search microsoft.com for 'Debugging Tools For Windows', " + + "and either download it to the default location, or download it " + + "to a custom location and set environment variable " + + "'DEBUGGINGTOOLSFORWINDOWS' to the pathname of that location."); + } + + // NOTE: The order of loads is important! If we load dbgeng.dll + // first, then the dependency - dbghelp.dll - will be loaded + // from usual DLL search thereby defeating the purpose! + if (loadLibraryDEBUG) { + System.err.println("DEBUG: loading '" + dbghelpPath + "'."); + } + System.load(dbghelpPath); + if (loadLibraryDEBUG) { + System.err.println("DEBUG: loading '" + dbgengPath + "'."); + } + System.load(dbgengPath); + // Now, load sawindbg.dll - System.loadLibrary("sawindbg"); + if (loadLibraryDEBUG) { + System.err.println("DEBUG: loading '" + sawindbgPath + "'."); + } + System.load(sawindbgPath); + // where do I find '.exe', '.dll' files? imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath"); if (imagePath == null) { From 089d7481924207231299a480aee1ff845e44de2a Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Thu, 23 Dec 2010 10:08:53 -0800 Subject: [PATCH 43/94] 7008869: Debug printlns accidentally added to make/build.xml Delete bogus echo statements Reviewed-by: ksrini --- langtools/make/build.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/langtools/make/build.xml b/langtools/make/build.xml index 0ab91613c65..ec3aaf8763e 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -327,7 +327,6 @@ - - - - - - Date: Thu, 23 Dec 2010 10:38:26 -0800 Subject: [PATCH 44/94] 6913300: Missing serialVersionUID in javax.print.attribute.standard.DialogTypeSelection Reviewed-by: igor, prr --- .../javax/print/attribute/standard/DialogTypeSelection.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/src/share/classes/javax/print/attribute/standard/DialogTypeSelection.java b/jdk/src/share/classes/javax/print/attribute/standard/DialogTypeSelection.java index 1dae59a1525..4cd68bb59af 100644 --- a/jdk/src/share/classes/javax/print/attribute/standard/DialogTypeSelection.java +++ b/jdk/src/share/classes/javax/print/attribute/standard/DialogTypeSelection.java @@ -52,6 +52,8 @@ import javax.print.attribute.PrintRequestAttribute; public final class DialogTypeSelection extends EnumSyntax implements PrintRequestAttribute { + private static final long serialVersionUID = 7518682952133256029L; + /** * */ From a5689daad8ef0dfcb030e007e6e7167e163a81da Mon Sep 17 00:00:00 2001 From: Jennifer Godinez Date: Thu, 23 Dec 2010 11:01:37 -0800 Subject: [PATCH 45/94] 6949749: regression cases need to be updated by removing "System.exit(0)" Reviewed-by: igor, prr --- jdk/test/java/awt/PrintJob/Text/StringWidth.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/test/java/awt/PrintJob/Text/StringWidth.java b/jdk/test/java/awt/PrintJob/Text/StringWidth.java index b8760aa942c..4c2250a21dd 100644 --- a/jdk/test/java/awt/PrintJob/Text/StringWidth.java +++ b/jdk/test/java/awt/PrintJob/Text/StringWidth.java @@ -60,7 +60,6 @@ public class StringWidth extends Frame { pg.dispose(); pj.end(); setVisible(false); - System.exit(0); } public static void main(String[] args) { From 4157467833ad59ce5bed7a83649e8fded84e0a2f Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Thu, 23 Dec 2010 12:29:21 -0800 Subject: [PATCH 46/94] 6982992: Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout Hoist some invariant code out of a loop Reviewed-by: ksrini --- .../tools/javac/failover/CheckAttributedTree.java | 13 ++++++++----- .../tools/javac/tree/AbstractTreeScannerTest.java | 12 ++++++++---- langtools/test/tools/javac/tree/TreePosTest.java | 13 ++++++++----- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/langtools/test/tools/javac/failover/CheckAttributedTree.java b/langtools/test/tools/javac/failover/CheckAttributedTree.java index 208cbe5cb74..e249689a41a 100644 --- a/langtools/test/tools/javac/failover/CheckAttributedTree.java +++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java @@ -252,6 +252,13 @@ public class CheckAttributedTree { error("File " + file + " ignored"); } + // See CR: 6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + /** * Read a file. * @param file the file to be read @@ -260,12 +267,8 @@ public class CheckAttributedTree { * @throws TreePosTest.ParseException if any errors occur while parsing the file */ List> read(File file) throws IOException, AttributionException { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - Reporter r = new Reporter(pw); JavacTool tool = JavacTool.create(); - Charset cs = (encoding == null ? null : Charset.forName(encoding)); - StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + r.errors = 0; Iterable files = fm.getJavaFileObjects(file); String[] opts = { "-XDshouldStopPolicy=ATTR", "-XDverboseCompilePolicy" }; JavacTask task = tool.getTask(pw, fm, r, Arrays.asList(opts), null, files); diff --git a/langtools/test/tools/javac/tree/AbstractTreeScannerTest.java b/langtools/test/tools/javac/tree/AbstractTreeScannerTest.java index 359690b9f5e..b0fe687fdff 100644 --- a/langtools/test/tools/javac/tree/AbstractTreeScannerTest.java +++ b/langtools/test/tools/javac/tree/AbstractTreeScannerTest.java @@ -143,6 +143,13 @@ public abstract class AbstractTreeScannerTest { abstract int test(JCCompilationUnit t); + // See CR: 6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + /** * Read a file. * @param file the file to be read @@ -151,11 +158,8 @@ public abstract class AbstractTreeScannerTest { * @throws TreePosTest.ParseException if any errors occur while parsing the file */ JCCompilationUnit read(File file) throws IOException, ParseException { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - Reporter r = new Reporter(pw); JavacTool tool = JavacTool.create(); - StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + r.errors = 0; Iterable files = fm.getJavaFileObjects(file); JavacTask task = tool.getTask(pw, fm, r, Collections.emptyList(), null, files); Iterable trees = task.parse(); diff --git a/langtools/test/tools/javac/tree/TreePosTest.java b/langtools/test/tools/javac/tree/TreePosTest.java index 9f586185334..bb6e466b557 100644 --- a/langtools/test/tools/javac/tree/TreePosTest.java +++ b/langtools/test/tools/javac/tree/TreePosTest.java @@ -249,6 +249,13 @@ public class TreePosTest { error("File " + file + " ignored"); } + // See CR: 6982992 Tests CheckAttributedTree.java, JavacTreeScannerTest.java, and SourceTreeeScannerTest.java timeout + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + /** * Read a file. * @param file the file to be read @@ -257,12 +264,8 @@ public class TreePosTest { * @throws TreePosTest.ParseException if any errors occur while parsing the file */ JCCompilationUnit read(File file) throws IOException, ParseException { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - Reporter r = new Reporter(pw); JavacTool tool = JavacTool.create(); - Charset cs = (encoding == null ? null : Charset.forName(encoding)); - StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + r.errors = 0; Iterable files = fm.getJavaFileObjects(file); JavacTask task = tool.getTask(pw, fm, r, Collections.emptyList(), null, files); Iterable trees = task.parse(); From 45f02b1cb5ccbc4d26b35071d677cc5b53e690e5 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 23 Dec 2010 15:28:59 -0800 Subject: [PATCH 47/94] 6891551: Font rasterisation uses more heap than needed for some strikes Reviewed-by: jgodinez --- jdk/src/share/classes/sun/font/FileFontStrike.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/font/FileFontStrike.java b/jdk/src/share/classes/sun/font/FileFontStrike.java index ca72867f8cc..ae6045f696c 100644 --- a/jdk/src/share/classes/sun/font/FileFontStrike.java +++ b/jdk/src/share/classes/sun/font/FileFontStrike.java @@ -60,8 +60,8 @@ public class FileFontStrike extends PhysicalStrike { private volatile int glyphCacheFormat = UNINITIALISED; - /* segmented arrays are blocks of 256 */ - private static final int SEGSHIFT = 8; + /* segmented arrays are blocks of 32 */ + private static final int SEGSHIFT = 5; private static final int SEGSIZE = 1 << SEGSHIFT; private boolean segmentedCache; @@ -171,7 +171,7 @@ public class FileFontStrike extends PhysicalStrike { mapper = fileFont.getMapper(); int numGlyphs = mapper.getNumGlyphs(); - /* Always segment for fonts with > 2K glyphs, but also for smaller + /* Always segment for fonts with > 256 glyphs, but also for smaller * fonts with non-typical sizes and transforms. * Segmenting for all non-typical pt sizes helps to minimise memory * usage when very many distinct strikes are created. From 5119e6d87a022547362afa52d8dd3093d6d47b80 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 23 Dec 2010 21:58:12 -0800 Subject: [PATCH 48/94] 6927458: font system should cache transient strikes with weak references Reviewed-by: igor, jgodinez --- jdk/src/share/classes/sun/font/Font2D.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/font/Font2D.java b/jdk/src/share/classes/sun/font/Font2D.java index 3fab32c8434..b78292722b5 100644 --- a/jdk/src/share/classes/sun/font/Font2D.java +++ b/jdk/src/share/classes/sun/font/Font2D.java @@ -343,7 +343,21 @@ public abstract class Font2D { } strike = createStrike(desc); //StrikeCache.addStrike(); - strikeRef = StrikeCache.getStrikeRef(strike); + /* If we are creating many strikes on this font which + * involve non-quadrant rotations, or more general + * transforms which include shears, then force the use + * of weak references rather than soft references. + * This means that it won't live much beyond the next GC, + * which is what we want for what is likely a transient strike. + */ + int txType = desc.glyphTx.getType(); + if (txType == AffineTransform.TYPE_GENERAL_TRANSFORM || + (txType & AffineTransform.TYPE_GENERAL_ROTATION) != 0 && + strikeCache.size() > 10) { + strikeRef = StrikeCache.getStrikeRef(strike, true); + } else { + strikeRef = StrikeCache.getStrikeRef(strike); + } strikeCache.put(desc, strikeRef); //strike.lastlookupTime = System.currentTimeMillis(); lastFontStrike = new SoftReference(strike); From 8769a48a69a4783a431c671906875c07f16983aa Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Fri, 24 Dec 2010 14:05:42 +0300 Subject: [PATCH 49/94] 6983028: java/awt/FontClass/FontPrivilege.java Reviewed-by: prr --- jdk/test/java/awt/FontClass/FontPrivilege.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/awt/FontClass/FontPrivilege.java b/jdk/test/java/awt/FontClass/FontPrivilege.java index d633f4d3fec..24fd5116c8c 100644 --- a/jdk/test/java/awt/FontClass/FontPrivilege.java +++ b/jdk/test/java/awt/FontClass/FontPrivilege.java @@ -25,7 +25,7 @@ * @test * @bug 5010310 6319835 6904882 6968373 * @summary test fonts can be created in the presence of a security manager - * @run main/othervm/secure=java.lang.SecurityManager FontPrivilege + * @run main FontPrivilege */ import java.awt.Font; @@ -33,6 +33,8 @@ import java.awt.Font; public class FontPrivilege { public static void main(String[] args) throws Exception { + System.setSecurityManager(new SecurityManager()); + new Font("Helvetica", Font.PLAIN, 12).getFamily(); new Font("foo bar", Font.PLAIN, 12).getFamily(); } From 0370a1df6b4a7d6be98decb450e0f7d1207a702f Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 24 Dec 2010 09:31:32 -0800 Subject: [PATCH 50/94] 6997210: Solaris 11 has no development support for DGA: Cannot build JDK Reviewed-by: bae, ohair --- jdk/make/sun/Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/jdk/make/sun/Makefile b/jdk/make/sun/Makefile index 31e1bdd866e..ba7b10e7237 100644 --- a/jdk/make/sun/Makefile +++ b/jdk/make/sun/Makefile @@ -42,7 +42,15 @@ ifneq ($(PLATFORM), windows) ifndef OPENJDK ifeq ($(PLATFORM), solaris) ifneq ($(ARCH), amd64) - DGA_SUBDIR = jdga + # Solaris 11 does not have support for new compilation of DGA code. + OS_VERSION = $(shell uname -r) + OS_MAJOR_VERSION := $(call MajorVersion,$(OS_VERSION)) + OS_MINOR_VERSION := $(call MinorVersion,$(OS_VERSION)) + ifeq ($(shell $(EXPR) $(OS_MAJOR_VERSION) == 5), 1) + ifeq ($(shell $(EXPR) $(OS_MINOR_VERSION) \<= 10), 1) + DGA_SUBDIR = jdga + endif + endif endif endif endif From f2bb972af477629013f279a355c1ef33923b8df0 Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Mon, 27 Dec 2010 14:13:52 +0900 Subject: [PATCH 51/94] 7003643: [Fmt-Me] MessageFormat.toPattern produces wrong quoted string and subformat modifiers 7008195: [Fmt-Me] Improve MessageFormat.applyPattern performance Reviewed-by: naoto, peytoia --- .../classes/java/text/MessageFormat.java | 443 +++++++++++------- .../text/Format/MessageFormat/Bug7003643.java | 73 +++ .../DateFormatProviderTest.java | 47 +- .../PluggableLocale/DateFormatProviderTest.sh | 4 +- .../NumberFormatProviderTest.java | 64 ++- .../NumberFormatProviderTest.sh | 4 +- .../java/util/PluggableLocale/fooprovider.jar | Bin 15434 -> 16789 bytes .../providersrc/DateFormatProviderImpl.java | 10 +- .../providersrc/FooDateFormat.java | 61 +++ .../providersrc/FooNumberFormat.java | 81 ++++ .../util/PluggableLocale/providersrc/Makefile | 2 + .../providersrc/NumberFormatProviderImpl.java | 46 +- 12 files changed, 604 insertions(+), 231 deletions(-) create mode 100644 jdk/test/java/text/Format/MessageFormat/Bug7003643.java create mode 100644 jdk/test/java/util/PluggableLocale/providersrc/FooDateFormat.java create mode 100644 jdk/test/java/util/PluggableLocale/providersrc/FooNumberFormat.java diff --git a/jdk/src/share/classes/java/text/MessageFormat.java b/jdk/src/share/classes/java/text/MessageFormat.java index 41623c48ed0..6590e767795 100644 --- a/jdk/src/share/classes/java/text/MessageFormat.java +++ b/jdk/src/share/classes/java/text/MessageFormat.java @@ -423,18 +423,19 @@ public class MessageFormat extends Format { * @exception IllegalArgumentException if the pattern is invalid */ public void applyPattern(String pattern) { - StringBuffer[] segments = new StringBuffer[4]; - for (int i = 0; i < segments.length; ++i) { - segments[i] = new StringBuffer(); - } - int part = 0; + StringBuilder[] segments = new StringBuilder[4]; + // Allocate only segments[SEG_RAW] here. The rest are + // allocated on demand. + segments[SEG_RAW] = new StringBuilder(); + + int part = SEG_RAW; int formatNumber = 0; boolean inQuote = false; int braceStack = 0; maxOffset = -1; for (int i = 0; i < pattern.length(); ++i) { char ch = pattern.charAt(i); - if (part == 0) { + if (part == SEG_RAW) { if (ch == '\'') { if (i + 1 < pattern.length() && pattern.charAt(i+1) == '\'') { @@ -444,43 +445,61 @@ public class MessageFormat extends Format { inQuote = !inQuote; } } else if (ch == '{' && !inQuote) { - part = 1; + part = SEG_INDEX; + if (segments[SEG_INDEX] == null) { + segments[SEG_INDEX] = new StringBuilder(); + } } else { segments[part].append(ch); } - } else if (inQuote) { // just copy quotes in parts - segments[part].append(ch); - if (ch == '\'') { - inQuote = false; - } - } else { - switch (ch) { - case ',': - if (part < 3) - part += 1; - else - segments[part].append(ch); - break; - case '{': - ++braceStack; + } else { + if (inQuote) { // just copy quotes in parts segments[part].append(ch); - break; - case '}': - if (braceStack == 0) { - part = 0; - makeFormat(i, formatNumber, segments); - formatNumber++; - } else { - --braceStack; - segments[part].append(ch); + if (ch == '\'') { + inQuote = false; + } + } else { + switch (ch) { + case ',': + if (part < SEG_MODIFIER) { + if (segments[++part] == null) { + segments[part] = new StringBuilder(); + } + } else { + segments[part].append(ch); + } + break; + case '{': + ++braceStack; + segments[part].append(ch); + break; + case '}': + if (braceStack == 0) { + part = SEG_RAW; + makeFormat(i, formatNumber, segments); + formatNumber++; + // throw away other segments + segments[SEG_INDEX] = null; + segments[SEG_TYPE] = null; + segments[SEG_MODIFIER] = null; + } else { + --braceStack; + segments[part].append(ch); + } + break; + case ' ': + // Skip any leading space chars for SEG_TYPE. + if (part != SEG_TYPE || segments[SEG_TYPE].length() > 0) { + segments[part].append(ch); + } + break; + case '\'': + inQuote = true; + // fall through, so we keep quotes in other parts + default: + segments[part].append(ch); + break; } - break; - case '\'': - inQuote = true; - // fall through, so we keep quotes in other parts - default: - segments[part].append(ch); - break; } } } @@ -502,65 +521,57 @@ public class MessageFormat extends Format { public String toPattern() { // later, make this more extensible int lastOffset = 0; - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); for (int i = 0; i <= maxOffset; ++i) { - copyAndFixQuotes(pattern, lastOffset, offsets[i],result); + copyAndFixQuotes(pattern, lastOffset, offsets[i], result); lastOffset = offsets[i]; - result.append('{'); - result.append(argumentNumbers[i]); - if (formats[i] == null) { + result.append('{').append(argumentNumbers[i]); + Format fmt = formats[i]; + if (fmt == null) { // do nothing, string format - } else if (formats[i] instanceof DecimalFormat) { - if (formats[i].equals(NumberFormat.getInstance(locale))) { + } else if (fmt instanceof NumberFormat) { + if (fmt.equals(NumberFormat.getInstance(locale))) { result.append(",number"); - } else if (formats[i].equals(NumberFormat.getCurrencyInstance(locale))) { + } else if (fmt.equals(NumberFormat.getCurrencyInstance(locale))) { result.append(",number,currency"); - } else if (formats[i].equals(NumberFormat.getPercentInstance(locale))) { + } else if (fmt.equals(NumberFormat.getPercentInstance(locale))) { result.append(",number,percent"); - } else if (formats[i].equals(NumberFormat.getIntegerInstance(locale))) { + } else if (fmt.equals(NumberFormat.getIntegerInstance(locale))) { result.append(",number,integer"); } else { - result.append(",number," + - ((DecimalFormat)formats[i]).toPattern()); + if (fmt instanceof DecimalFormat) { + result.append(",number,").append(((DecimalFormat)fmt).toPattern()); + } else if (fmt instanceof ChoiceFormat) { + result.append(",choice,").append(((ChoiceFormat)fmt).toPattern()); + } else { + // UNKNOWN + } } - } else if (formats[i] instanceof SimpleDateFormat) { - if (formats[i].equals(DateFormat.getDateInstance( - DateFormat.DEFAULT,locale))) { - result.append(",date"); - } else if (formats[i].equals(DateFormat.getDateInstance( - DateFormat.SHORT,locale))) { - result.append(",date,short"); - } else if (formats[i].equals(DateFormat.getDateInstance( - DateFormat.DEFAULT,locale))) { - result.append(",date,medium"); - } else if (formats[i].equals(DateFormat.getDateInstance( - DateFormat.LONG,locale))) { - result.append(",date,long"); - } else if (formats[i].equals(DateFormat.getDateInstance( - DateFormat.FULL,locale))) { - result.append(",date,full"); - } else if (formats[i].equals(DateFormat.getTimeInstance( - DateFormat.DEFAULT,locale))) { - result.append(",time"); - } else if (formats[i].equals(DateFormat.getTimeInstance( - DateFormat.SHORT,locale))) { - result.append(",time,short"); - } else if (formats[i].equals(DateFormat.getTimeInstance( - DateFormat.DEFAULT,locale))) { - result.append(",time,medium"); - } else if (formats[i].equals(DateFormat.getTimeInstance( - DateFormat.LONG,locale))) { - result.append(",time,long"); - } else if (formats[i].equals(DateFormat.getTimeInstance( - DateFormat.FULL,locale))) { - result.append(",time,full"); - } else { - result.append(",date," - + ((SimpleDateFormat)formats[i]).toPattern()); + } else if (fmt instanceof DateFormat) { + int index; + for (index = MODIFIER_DEFAULT; index < DATE_TIME_MODIFIERS.length; index++) { + DateFormat df = DateFormat.getDateInstance(DATE_TIME_MODIFIERS[index], + locale); + if (fmt.equals(df)) { + result.append(",date"); + break; + } + df = DateFormat.getTimeInstance(DATE_TIME_MODIFIERS[index], + locale); + if (fmt.equals(df)) { + result.append(",time"); + break; + } + } + if (index >= DATE_TIME_MODIFIERS.length) { + if (fmt instanceof SimpleDateFormat) { + result.append(",date,").append(((SimpleDateFormat)fmt).toPattern()); + } else { + // UNKNOWN + } + } else if (index != MODIFIER_DEFAULT) { + result.append(',').append(DATE_TIME_MODIFIER_KEYWORDS[index]); } - } else if (formats[i] instanceof ChoiceFormat) { - result.append(",choice," - + ((ChoiceFormat)formats[i]).toPattern()); } else { //result.append(", unknown"); } @@ -674,7 +685,7 @@ public class MessageFormat extends Format { * * @param formatElementIndex the index of a format element within the pattern * @param newFormat the format to use for the specified format element - * @exception ArrayIndexOutOfBoundsException if formatElementIndex is equal to or + * @exception ArrayIndexOutOfBoundsException if {@code formatElementIndex} is equal to or * larger than the number of format elements in the pattern string */ public void setFormat(int formatElementIndex, Format newFormat) { @@ -968,7 +979,8 @@ public class MessageFormat extends Format { if (patternOffset >= tempLength) { next = source.length(); }else{ - next = source.indexOf( pattern.substring(patternOffset,tempLength), sourceOffset); + next = source.indexOf(pattern.substring(patternOffset, tempLength), + sourceOffset); } if (next < 0) { @@ -1222,7 +1234,7 @@ public class MessageFormat extends Format { lastOffset = offsets[i]; int argumentNumber = argumentNumbers[i]; if (arguments == null || argumentNumber >= arguments.length) { - result.append("{" + argumentNumber + "}"); + result.append('{').append(argumentNumber).append('}'); continue; } // int argRecursion = ((recursionProtection >> (argumentNumber*2)) & 0x3); @@ -1334,25 +1346,83 @@ public class MessageFormat extends Format { } } - private static final String[] typeList = - {"", "", "number", "", "date", "", "time", "", "choice"}; - private static final String[] modifierList = - {"", "", "currency", "", "percent", "", "integer"}; - private static final String[] dateModifierList = - {"", "", "short", "", "medium", "", "long", "", "full"}; + // Indices for segments + private static final int SEG_RAW = 0; + private static final int SEG_INDEX = 1; + private static final int SEG_TYPE = 2; + private static final int SEG_MODIFIER = 3; // modifier or subformat + + // Indices for type keywords + private static final int TYPE_NULL = 0; + private static final int TYPE_NUMBER = 1; + private static final int TYPE_DATE = 2; + private static final int TYPE_TIME = 3; + private static final int TYPE_CHOICE = 4; + + private static final String[] TYPE_KEYWORDS = { + "", + "number", + "date", + "time", + "choice" + }; + + // Indices for number modifiers + private static final int MODIFIER_DEFAULT = 0; // common in number and date-time + private static final int MODIFIER_CURRENCY = 1; + private static final int MODIFIER_PERCENT = 2; + private static final int MODIFIER_INTEGER = 3; + + private static final String[] NUMBER_MODIFIER_KEYWORDS = { + "", + "currency", + "percent", + "integer" + }; + + // Indices for date-time modifiers + private static final int MODIFIER_SHORT = 1; + private static final int MODIFIER_MEDIUM = 2; + private static final int MODIFIER_LONG = 3; + private static final int MODIFIER_FULL = 4; + + private static final String[] DATE_TIME_MODIFIER_KEYWORDS = { + "", + "short", + "medium", + "long", + "full" + }; + + // Date-time style values corresponding to the date-time modifiers. + private static final int[] DATE_TIME_MODIFIERS = { + DateFormat.DEFAULT, + DateFormat.SHORT, + DateFormat.MEDIUM, + DateFormat.LONG, + DateFormat.FULL, + }; private void makeFormat(int position, int offsetNumber, - StringBuffer[] segments) + StringBuilder[] textSegments) { + String[] segments = new String[textSegments.length]; + for (int i = 0; i < textSegments.length; i++) { + StringBuilder oneseg = textSegments[i]; + segments[i] = (oneseg != null) ? oneseg.toString() : ""; + } + // get the argument number int argumentNumber; try { - argumentNumber = Integer.parseInt(segments[1].toString()); // always unlocalized! + argumentNumber = Integer.parseInt(segments[SEG_INDEX]); // always unlocalized! } catch (NumberFormatException e) { - throw new IllegalArgumentException("can't parse argument number: " + segments[1]); + throw new IllegalArgumentException("can't parse argument number: " + + segments[SEG_INDEX], e); } if (argumentNumber < 0) { - throw new IllegalArgumentException("negative argument number: " + argumentNumber); + throw new IllegalArgumentException("negative argument number: " + + argumentNumber); } // resize format information arrays if necessary @@ -1370,120 +1440,129 @@ public class MessageFormat extends Format { } int oldMaxOffset = maxOffset; maxOffset = offsetNumber; - offsets[offsetNumber] = segments[0].length(); + offsets[offsetNumber] = segments[SEG_RAW].length(); argumentNumbers[offsetNumber] = argumentNumber; // now get the format Format newFormat = null; - switch (findKeyword(segments[2].toString(), typeList)) { - case 0: - break; - case 1: case 2:// number - switch (findKeyword(segments[3].toString(), modifierList)) { - case 0: // default; - newFormat = NumberFormat.getInstance(locale); + if (segments[SEG_TYPE].length() != 0) { + int type = findKeyword(segments[SEG_TYPE], TYPE_KEYWORDS); + switch (type) { + case TYPE_NULL: + // Type "" is allowed. e.g., "{0,}", "{0,,}", and "{0,,#}" + // are treated as "{0}". break; - case 1: case 2:// currency - newFormat = NumberFormat.getCurrencyInstance(locale); + + case TYPE_NUMBER: + switch (findKeyword(segments[SEG_MODIFIER], NUMBER_MODIFIER_KEYWORDS)) { + case MODIFIER_DEFAULT: + newFormat = NumberFormat.getInstance(locale); + break; + case MODIFIER_CURRENCY: + newFormat = NumberFormat.getCurrencyInstance(locale); + break; + case MODIFIER_PERCENT: + newFormat = NumberFormat.getPercentInstance(locale); + break; + case MODIFIER_INTEGER: + newFormat = NumberFormat.getIntegerInstance(locale); + break; + default: // DecimalFormat pattern + try { + newFormat = new DecimalFormat(segments[SEG_MODIFIER], + DecimalFormatSymbols.getInstance(locale)); + } catch (IllegalArgumentException e) { + maxOffset = oldMaxOffset; + throw e; + } + break; + } break; - case 3: case 4:// percent - newFormat = NumberFormat.getPercentInstance(locale); + + case TYPE_DATE: + case TYPE_TIME: + int mod = findKeyword(segments[SEG_MODIFIER], DATE_TIME_MODIFIER_KEYWORDS); + if (mod >= 0 && mod < DATE_TIME_MODIFIER_KEYWORDS.length) { + if (type == TYPE_DATE) { + newFormat = DateFormat.getDateInstance(DATE_TIME_MODIFIERS[mod], + locale); + } else { + newFormat = DateFormat.getTimeInstance(DATE_TIME_MODIFIERS[mod], + locale); + } + } else { + // SimpleDateFormat pattern + try { + newFormat = new SimpleDateFormat(segments[SEG_MODIFIER], locale); + } catch (IllegalArgumentException e) { + maxOffset = oldMaxOffset; + throw e; + } + } break; - case 5: case 6:// integer - newFormat = NumberFormat.getIntegerInstance(locale); - break; - default: // pattern - newFormat = new DecimalFormat(segments[3].toString(), DecimalFormatSymbols.getInstance(locale)); - break; - } - break; - case 3: case 4: // date - switch (findKeyword(segments[3].toString(), dateModifierList)) { - case 0: // default - newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, locale); - break; - case 1: case 2: // short - newFormat = DateFormat.getDateInstance(DateFormat.SHORT, locale); - break; - case 3: case 4: // medium - newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, locale); - break; - case 5: case 6: // long - newFormat = DateFormat.getDateInstance(DateFormat.LONG, locale); - break; - case 7: case 8: // full - newFormat = DateFormat.getDateInstance(DateFormat.FULL, locale); + + case TYPE_CHOICE: + try { + // ChoiceFormat pattern + newFormat = new ChoiceFormat(segments[SEG_MODIFIER]); + } catch (Exception e) { + maxOffset = oldMaxOffset; + throw new IllegalArgumentException("Choice Pattern incorrect: " + + segments[SEG_MODIFIER], e); + } break; + default: - newFormat = new SimpleDateFormat(segments[3].toString(), locale); - break; - } - break; - case 5: case 6:// time - switch (findKeyword(segments[3].toString(), dateModifierList)) { - case 0: // default - newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale); - break; - case 1: case 2: // short - newFormat = DateFormat.getTimeInstance(DateFormat.SHORT, locale); - break; - case 3: case 4: // medium - newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale); - break; - case 5: case 6: // long - newFormat = DateFormat.getTimeInstance(DateFormat.LONG, locale); - break; - case 7: case 8: // full - newFormat = DateFormat.getTimeInstance(DateFormat.FULL, locale); - break; - default: - newFormat = new SimpleDateFormat(segments[3].toString(), locale); - break; - } - break; - case 7: case 8:// choice - try { - newFormat = new ChoiceFormat(segments[3].toString()); - } catch (Exception e) { maxOffset = oldMaxOffset; - throw new IllegalArgumentException( - "Choice Pattern incorrect"); + throw new IllegalArgumentException("unknown format type: " + + segments[SEG_TYPE]); } - break; - default: - maxOffset = oldMaxOffset; - throw new IllegalArgumentException("unknown format type: " + - segments[2].toString()); } formats[offsetNumber] = newFormat; - segments[1].setLength(0); // throw away other segments - segments[2].setLength(0); - segments[3].setLength(0); } private static final int findKeyword(String s, String[] list) { - s = s.trim().toLowerCase(); for (int i = 0; i < list.length; ++i) { if (s.equals(list[i])) return i; } + + // Try trimmed lowercase. + String ls = s.trim().toLowerCase(Locale.ROOT); + if (ls != s) { + for (int i = 0; i < list.length; ++i) { + if (ls.equals(list[i])) + return i; + } + } return -1; } - private static final void copyAndFixQuotes( - String source, int start, int end, StringBuffer target) { + private static final void copyAndFixQuotes(String source, int start, int end, + StringBuilder target) { + boolean quoted = false; + for (int i = start; i < end; ++i) { char ch = source.charAt(i); if (ch == '{') { - target.append("'{'"); - } else if (ch == '}') { - target.append("'}'"); + if (!quoted) { + target.append('\''); + quoted = true; + } + target.append(ch); } else if (ch == '\'') { target.append("''"); } else { + if (quoted) { + target.append('\''); + quoted = false; + } target.append(ch); } } + if (quoted) { + target.append('\''); + } } /** diff --git a/jdk/test/java/text/Format/MessageFormat/Bug7003643.java b/jdk/test/java/text/Format/MessageFormat/Bug7003643.java new file mode 100644 index 00000000000..aeb722cac17 --- /dev/null +++ b/jdk/test/java/text/Format/MessageFormat/Bug7003643.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7003643 + * @summary Make sure MessageFormat.toPattern produces correct quoting. (SPI part is tested in PluggableLocale tests.) + */ + +import java.text.*; +import java.util.*; + +public class Bug7003643 { + private static final int N = 5; + + private static final String[] elements = { + "'{'", "'{", "{", "''", "}", "a", "'", + }; + + public static void main(String[] args) { + Random rand = new Random(); + int count = 0; + int max = (int) (Math.pow((double)elements.length, (double)N)/0.52); + while (count < max) { + // Create a random pattern. If the produced pattern is + // valid, then proceed with the round-trip testing. + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < N; i++) { + sb.append(elements[rand.nextInt(elements.length)]); + } + String pattern = sb.toString(); + MessageFormat mf = null; + try { + mf = new MessageFormat(pattern); + } catch (IllegalArgumentException e) { + // bad pattern data + } + if (mf == null) { + continue; + } + count++; + String res1 = MessageFormat.format(pattern, 123); + String toPattern = mf.toPattern(); + String res2 = MessageFormat.format(toPattern, 123); + if (!res1.equals(res2)) { + String s = String.format("Failed%n pattern=\"%s\" => result=\"%s\"%n" + + " toPattern()=\"%s\" => result=\"%s\"%n", + pattern, res1, toPattern, res2); + throw new RuntimeException(s); + } + } + } +} diff --git a/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.java b/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.java index 6112b6836a4..6d5ecd23f3a 100644 --- a/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.java +++ b/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ public class DateFormatProviderTest extends ProviderTest { availableLocalesTest(); objectValidityTest(); extendedVariantTest(); + messageFormatTest(); } void availableLocalesTest() { @@ -118,4 +119,48 @@ public class DateFormatProviderTest extends ProviderTest { } } } + + + private static final String[] TYPES = { + "date", + "time" + }; + private static final String[] MODIFIERS = { + "", + "short", + "medium", // Same as DEFAULT + "long", + "full" + }; + + void messageFormatTest() { + for (Locale target : providerloc) { + for (String type : TYPES) { + for (String modifier : MODIFIERS) { + String pattern, expected; + if (modifier.equals("")) { + pattern = String.format("%s={0,%s}", type, type); + } else { + pattern = String.format("%s={0,%s,%s}", type, type, modifier); + } + if (modifier.equals("medium")) { + // medium is default. + expected = String.format("%s={0,%s}", type, type); + } else { + expected = pattern; + } + MessageFormat mf = new MessageFormat(pattern, target); + Format[] fmts = mf.getFormats(); + if (fmts[0] instanceof SimpleDateFormat) { + continue; + } + String toPattern = mf.toPattern(); + if (!toPattern.equals(expected)) { + throw new RuntimeException("messageFormatTest: got '" + toPattern + + "', expected '" + expected + "'"); + } + } + } + } + } } diff --git a/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.sh b/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.sh index 0d7ad953fe2..228a2484a10 100644 --- a/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.sh +++ b/jdk/test/java/util/PluggableLocale/DateFormatProviderTest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,6 @@ #!/bin/sh # # @test -# @bug 4052440 +# @bug 4052440 7003643 # @summary DateFormatProvider tests # @run shell ExecTest.sh foo DateFormatProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.java b/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.java index 93540bf1764..a7ebfb79497 100644 --- a/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.java +++ b/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ import java.util.*; import sun.util.*; import sun.util.resources.*; +import com.foo.FooNumberFormat; + public class NumberFormatProviderTest extends ProviderTest { com.foo.NumberFormatProviderImpl nfp = new com.foo.NumberFormatProviderImpl(); @@ -43,6 +45,7 @@ public class NumberFormatProviderTest extends ProviderTest { NumberFormatProviderTest() { availableLocalesTest(); objectValidityTest(); + messageFormatTest(); } void availableLocalesTest() { @@ -72,14 +75,10 @@ public class NumberFormatProviderTest extends ProviderTest { } // result object - String resultCur = - ((DecimalFormat)NumberFormat.getCurrencyInstance(target)).toPattern(); - String resultInt = - ((DecimalFormat)NumberFormat.getIntegerInstance(target)).toPattern(); - String resultNum = - ((DecimalFormat)NumberFormat.getNumberInstance(target)).toPattern(); - String resultPer = - ((DecimalFormat)NumberFormat.getPercentInstance(target)).toPattern(); + String resultCur = getPattern(NumberFormat.getCurrencyInstance(target)); + String resultInt = getPattern(NumberFormat.getIntegerInstance(target)); + String resultNum = getPattern(NumberFormat.getNumberInstance(target)); + String resultPer = getPattern(NumberFormat.getPercentInstance(target)); // provider's object (if any) String providersCur = null; @@ -87,21 +86,21 @@ public class NumberFormatProviderTest extends ProviderTest { String providersNum = null; String providersPer = null; if (providerloc.contains(target)) { - DecimalFormat dfCur = (DecimalFormat)nfp.getCurrencyInstance(target); + NumberFormat dfCur = nfp.getCurrencyInstance(target); if (dfCur != null) { - providersCur = dfCur.toPattern(); + providersCur = getPattern(dfCur); } - DecimalFormat dfInt = (DecimalFormat)nfp.getIntegerInstance(target); + NumberFormat dfInt = nfp.getIntegerInstance(target); if (dfInt != null) { - providersInt = dfInt.toPattern(); + providersInt = getPattern(dfInt); } - DecimalFormat dfNum = (DecimalFormat)nfp.getNumberInstance(target); + NumberFormat dfNum = nfp.getNumberInstance(target); if (dfNum != null) { - providersNum = dfNum.toPattern(); + providersNum = getPattern(dfNum); } - DecimalFormat dfPer = (DecimalFormat)nfp.getPercentInstance(target); + NumberFormat dfPer = nfp.getPercentInstance(target); if (dfPer != null) { - providersPer = dfPer.toPattern(); + providersPer = getPattern(dfPer); } } @@ -174,4 +173,35 @@ public class NumberFormatProviderTest extends ProviderTest { } } } + + private static String getPattern(NumberFormat nf) { + if (nf instanceof DecimalFormat) { + return ((DecimalFormat)nf).toPattern(); + } + if (nf instanceof FooNumberFormat) { + return ((FooNumberFormat)nf).toPattern(); + } + return null; + } + + private static final String[] NUMBER_PATTERNS = { + "num={0,number}", + "num={0,number,currency}", + "num={0,number,percent}", + "num={0,number,integer}" + }; + + void messageFormatTest() { + for (Locale target : providerloc) { + for (String pattern : NUMBER_PATTERNS) { + MessageFormat mf = new MessageFormat(pattern, target); + String toPattern = mf.toPattern(); + if (!pattern.equals(toPattern)) { + throw new RuntimeException("MessageFormat.toPattern: got '" + + toPattern + + "', expected '" + pattern + "'"); + } + } + } + } } diff --git a/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.sh b/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.sh index 7967da9f070..7f4e902a914 100644 --- a/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.sh +++ b/jdk/test/java/util/PluggableLocale/NumberFormatProviderTest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,6 @@ #!/bin/sh # # @test -# @bug 4052440 +# @bug 4052440 7003643 # @summary NumberFormatProvider tests # @run shell ExecTest.sh foo NumberFormatProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/fooprovider.jar b/jdk/test/java/util/PluggableLocale/fooprovider.jar index 29ea53fcca62228087b1f864009aa21447af46c2..c1b5723f9b95dad064ed0393dd878cd7d82f3c51 100644 GIT binary patch literal 16789 zcmb7r1z1+w@;69Gcb7EMDc#*2(v5U?cXxMpcZZa((%s!1f`CYTaN^4Go^$^98y}x% z>$}#hnZ18&)~pFx2@p^eAP5KuAXLvpE}$0#2?PoxC8WqlEha5Y`!E0m1Og;0@fzZJ z#H&As$^PSHl&2B@nJmR8Eha3aphzPnd?7V7C@DcrGY%_3O))YwS|?98#kjU@OCv5t zB_=iQPznl}e2BScw3CpJwoS70*7ydUgmgEbf^`=ibqk#&5$K)CSKD)2;NL`%oYOKE zds;~R>F={BP(VOW;{B=z(o0e73~e1v^bPH3|5!?d(Z|H1KV`ptbBdBX{ zC~ReGp=&Q|YvpKSU}$SGL=WXn2g5tQtN@yROfG1B0mY{fP8`uFcX>6V`EcjCSg(yB z6H~+?jS?vdO|1ATY>l!z5FNZ|QDC0!a*ye~@+J9VKlJv1suMxM)}A?}QMdeo6Ep1i z5g;6u=}Fwz5c9V@N7_%qdHkX7-+wmF|3!R5eG>~^^WQa4aIw&{GPnCv5v3t|IKO8_ zG8EqHSxUT5F0DZjaTJE|S-VZ-fZSgE@R)t{tq)0$It}azG4Tx-*MW2=eQym| zvv)403?dU!j_(f5?Fv2Slrwofqa;es!LAaKGHISq1;9s&N)l0hot%OI2qL4 zRPV)qj1&^2E)TUG7|1_dPHQ;5dR9m-a(Bt}NnHPbRfz6?P)NYa++5e*%J$DsV;D{k z=Zy~oy)wS$iJwx&?l-}Lf&!`!l?%?5)9Ka+6OKK)6BR|b-xSl!INxU}}d zO)biE!xX-S4i&C8*$ev8LT}}mnPy7TQmX&46`CAXupwP7T||L0@eFsTVU0~_k7se>93sf9YtN)owHtz=swuC8TefL z#S6&E`U#XzlrO1ik1ESE{}?T_4E$}k7hN^K(|?lD?+-2h-nfB2{i<(e@tZmO`w`Cu z`+0s#q^Yx2haUj7q3njV8|3e zWN-;D+qYd)l}Hy2YTv|}hH-Z68yZ9=!^QsDiwT8D9L){2};=uU8Iu5PZ zqI#ClM$kEigJ!@nE^sAG)aK~rNGgj|M`;RM(L(Wl;`Kl*!@K(p5*QZUd95Ccsl&$2 z{e%$E-t~Ku#BtsPg6cv<)wg5WbCr!Jvj%?2-=r4n#3s#=ukko9S%~jyC~?GD(oB@3nz;G~9jWbR8yWp>d#p=UFqOvkM+R0fH{8m)h9bIidX^UG(x%R zP&t4g<4EON-JUcEMrib8#=$vye}G55df(MG!m{W@_I-zwJOoAH>r$$8Az%#30s$;_36Mk7I{6h8MMtpJs!A1fAz{FzxBOIKi)L2LmM|F%W zbk#j{BN$1?H@c6R?RTE&HI@3?5GH`n1J}%Vl>N!Pcy_FU{p*8Q1l@$fr>XjlXi3SciSmhLZt8SV{Mcg0qZN**uE@Tk#H~p~`rQ<4W17YIp{N-1O z6PC=91;2Q^atn17bf0tZod0%E%zE55gFV?Ej@Q3?UVrb35Wg@g|LrmTG%FQKs|wgk zC=WDZa}ud&8c?V{sf~?kDEugtjowrBBnZR^umOQ;4q}Zqx^WR-Cdj!Vds#EiyHh$@ zhic{>?dPow8uBnp5N;1JowW@+8tdrkvz!=V7Y5=kW@;)}D6>&{z|cks*k zcDqFwvTi8B(i3N-_O6~FPylm!0;$x{q~9G@zxca3s|o5icV!(aE|p$U%nbfXG=a_P z%-IS=a20&k!L?3vBc{L|F|H~p>Rq(@jqp~T=z@1;s)&62#nS^MfsMS?Gx{8&<7(hSSp;KtT|%hVs`1M zM)|%~EE}$OC0U#H`$ge4Ej2on(f9;|pJ&VzN(mJAB|+cEI~eL892>o_-!d>!m0qTZ zj=86hIDA>b!Y%z^(qAw6wY>bOpSuxk;TY;ZK4{getS@1C^z<#J;dPxGR77%h(B`=_ zYg|qsduqj5>Ku3Fk!3k~OZwNd5rB9}{#~n!%DLC)F(&ThLD)ob{zRMINbGAm10QwxhKh1rGNr$dnkbX@-El zt?KHshmZ?creaw+igNp0QV=PI9K2;^yX#DlU8V{2gN^UXD1OH$OKY26(T$DLIkT*~ zz~cr)Ne#izuMz2q%;5bVdu$u54uB`m5a!S<87tgK|ZT22o!z>=Y zUBJ1!@qVXsaci>iM=)f16r9ICx;<8e#t1-{iv?KwY=tF%bg6Y+zXgFcUt{T!b$UeZ zN_-4hMX^aCW#gkN4A!oN>*9l9yE}=Y$xYM%Ibn86SjV8YIC+ScI@icR8yKDARBy%U z1g%7ZoA+N9bavxeA47&59nbpu&K_T=BAsY~#k_}`Z?4}{L{WAJ!;?uwJBHLVOO%IS zx}|X}RkFoNG(Kv;!qyEF5KBHvbg!yzRsSuLAydNB4;<=9vSo`VG_DPj>J6Fy9cK$M zU>m&>xyM1iSvsby-=+g!qbT4o+?ssLv{b6jJnPEjzysbWxKa$M*X$}$v zd$fBpVt^+X>7TEItS^k%-}-~kc8plq%IYsa{^2jh4q8s~q69vQO*Av-NDUUCXGBemr4~zbQ)UjOon2HiA>UF3WX&$3?m*jl*zdFc(9M zq0w}B4C1uGEMS>d;i1yTb;ZL5@}a(6M?}bTbvkJE;?1}TxyNHf8AC4Fn3FG>w3!CSS=ZLol?pvDp(Ge{4Aw$xpDq^{l@6M+dB4ld zPK+`Z5~|OykhM6E$Y+G+^<=56k)dqca>A&PoPDwmRokfa(Lid#QsLoc;wE%LnPip9 z(5E>|c9GH9An&kC<{42hK&@}NYkT8Pe{Ns04YTCk>fNv1yrkU%a)6mGHH&A(hZ&9GiLdLG&u>*FS+IXrd^`|TACo*gAUGO`Hy5%qFX>>3u; zf>5QAT!71mlu`A5@H5zFXcY}`=Y9hQ0xEuj*FQsx_XV_mo{zs=UjKyGe+~EpVhM{f zIEEOXvV3aowqzH4sW1H%lZ58b)ZoF?)u2N8B{cnK@P>ehBLvvP z)RgM%2s@*X@27F>tJ;i_h3_r)q;H$Qw{U}Tr28II&N+}&GQ?bb?dB|#@>-z;)z>ZT zIA(>eyP`%j3qw_iy1?RSO4gSIy{KIERP3J2W7ML#PuwjSo%dlpLbY{_Zb?YHs(og=c3$S^2q zEM;nm99&FlYE#n){ttB_8g57`QGTiNYXNH$REnPx=6h z-7!ej)f3A$vh~T1B;7jl5kvTsI>iucZ)JJmu@_5~dg6y1Seeq~>N9py>Uw=~V5+Cn z3!2)vp;~*(`!ipR0AY~ORVeXzPBvSs%!i~UDzcb$8r9}-7AlQyC1}mP>S#1J(g{ji zeqq*@ib=~iSM8zTP>z7b8By+26!5ynQw~Y>&}bh!#^Q9r?idT;&)Zs!%SStaT9oGb z%VL(^(=r)L)dEVDLU!`hYIO9ByK>)3gQ4Nl>K>`BYPGcls>*k&^VLy76GNxCV>f^} zzq_-uP#Z4{c>i-94ETWa>b^km7Vsg{oU^e=*(|*)xYF;?F!}5%+4<~6o%~8>qZFkI z5gf|0aq`O12y#M9h?;!}^kKslGkDB*vHEAY*^a&W(z)OY#vd_Kt$p%0^IJZvY70PN zYDGih07%kzhUK;bxe818P&Z`{%!oS$yeJw%)sPggn}X{+;c=1F@p4bTQXGVBXTCPp z$q8Hsb~IX1h#!6Yu4H;*mt9IY!A)GOlCyzzV3YAZ&E338A84`<*k18IAY&lQV7J%* z1Ai*BBYLX;k(8cYfbe(+-wYVLX3eFk=<4SR%JDLS4mIH_OR*~9edzpau{U(ugdV)N zX$hCh=a;7OTJKj2;vx%X`ENBjFOWLWCd>>k7ZNYk;vYOFym)UHhj@tZEhbh=@_Ddi zs)Y7=2oC}Fk^K{g1oxI&Ge{kH6NiSEw~3do@ejxoUgEcHL#HthH2XYd`KKX8vw4@= z(cic;R^Gc3<*)Wul?z(=UkYP()R1%_7CZ)CuEu&sd>5Fgit+4-eQ@S{{?E*Eo-sB= z39G*fy&SWUD>p-KLhu`98O5vpc{t+B0BT zR<#a6m1$Ts4`=B8PHCb-gq81s}JWiDL?)E3o z36{YGmgsTOh}Q8t*j#w*5J2M%Y0*qL!<;Ghh5wN1_d%6_UTps&t+95aFh?>hp>`jk zYV;h;B1vpBC98-%IW2ATyuiQe%wc%hC%Z(?5s!1J<=UHFfA;~Nt)n8dag2BFY z1X~)9gd`g(H2v8I18SPZu31{CB6N@7Zg_~H17frvI#PA;{9KlcZeXDT800{WwgEfH zj+V8mbYpBb`wcdL8;AWXC9+hrWGIQ=S7i`VkuAppzF?8@>fZafnv^-F*Dd35_Sy7$ zi3RZ%j&)Zjb#Gv(IpbEkt$b(&`ErA}g*`4kF8Oq#_yb<3rr{&fDENuN)={J^oDcFZdiIs60 z_O<ylDg-Ox)3;vA-{KMOdHJc2%1(y`z^Eh}3&EzQi~pd3sgM%CkTyn_!i%FoL0VxnIk2QShzVPVbpl}wrp~U+ zjj%W38O_0PEZUSj0@itqwhO9e?lkCltfPXzA+Cat*4{*!H~Gql`7~idJu}HuZ~Hjb zK9Q@7*l)?wWYUhptg}fUor*_+f+Id;m@)>;hkWx6z_3XRmYUS=OEMPIplQ~iworfP z(6T=^saEehq}{Bg-;U_1P80q87*&;7&W;{=_ia`_K(2J{ov-DV2A|rLy222bWz9xG! zCKZ-|yxMt%B9g{UD-Xlyem64HMsrZx)}TPoh7Dl@YzC06%M85PPWMVqd>+Sb1t+l+ zYfhT|aNFheZX~wtL>ZPXibrb;B9VC_RT6a*KHYqA+6Rq>iPAD$=O7y8dcP>pv7t9V zK)&slM0A)Q9VrfPQ9#YWqMOj#d_zO@^nqk-c&%Hg<-w<5y90z+*X9B*r*K427>;Jy zK>T6vZphhZupVU0I7@*Ma6~!fHK1G-V}wiIu7iTDJ$M=J;_RW5td001gzti51N*gT z@@wPeAZe@kUhV}&;XrpibA{vrF5)Gf%2^D8bEV4Scl<5DFf&_0m`i>1g%6@f81#s) ztB7(Fj8h0A91)XRL3t(7uIaCAs5Ve!HZ;t_^QJe=kpb)GtSGqM$JRkr5S?EwfxUi9 zeyWgv01J9b#FBvh+rf_e0{TzLewmi}9nlpE>Q9Kq;F`3oqQU>H6s-rm4_54bCZCs^ zFDPUpFF+Q@!F|~kS9QU4H`bxSd5AO_8^MEv#w$+euhkYgoVRx#Hn-eq-s^W z3*>#b8cIhpGy!4&{1=EG(R~HA-uA!%1T=>s%VPx^d zxDO!6F^nc4Nhj#i*)$k4V9ukLPSRj(c!4cn_tWibeTMdB-xX&+yrSo^fqwlp**v1J za>cYB-%MI;i%N4>M|wawDZ)N%;gcYba!Dpl;_Wx@5N-_?dVgJ5B2r;`;n>)6g8_M? zg^ASW5F6wsIupV`a^xmN7WxRxz;%fvL;J5#T+$*+Bcyv6MSVtFcLjS7!=1 zq8WY#o!!^$TwZXG=ond?)A+hofZ$&IUeBR1YNh3=(P(boaY>Ir`X)M~Da0G+92j{} z`Aoh1IKmxr-{Vjc{!|eKL^3Z;K1Irj3kUy&?`Hl?*`!_>uHWR+B_9QEQ1UX5UiY9J z1g8@kxO=bj5Cv9|h@c_+1K*J1(YI#Hu}n(&xcFNSNFZ>TF=~^AyOhHnnH?8cB29c{ zuN!u}vgUDmCFwMV0nDhmN zU*h-AtmsdlG(zQv6EXnxVMfhmR?jB*qjv}acz;MZA~-TWeHE6z0-}0z;;}OCMCEqF zd$$6m0@OL;dY|YI7p52aCYe%)6J*h!cH-l<(laM_(jO4-1G;keiSCV5Xt8ZJv`>bX z+;&Ht8^#YAEm^JxwhvU8b*Y=S$WqxV~Sco3)Ha3fNWp!C^1va;ZsI>ir9FikpqCuqxvVhwCTI$qL_feIx?DuusCbk!bh+(nyhcy}ceaD}t)3B7mIE z^_9*!QPtfz*{;>0318ZTrB0Lg?jyGMjS&g> zORZm}5(hY05hO7(e3>r}WBr1$*wgf*(TxI-Y{T9G_TyMX%?ZQ6aA`bl($BRKg5Y!Z zc({IkxCY72vZCt+1^YUy!B(vBr;@j)vt)%(Eq?L)Pt}IUTYlS;4`8aBV2NX@^<@O1q3-SlnmdvLSOL+pPpUYuzE(S<24j?#m-loHjuo856rYayV&u#l5ZLI^$@rHj<$p z&l(lvAE=JLW2xEfe)uJf>Ovizwgs1>Dn7n5IJt$Oo*HGLh6@FXt8??NQ`E5jf-@?+ z3?^t{d3>SE^C(plAg_&qwPcC?4M|Nx-M$Fw?QyvJ#rJa6Nx7cF&`CrhlR}5Vi{Q~h zfJImUR(XDz;>3`E%{LpaSvGOxd#o_^r0ZCUbswzV>Q7%dST=?@p@lUMWMXB-4~%9B>2quUW1V6L3{HScE%2I`WgW)jaB7`k!~5_i|%N~tQw z*e@!!H`!ro(v4Nb4u=sFxbMQg$1>{(Yu@P?eob}22J@A_GKOJRkt5AA*KE|ZoELj4 zV^V|6f}!fcnu%iO;>{uELC87Xj4QZVM#Q%90-!o&mA&mokn)acov}NULhDtN$7hS# zOZ4!{%duG@06YFCs3 z-$rdL3e6_wmbv3Ps3bY#<%Vy(AHTqA@NAsy1fjNnxFZsrueWzt@;+s_(h52{{ptno z)#HTwjau{E|EPf_yU&teN^ozk+MBnjy+Jh-5Nh=Opn%=vnH!|G7U`YQJWJHON^{dhF++=xfrM?@d2uA(bX$K#;eHXul62w( z1&qGDdd@)l0fjMig;2M6@WJ>M5|We(twQ_aP-lb(@6WCG}%w z&NsFN?QFnB^K04-t#*Irc1ffv9Woy3wsWkDd-k$Nsl-urRv#w~`7{ErVX<1@)3+GP z2r9;jDBL1AoX*@HUq4@yETcr&P@hw^aR25jQocB7|0~-3-=}Sc^0ErH5XvJggq#LX+|!rpv^O_PTZ0PAsB#rX?QNE!?*~=M_C{`3d^phV9%h ztk$~DaClCrAZ25fBY#+b*cmzX9O+>E@niM3@XzYaxZgNwdOrr)rl&@?zqb>p#<$)e zIYb+7Y1^+fWRN^q^!+uH!_9%1z^67T*Z0Okv38Zv%>;VNeNu>TZpH)SgIh?kc7@#E zZV-*!&PA!;2znC|QWFvpQu1%JTS0&RJ|6L05&{i#j9kc8$$H>#vW-fnI#49FY!tl_ zn4_lOs<%i%jh#RuG>N&egAC0Sfr2X)MLZOqTP7Ds>co;W57)ci0km;;oS(>uQe<2L zv;3nm$n0B0ba3>vajK0Y^+9M%7%{E{qpkaDCHq3FNO!z^c8B_??ZJCdgCX~=MiXJv zS6MYfB-CYU=k9!`l}VVh9IMq&u^$LOvN?{yHC)Czifci}seL`}3bomUdg=7W^n*TU z(;M4GW*2v+Idzt>VgE?%#ykwnST6MP{!7a`9EbT5hYY5AVqB6sQTn#45^IdU^>8hl znJlI-W#NpmX0sw~j9Z{4qIHLMf*g1P$a@Ir_wm_8GPP~5k!Bs<746YestlC{+8MIt zq2UZOJr$bpG>qpK#<>P=wqi>a898AUPMV-YgH75_9my7ff{>DdL1y)Az|A3zZ2AI; z@FPmV2s}RSHD71hWDFvS-=vE>c==*tp`j4QF)E%HR#3IF-T0z~kxUYdcJ`^%Yf>Pl zq;0xsLpM{d<0+ReT!BhD)H*zN&vg8l0#>KwF|Xh(A5kf@({5ITvXiP>$LWpH^s1z| z!etk+^wseJ0UI8xQ^#}UbK_1;uP~ORRNex|%&+BCWP@l+4db=;qMR-H%m&3zj-p63 zhyXX!XleypCjWZeZGHjsP*j!xG&A@6RH-&x_6_!*yxoO7K-8$cV7Z=_4KQ1-PKGl*h)`ed)P% zZDPnzrxdw9g zs)!E@-$m8@v ztXYV68$z)O+s6}P^-_Jx8H?gibcPPzq~?F)%W{Tp08B)6Np`OsOspa`*;K!=ntR5$ zAfG8kXxrwl=vfl3|0Uk(!+mX=rAF_$!N9Jqc8pBC4MR&LIMfzB`^-84Zjn6RcO|5F z4oGSz#P{4%$&6`x(vXIrGvl>x7`17ifdY^Tn|d$nY-4)bkHE17s@ya#bLE9VeY}1v zBK4}}8V`Po14;gC90>b`fqM?~{HI>@_p7jj{Nhu#7J(~`)#jj;+8<3EvOpzOq8p+w z4%kM4I3Fm%mjYM@`@?c8>&hDRhRQ8i`z0{3C`mLz`&YSORRAHuTUy4p&8IxA>gaD* z;pPBb5O4~18tl)y4&dyS#gnN}hwRLXD~h@j0A>O1gI1V?8ALBY#ryWCipJT)9~<;h zLJEOgc#AOo99nDr*BFka0@bzZ_}qxwe06iS!8TMU z4uj9YPHz;+TT3W<4-YUD8tNV=J(HU&A&%+oq-1WExiDR7$UxedBf4exF6eR{or>6{ zzg?l2%3Ey(AB8qSUK0ft*yQYH5Uuw)9;5bZaO{kv6}4v#tFUj4uUp@^H(dF58xIoO z3r;F%4@!}X$hc{erzZC*1t#o!@e=Gv4fQbDpcx|XR*MGW%-3mX8e}Z%-fV^KdL}8E7N_j8tpbe$0hUtT`xm^2-E)^ zr3MmKeakGZbc<%QtW?;g@c~m!|9Sx^Aj&I5Xn@y`P%0LYSyb{1ra%u+zt|mYD3eB@ z7w;##col4(oHzPx1^3?4Cf*bD_QxRgcaQ|O`dCdi1i0^1T1Ja`N8`U#_!M}{bD<`) zr5IZ(Xo&UG-2Vokv!EX$H%|#$Gmw8fA*o&f=r8I1m!~7KqKmcR?}$oJu#j1hMe(FT zQOky+pxsE9-qrAtvLET-3y-V`_y4Gu0zF^kn=q9yGo@GS)u79eM6G_;{-)t*DH0xo zsdsUU)8m9|mvc8W^Wov*9^G4t6Q0i-Nf=xe(F75`CwQHJ#SE#i$3A%%?+^(IhlQA! zjXO4aqnUhzUZD8W$jPc{>g_2#M1%~0-A|*2YMDG`;Y)~TPqyNsBa4^u;`gM;N{{m9 z*1VR+i0`5y!Y9l)8Z9F_$AwFc^Xf7v$M|5>rg(8`PGU}$}*S~_{}2d zOjDz%q-X_8B+~dJkXGS()Az0wvljc(0%j@oM6TZto~rT+T=O$bT@>orU8Wsi$`n2? zWmo6wVxBMyd=2GH7~*bFddHr)bA=Q8jnZ9&qH&mSDl8|vcKQ$vptM4ITy1)t-uSSv z#-i5DtP>&eIeFVJCb1@fj4+d-JhF&bA9&PYse9t1BmoUkw^VEz$_7kal2tc?aayC0 zQh&nG80=vMQOB|Tw#4JK(Hxd#F^g|NS?84DcFzd=uwA%k=tt?)Bq#(@@MIjFP<`{r zCVx&af4U%bon*2`$mv&^J8D`pr_zdl?qdkFU^PKRB&lI1(`;)UF~ld(&a9 zZB`Hsf}pJzy+){O`ECc=70yZ<_f1XSXRC&IBeu9wangh_fJ^ zvq2A09AA`Re^%d}M`~Z;n24YS_-(RmS~qv@0p^@B*aIKzb@joz$Iw~iScx}Ip_9?? zNj#7f)?>k^K#9x0mJ^WuFX;Rom>Eh>**jsBhZ%HY4Ki6iOKPd%0v&-6byo?xeELsJ zjyM7_KCEK2{K`1Gs-1gdMMTD!0e-w+4l?gJZw6a~d6B-P72Bu0nU za7Xm^F2hONARO+02b^Ll+Dt=8sVCPb@7+!-L=_e-wAI{1sH4=E8jMZ&mC*9*L=)%| z+8L_AsjuPie5$;7OKL@P;xK|_N}&-MOur42$j4cj&ZYa%PirbCaY|IihjYaw}r;XoXMOTzom_oCUIzJ@DN;Epi z&?0Qw_BVet0Xyd=^@AWHTua064CtXNP}|5p5zP+N6b`NUh|3V;O3p0H1MluMmB3 z+n7sB1ipBCb+-^E1?__^J7G1al#uyxtTb!DNMg%PYxn+w%fYpu_j%hqB=;J52 zG@5=Z^CbBaW1}387Ol?J7?7M9{Qj$T^jVg@m>cc(J+-!=gs{QyKt-Y78*K(55E!k8F z-^fn9!sxmqrj2G1O^vyVn(g)^^&=2x;DzQRcW;)8fj`rQ<{tC?!MyI$8gydX$4$y6 z^vEi;b$!+=;kv@X!MldeqZd5&ajK8e`Awb^cIVv<=^coJJ(tIpuFS)CeQbVDY`xA% zOY-Uf7Scw9rJfLW>4zC(e-(BqRiCiFQ>6LHsSP1h%S2PVk(I7B-5egs-m@==DVI25 zV(FzLF&X%zHhQ&VK3|GN3?|&DNKHyzBaUF`#gOCr;Uu{^2;*3y`UMM1*=kjSLnI|F zadZeLN{->O1@Im#AiMYn+*roRc0Cpi#P27__w8{%Y_)rh@+_XUVLhv7r=NFyhnS@Zif&Bq7pO+7)OuzrF(s#pK zvXS)3?C|{IS^a&J0rXGPqo-^8FMS4Re;ue~Z(?ruhxer*A%iUUR0N#in2ozqPxuvW z?=nJJ4it)?e!xzBKlf%@I@}4X1FmP$z^Ebf`mXnZ7@gmCk_d7j=9vk=>ha?jcA6y@?GVb~fHrb~eR7KYI!>7K2ugB9;O%tHU zm9VS9OM8k3W!j6DsBzMj`J-VF(B(nMksyZWy@?~18Xv_J!lEdQ$&Qeih%Bh_he4g3lP=&vR5Pe1)e&rOworT=tEKDSuPO8j-|%MQoq zmdc;R_4N3ksV^EVpE*DQ{rxU|?u7hFpPwH8!{J3=w2a8TpfLo*w^u{{Ph{ z`KyL6+y9D``OkRD zubf{xr_ZFJ*7(~q1aC>R-+1^6mS)b0)*wvBF z!Oomc(B4?zQrywlUfGX=#ZjTr6^V;NmTEujJ zntJ`y|KEdS_!r=WY^|(*#^v<~uE4cFaEbN5=?dxU>On7^K?cZZq15>;uydnK;I4f2 z*ja1*8jM+v^_CA~erPS9*i7SvvT8=*kwJ(Z7oykcx+l9i@(sZXEDS|HG>i#|w4SWr zV_78Us9BY~`bSVq{{ob-zN0a~*4|p* z@xRLzIK&78!ie;0d_K*9FaiUh2$g_AJm(gu@8U-iH)O-qw0k%V47OHx`~<7&vgsMt zGRAz@S{Q)64Es>tX)ETZ)q3}|THZQx9E=fi45(%x9w^_MoJQPG29)3;YT60sG#(LB zgcR=ekMQfCEDsWj1Fs|7^=Z}>|A>q8{|lF*o3(+hmBWAGIgM1pd}2WAIsMGjEr5al z)&vO;KX;Y<8qCzALyS%}&a%?h7Nhr5-NS?Dj9R_b;ZX!LS6)RU7r;d%PX;E355rrc z_$#pkUZGXP{TyWl<3E4?z$8<{%5d7 z4hORSPf&XP5iHBU04w8UZD4HwKh0IeFTyqO^^>_Kr?V#0xO+GN30xoEExU1)-EW7& zLgds1ayitqH7IggB3EmU2Z~aaU=bf6HtFzit!P_t`qWkgC8JJ4p~Co*e}L?G)P3<` zC^>*!$S_^6PtB4ak&3A3K`BvY5%U?FmB0Gcvv;Za54PXCTCk^I4Q;KzJJ;X0cn%@Y zElg}}|G@>*{M72Vu2$UI&WcpY&CZz4&`RII;ho~0?SvfK109-%1pC!$W#W)@8js`9 zo~Hl?xdAEBkX#zkgOZvkmt<4C=(V)inH=urd&R$j1m5^AwGJdxMuMrxoX5c zoa`|Dy=m`)B5tQL^NGma?FD{=J__pI`B#G}DbpjxyuBah8>Zl425}R{7mP!6VhYl@ zvTBO~3lr{M!A33Ott4BT+b_R#tI73$aXE{lI*zR^o%brpYh$~PSf7QkvWEtT^<=<6 zKUfV7DS*R`qofSkNcLM$!%bEXKo_nLwMP|7(!X7&#qy+`tSv0IV`6pgyx*=|{vy9+ z`8aJdhizNP?blG!Iwi8Dr60cS7UT`1s~?jHg9HFz;p@NM7(%gyc7uV^gC5jVBdV3@ zOXLB&gBj&)&J1N-B;I!!P3Y&3oQ`?KcU@dsU|5RhwF?jVx^>) zWwIU=8uW^i;8uR4yxpX(0&wW7aHvhYG%G_>gG=2~F+KG)*BP*(7ktgjf3a~#ZUckW zvQdflA&nuv5w%{Pl*E_9Ia2Ur3_!uN*PP&ktfN8A&>5z; z;9<^_$Vs@@T6(|ws$ zzL}{?3yx0ruAFC1+VPO%>TBfi%v900RCn;qD(XseG-9W-7JYs^jFD1yD<*HG|N6}+ z_R?p$Gd(vlkTaepX^!c&q@Kss;UVRvrd-x-f#uB(Hgimw=W(14k7?0pm;A;k^EI?c zO$uD+JMd+!5qa7pjhDHn68l$>Av2EdmKVM0fXS?jlwQSswkc0i{-Yyc zAfUp3v?+>zV^e>aP`dJpBC0CdgAGbmsv~$Kp+)M%Nlx?|EXi>UP&26Ppq^LIf;sm! zRx|Y%cSiIIenw>JPe;?moya<1>7ySW!rwkOqW@35F&*!2ftcdbQrlmdh&i> z7n|B1?+?J=yq*()BP4jmpYNB{^Y%>%Fx;935+5np5R4cE5iy-XWE3UccEdFb6!0u3 z+i*7sW+rqW7~w`xNNI=&vZO#2A7&*DF@-^(COdd(m>TM7U`TU_CeNicurADXShmA* zm5H_VXQ`%?vigK!!aQlkk8wfk94RELmJllg_f1fl|Be-GeZ@08G*~3|mGbf~%()CXO?@Q2_&Cy?)hyvJatn#YMKT{7h3S^YO z-zIk@wmA}U!IBYuPy5jsmCH@F68+tEfpo93)H}boA_)FD9(1ZDjg_+!`3wd2OEdiU=_9=T7MyxG(btaz!^F`AXA^_PPY08z#);c@L9=ehZMw(wQKp5%X zMZl&d1e{~VAqgn8v!k>Ieqt!s$eY6-47=Z%=Yo9c(o_uI!0yRR8Du^nsDWtOXmZ=NsSFAct|7&C-A z;B&3ITRlBOL@X+Be!*8vz4^_2g;S+0@)U{$%XrsggPaMD1-FxOzbpn$$d)g%#be?# zP&u{p0l76$jje~_U0O?v9+u5`7Oln=#=C^(3^f^2RfR#gn4xhFIZ=87U|fESdX~0I z?>w!UA;EL|7WcNCV66y1*o$`ha@#SI(>B-f8XW>>mrVwS5nX=_xa*u)aZ^P!!o-2{ z+$wPeFU#;jhbbM{&^+M;0h`MpsoD@{G{jL3&)k}E<%{tW?pORkh%K9rgW{-e{u3|X zoDRyKfv9`2FySl!EcE!}J|U4{=LWtJehhIt)9MO_cP#||YTa?}_~NkQ&RslmBM0Kl zqq;+KBh7_NcomcXeP+T-)mD}_Tk15QqUXHpf%_X-eQkt z&O&tU>*AoRl`nxOQoLyBN;r>2mwM4g{OIg&L%B?kbx%H=WCrNhJ4%t`Qy4HwsE@|+ z0i*z-{oNQ+bT8t>cS4h-^EvB3kxOaG0aY38afzjW*{bdhE{GCHzKDb%^!Tkf|5$DQgocDw zR%16}Z9hug(m~LYwDd~A+PJ8$>t*0+S$uMQCCTkU+xVm3>n?{n@f>SMDU*?wowSwX zC*Q;C;`4aEvjYS;DSJ!ww%d+igNfXZH3;?kRZnnIJOi1&Mo<7Fw!9~)vs)y#@4ec~ z*#I|{Pg-!9dOB+5gKF*Y(BP4>#$AC9@?bRfi<|Y`m85Z3*u6V=IK520*3i0kp8coj zy|Z{Oq`N38Sj4xDHX3lJ3+E-(!_!`q1H;^8OH4gjPv)2!yK<`8sNIk5HCs)+85NmY zyQgcsD{h*A^=VS(vmOVR?R<}5OQS(O`z3lf&1u-0Y?yyQBj%E!ST3`+>>=4j>ETVI zHn9zt7gpS7<{Logs5Ey%-d&_*SL^$V#F_H_n$@|iuI{WR2RP4Wqng-v;WA6K*v$E2 zWo^Us^&^eyY>S^Qh8t-KqHGATZu(zC9 zg5n_WSe4mn!z$Xliv3vSW^;s!wx(Pq1RyZcl>)u6*gA`3HvNv=0j=^(7Oi`8D0twk zi>RKeeg*BA*BvA39}|p~94#lxrb>bikC}@UsLgZ+E);4v3Yy)^w(DEv38WeExaSPO zos_TyOSnQCK;XkR_ACWtXT;SP>^y^cA|Rlpb4qmcb-71Y!c0OAmwlQ&9>_PG71hXd z_sC<^+GSGE4tiU)<`5UyALz+An&phEe0hS061uGl2Zry(lfHLrbD=T(VG!=~h5lE4 zfTev%pI5=stT6kR3H}Pb&hrSW7MaexY7`IG$$oUG1Jv%Z5<^J)`pPPa<9mLG5Ep2n z%&?R(nv{=XW6VL++9==n6NXSAb|=||Gl!AtU45!I)PuEpC58a3e&9Z=T-gWCvkZ!3q;mOTkx|zGvOg)Eod1PhN!^@}Im4=}%te|K?tP_?0r{B}LpPzoH%cA<>bto<#{} zs(RW+0p-0~Ohqk(1|bv+PFT=w4e3ICw2@)e9@>-RO&hshmD0sC@wCtHyfzXEE_{1A z4EYG3f6ZT*lhLG}0%LCKIMm7ebf+6R&hR+ePUQEgN6bPLp$Dm-14B=2b_JJ*&OzyE zK2b_f40IMT+Yn4W`4k}z%@|3k-}WW&tvPbWTGBha8fchxyo%S&BQYnjti7)z40Q@8 zQI=O-<4F1|+h3<|&_>pAF0Z*JZtx;R7|IJu2&Q!8EKR+o5n8z1BU2zT9_$0;5634= z2V+O(vPwo-CgfqBvr4H9ni4~om~AqH7-Bcz03>j$S&bQ4BC*^$8~avaz;>_~4NWvm z&63&9Zml@$3Nd%8yJ_6!nHtg2Ndwf&vpH7v>%kvjH|n0@qGrq#TxMsi1JiVmxVM&SWL;Ee zOQ<{hZzmL|8_IzO7nF`H(jr-w z$&H;)y|G(8`3Of~&-szaWRmHthZl_<7KaweX<;2g=nZI11s&b^ppSvIE^m2!FEe_C zs3~^5yRG+0rDMhc^vDL97c=MuxU+wFum}!jRA+*|=+%4`vQ#s_hAv@ADk;exrz-GW z3L4mxXXnB&*LR)0%S zQ5^Aqmh+Fb-};cib+-Gg&)&A3;1bgL=OT`Cz4}HswZ<+s zPSw_A6s|p3?p-&kZOkF?Y3B%b0c~{FJo_wu_+!oBn&c|g+6U=5>3}*!6a@YRyZDC? z(Q#i!sThLZ0BJRh0PO>px3B|vorpWT)Ky)_sC%L>#b+_*QN+I@6b&$T7gVd-@x)y4 zRA<&60v3)6SB2McS;l%sawYfPdr7eSc25+hA%=EiAyhfbywR*6;MAJwC)zvi^FKOkFSd>_*)jaGl z)bu4|jjLd5UAQ(PW|DRGjmvTpHS&h4Yc|q@Egx}ue+Pxy8T|cM_8j=MZD&-6vJQP(5w*g^&u73Tr01 zN+nj0p^T9vwk=9hiBZg=<4{@7_=?VAYO8LkLT-zW$;{cdiG~S@c2FgmP@p$jQ$HZw zL3=A%D&sC`)1L{$bSSi-qx0eDgPLx6l2^v8df+<{!%w>Q%_AEyIwK=ZfkTkxsSRc~ zSM{1yYTidO`Xj?0lVmQ#>K`QI0^c=DvF)Pa`-lm+SOj~KHsUDntacE_2<1sF?x;kO=sLnOu>a*g4Tv~)!TA*Sd8&y7* z_s3+4wW_R<6|dm3oIlVuc0-oj#-fwLq~hqndt`i@)})bA*Nd+%-TP>xQ$aH-45_2U zXt>T)p0wLl3X(Jz1xh|YX0x8vM-nh8)z=b?yMTV{QYewV{01jl6T@k1U@Bi2b!H$;TT5;%F04TvnR-qbq2$JBvWUwT4F90 zLgFr?e8SQmD-afw!%Z{ti7GQONb({q$l6^<;t8p#hhA3KyuGU)Z|1{u-v)ER|JubT0i)SibdU2eIfT5_CE~27yojA5yo}tPAX197Gz4NfPgs z=&cZ>gni!N{kNSte;2 z^?Y~1w`VK57u7pysqe0TpEMGx=FXe7GB~J_JqzmI5~j0~po2K+BXK(_=974{liMbF z>mh&J>gvub^$4!smg~Tjune{P^^~$?3>UaXUc}Z)(l%i4X%5sA{CW?pdoQ9N7GB;L zxw?}`Jw})Ek8$ElX2R`iUb`2LQGnhWp?leD-Wnx6Fz#hWKTw`$iao|(@Qd#0Mij^f z?fH=H+tQ>{%AVsaQ_h|sMhdmTfBSwhE1hiY#(45UUH^D7qyD!(=s$@e6;0Krlhgx3 z!w?dL86=V=tRNW@6p|)=&6_!(ZU|73Nd-`gbka#jJtkCBa?T!u1|%UXl8 zTO7@SQn3y@H%Y&6CbxX9Rzfnfs@RN6Xi&j3IX}iPXD_BcS;f&QK6`m7!m_s0Zk^!` zizj!sF?=_r8kNv!%weU4$A+VDpBalZHza{mcOL*HG7nq5)m9b6n$Jj2rGIjHn1Yp+ zr)$!L&VG=EL^*U+bGtY}zD$j-;_H+_Ps9j+K6VQ8$SU+DJ%cO7@Y?~BaX6>)Xvv}( zRwgDyNQ3e$0_+)K0?X1UaVgGCNcdQ zsu~ZF=6eEnkvAmSZ#9(|m6Ze<&WS)oNd0eSB6dO?lGfn7s9%FX7~)O3)UlLmQa zTxg#$uVZV&MNq=SJ&&n@btUWlFT-ktpcT^(mRssPcIceik8Tm0_P+JV;Eq{4s-6(qGr`KUfHazAcN8qgE!Ik1it0_gPvdP7nTV+M18=$>LjKwuS zz)EEw6DxP-Hr>Yn7g(%W(wWJgVp8e#0K zS$^MYh`nusz$!mg75{!1_S5nm2AGhftn}sysX|MG!d(v~WZ4wk%J|$v0gwpI0ZviW>pbtb-kh)1h!N75#hkP*^6@oG;J6lo< zJw8NTHF4Qkpcxu(RyfW`=Cne~UK2I1WII5%ZX$f^M*&k`1bDgP`dYKZ6W&*a_MDKg zOpjM?f9_bZ>tJ3Mpd;{!BEsPsi3>#i`q~|GxZgJtMP}p-)IW;Q!_E-&@+*(kMkYVR zi+aklkf8BbOk!>qu?G||5HI5x=#a%&5}s&k^Iq1zV|z^%bI~-9xj9LeCT^7-iQ*O# zN$c7NFr6T26NB8M6C7LuOBhAj&cnYT4Mg$NG~=m<`%G4q+-Kd1HorG2L6PUyFU=;= zf4cvko+=Lq(-Z`%ClpcQ{7izGA`$Nb#EGmY(pIqTk>#;@IZE8A8IBFSF! z&}6PgW*4l^F#SAsH!CF{o0V>aY#$QA-RV^~VN7BkkF%Sv>W!`D#3vQ;<8uF_zRf zZt_^ZFU2Ww?w0Z1wPL)acy}J=2#G0+V?RF#&l$iyp+sL_np{_Ea>KE;Vw(&urj&=Z;8{tY?{e+Qdy9oO-LpW@$0(A3;m_?+Z z{j(gjMZugNA7O5Rx53N30oMUMB+{=hK60ePb8rQ-tZzc^V6R!F^)!s*iQ0C#iF2f~ z;KGaa+R-m&tAe$h9fA0K&yD~ioG^tveM2Mz|EKE(-T#N}|6${K|B3EFS|(UQlEK99 z!Lw14?80YMtOcyHo})Wx8E{EDsSsAuP**ZEifv2j1MrLghWAF{65H~v5`JHwH4U9B zY!tniYGc}SJGwhh(@a~R=lH&nnVA8^5!^(4%P1ekCsnl_7E+S5eo7E!N$i(|gk*Tn zV!3Q8ttAY^4989V9&^@hsFL?Zh*?kYQ0yury`DfjJTSXR^*RY~zxx+Va2n`qwRT$M z%vD8#I`Bde1&|34rlFi3!{mm(GqtsB2eZtoQfdv2(W0Js;~gb-`Jp_T&NaerDaDTz z@YAnZQXrAF?Tu_)^skwZ1jr^f)CQywL+mtJ#LOP>V=ZZr zCr3*?VkUgBmZ;CqhYyHMjx0$rpZCxy>IwKNU0%C31NSD4gJv_VOJEl%aXf zkgAj#ICq)!-dpWmH=MU0CP}s0Q&AuoUg|@2@~DuN`l4(ctdVuY2@MtlrbaNHzB%bE ziCMa-)=5d!ZLo97kHOoIW_O+#e3?nNnY3?8e+u%S%M%)=Xo(=>SQ7$x_zc0ULSgpd zp%Gs4(><gfK1%dx(3vpRNoXZQNa`Z@z=>;sY6W;a<1H0`VCAx?fe4`$hY{*jj*HpC z-ucR?mlWQ{07HT}Pv4|wZU27g2JKShb#a=5lXgc(I<7&1@=H>D%D08qB_hE~r5_&; zg5&cFCb(~DPpHvI-FFSAWLHG_!LAa<#Pmj?#prNmi3A-aJVs^my!H5HxjC-DpAgf%TQeQ7d&KxcfS=``5z&Ctt%iNWe0ZtYRt3JY zYIxlyG)o84uMHMQc2f1h|F#1^gxl<;z^xN(1dHV@{4ldn+lHTQa~y)}881Z9K9A^~ zCc%3{%%`|Mf+91_a6N{wnVMSYv%10dc<-><3{XgeLT&Mn6{n%_o8`4rmr> zlws6$3~0wxt3lFX?f@G<{tI>u*S8L9ZM(<*Z(I;bZxc)o5;uGVEGOzDBRn;1;&fkT z^Tu4f7}CAi_N8?sjTIQZjr~^T8Khn(FY3z!*kSYB%%k3m)6FikXJ6YQ@EbIRKL0}J z9_I<2ZOuZU6L`=+C&jYB5a?XE`~DTZ#~Of=$65WNGFK0M^?P|!l?(8U_fu47`^TtG z{*!0>T^ZAl%x{G1odfDD`ooNd+pK|gNc)>mB8WsnLs)+|)@B7mIP{tT%g-|4x&0bC zT`AM$RT}zmM9=}Pu@_6#WVF&L`A&PNyHh3uq{(|ysmTw>_knHi_ek!KzL=B9ej9A~ zn&EKNu;NyJ5%qY#1q$R!mO z3PVvlR5tbo)kr8SNuQg*5E6?N^b)L}nx7GPWgxO>v=$V7J31*nSOy`u09_D6gd~hf z%9!sURe7PSeD^exEPauydN;KJciw7B*glnx@@t`PRV7d5?pY;I?GARdW^$rJ-6?6w zPhXgY6c?{BcqYH#+fOtaJUZTPR1|a!yvN16wVTs*@`B93G1wo2JK%nNJ>-Y!s2<2P5 zi;{v7Yj2=z0-H`mf3WYXju0l|*00aG4GIL?Mqezq3Z z7_DXc{8!>?%EJ#up_B;$K`nCytK2xP;m6`?bzm&S6DMBZUSWAFb|S5#)GAqb(+u|Q zsFCKmm| zvOct~E0urzL~(KAgt@tF4PU@J(uMUK$g%k~*|I@3ShKEqQg;RGBE}}W-#3gpv~Mz< z$EU$n=d9D&Yf<$i+4>R`oSZ{!_Gh=?{O&Gp^$Z)X2xN)$^iW#kh|toA6~lbZ&gW~? zv+CQ36)Pv~M$2@}pz^OBgiK{kcSi8j)6-R*b$GGLGMu&FeYmPPzJb$KT80&fYg>|N z4T!9cJLKKrXp!7%PJ`vQy-8D7mH(7a7Mq&ZFT;T$$*cu0*ATMjws#4=bcml5;!c}q zv=y!&|DjA~XL_%D5*CKWX7k*==cR!j)aW}lSrLMC`5MC#wfe0Q9gcpLYhJCRe%?$b zq%R`AfU6nc6Z5(*JIg5t&Q6m_z&@5MnoSWZ0^Nk}L`!k&7tSqWEz~01;2C!)sMlW0 zC+oLl%$j|48Ity-Q|XOtPOb z!i}}_?LFkJtwU)@&ZsT6xl(gHjRiy$tQE}_nri8I#>%Qn&BO(b_P}UrYnDZ|TolgZ z(5b1qIQ{kmhA^k2@?Y%U)@c-vtv9-492-gZuwsRFcX@Qg-FMzYvl+G^>b5MaArx5R zrQR^-N4?krJbYOV_T^R{^7dIeuGl|S=jo2R13umB5y(KCPD4ER%-#ORaxA{iE#w}b z7NJE}-f?&yeRSJ~0`YAJ>|^o;7KCK+A(`?G0nQQ4#3H~Qk3u5Fr61nD1&L!(W(#py zPM{$^6ZA_ZJfDz*9=`VbbSN_|bKB{SIp5`vjzU{$$tHikm4S1nO{*8^3A()lV+B$A;V7`jF zE^%YPnF~0dr7OPNn95}`##=&$f%^3}S$|TLqIbe7W_>(OqhrR(lhpK}i_Kmk~h&due9mi>I1=Wpy)-U;masI zIXWxC@Ut*f2-k};Kra$`sSfgya#;RIVFR280Z}&VOCgCA&QL_`OKqlTBIS1Of;M1L2R`!S9P?VSmI>1AY5{ zsFTI`YeQv6b1R2Gt_w~IlCr4sPZhE0&byAT%3*JKz=TaCB;~=jh=@r^r6tsr7#oS| zj0^pZA$Ign3O?B9+04}!t$(V&!mMXM6~#gu#ShB`zvDRWbs1?`dGLGyS!Gi}tJZ(z z8`fc>h3P34tq)F8Pt;dP$Zm+`kKrGgOSr+L0HYC;z(_>WiKNazJE>^|Wqu3cUu|HE z4QI_c$#nK$Gj2z4Y7j_MR^C=;%AJw=QBn)5r+N{=r<=LeRE4Ra=O!HE9$QGVV z#b%H|Q`G{SbY|w6u4e1@`ZQEVCrq^4c4tzY%|9RHv6A#i zX2PC8)6PQi&skdDi(sV;`xG{f*v&`_DR1p84&&bGoE#K}7=cUNYt@irz5hB7aSH7l zYKa^XHzS*76J&QrG6#u*RgM$^2Edko9jvkIA_0#|Pf=nP7Q9SEgAemM?ZFlq0a}Es zPSPlGH0mPD=ehJ^o;2{B`5~ zTonJz%lIKaKlS=ct^0pp%JRyDE)O;{kZ%7s_*Bb1k%6g6MXVm|DELj z-A8|~@#jyBul}MD82fh`f7vAohB>0l`*3I4S0fq*cd{*s<50MovExBmxG CGa1AH diff --git a/jdk/test/java/util/PluggableLocale/providersrc/DateFormatProviderImpl.java b/jdk/test/java/util/PluggableLocale/providersrc/DateFormatProviderImpl.java index 25e7b176946..55bc8d5ae73 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/DateFormatProviderImpl.java +++ b/jdk/test/java/util/PluggableLocale/providersrc/DateFormatProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ public class DateFormatProviderImpl extends DateFormatProvider { static String[] datePattern = { "yyyy'\u5e74'M'\u6708'd'\u65e5'", // full date pattern - "yyyy/MM/dd", // long date pattern + "yyyy/MMM/dd", // long date pattern "yyyy/MM/dd", // medium date pattern "yy/MM/dd" // short date pattern }; @@ -68,7 +68,7 @@ public class DateFormatProviderImpl extends DateFormatProvider { public DateFormat getDateInstance(int style, Locale locale) { for (int i = 0; i < avail.length; i ++) { if (Utils.supportsLocale(avail[i], locale)) { - return new SimpleDateFormat(datePattern[style]+dialect[i], locale); + return new FooDateFormat(datePattern[style]+dialect[i], locale); } } throw new IllegalArgumentException("locale is not supported: "+locale); @@ -77,7 +77,7 @@ public class DateFormatProviderImpl extends DateFormatProvider { public DateFormat getTimeInstance(int style, Locale locale) { for (int i = 0; i < avail.length; i ++) { if (Utils.supportsLocale(avail[i], locale)) { - return new SimpleDateFormat(timePattern[style]+dialect[i], locale); + return new FooDateFormat(timePattern[style]+dialect[i], locale); } } throw new IllegalArgumentException("locale is not supported: "+locale); @@ -86,7 +86,7 @@ public class DateFormatProviderImpl extends DateFormatProvider { public DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) { for (int i = 0; i < avail.length; i ++) { if (Utils.supportsLocale(avail[i], locale)) { - return new SimpleDateFormat( + return new FooDateFormat( datePattern[dateStyle]+" "+timePattern[timeStyle]+dialect[i], locale); } } diff --git a/jdk/test/java/util/PluggableLocale/providersrc/FooDateFormat.java b/jdk/test/java/util/PluggableLocale/providersrc/FooDateFormat.java new file mode 100644 index 00000000000..80d4ce2010f --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/providersrc/FooDateFormat.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.foo; + +import java.text.*; +import java.util.*; + +/** + * FooDateFormat provides SimpleDateFormat methods required for the SPI testing. + */ +public class FooDateFormat extends DateFormat { + private SimpleDateFormat sdf; + + public FooDateFormat(String pattern, Locale loc) { + sdf = new SimpleDateFormat(pattern, loc); + } + + @Override + public StringBuffer format(Date date, + StringBuffer toAppendTo, + FieldPosition fieldPosition) { + return sdf.format(date, toAppendTo, fieldPosition); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return sdf.parse(source, pos); + } + + @Override + public boolean equals(Object other) { + return other instanceof FooDateFormat + && sdf.equals(((FooDateFormat)other).sdf); + } + + @Override + public int hashCode() { + return sdf.hashCode(); + } +} diff --git a/jdk/test/java/util/PluggableLocale/providersrc/FooNumberFormat.java b/jdk/test/java/util/PluggableLocale/providersrc/FooNumberFormat.java new file mode 100644 index 00000000000..d13bd7362fe --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/providersrc/FooNumberFormat.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.foo; + +import java.text.*; + +/** + * FooNumberFormat provides DecimalFormat methods required for the SPI testing. + */ +public class FooNumberFormat extends NumberFormat { + private DecimalFormat df; + + public FooNumberFormat(String pattern, DecimalFormatSymbols dfs) { + df = new DecimalFormat(pattern, dfs); + } + + @Override + public StringBuffer format(double number, + StringBuffer toAppendTo, + FieldPosition pos) { + return df.format(number, toAppendTo, pos); + } + + @Override + public StringBuffer format(long number, + StringBuffer toAppendTo, + FieldPosition pos) { + return df.format(number, toAppendTo, pos); + } + + @Override + public Number parse(String source, ParsePosition parsePosition) { + return df.parse(source, parsePosition); + } + + @Override + public boolean equals(Object other) { + return other instanceof FooNumberFormat + && df.equals(((FooNumberFormat)other).df); + } + + @Override + public int hashCode() { + return df.hashCode(); + } + + // DecimalFormat specific methods required for testing + + public String toPattern() { + return df.toPattern(); + } + + public DecimalFormatSymbols getDecimalFormatSymbols() { + return df.getDecimalFormatSymbols(); + } + + public void setDecimalSeparatorAlwaysShown(boolean newValue) { + df.setDecimalSeparatorAlwaysShown(newValue); + } +} diff --git a/jdk/test/java/util/PluggableLocale/providersrc/Makefile b/jdk/test/java/util/PluggableLocale/providersrc/Makefile index a85ea065e98..8d2fa9cab80 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/Makefile +++ b/jdk/test/java/util/PluggableLocale/providersrc/Makefile @@ -28,6 +28,8 @@ FOOFILES_JAVA = \ DateFormatSymbolsProviderImpl.java \ DecimalFormatSymbolsProviderImpl.java \ NumberFormatProviderImpl.java \ + FooDateFormat.java \ + FooNumberFormat.java \ Utils.java BARFILES_JAVA = \ diff --git a/jdk/test/java/util/PluggableLocale/providersrc/NumberFormatProviderImpl.java b/jdk/test/java/util/PluggableLocale/providersrc/NumberFormatProviderImpl.java index 164de5e1db6..9aa677cf89b 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/NumberFormatProviderImpl.java +++ b/jdk/test/java/util/PluggableLocale/providersrc/NumberFormatProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,13 +49,15 @@ public class NumberFormatProviderImpl extends NumberFormatProvider { static String[] patterns = { "#,##0.###{0};-#,##0.###{1}", // decimal pattern + "#{0};(#){1}", // integer pattern "\u00A4#,##0{0};-\u00A4#,##0{1}", // currency pattern "#,##0%{0}" // percent pattern }; // Constants used by factory methods to specify a style of format. static final int NUMBERSTYLE = 0; - static final int CURRENCYSTYLE = 1; - static final int PERCENTSTYLE = 2; + static final int INTEGERSTYLE = 1; + static final int CURRENCYSTYLE = 2; + static final int PERCENTSTYLE = 3; public Locale[] getAvailableLocales() { return avail; @@ -68,10 +70,10 @@ public class NumberFormatProviderImpl extends NumberFormatProvider { MessageFormat.format(patterns[CURRENCYSTYLE], dialect[i], dialect[i]); - DecimalFormat df = new DecimalFormat(pattern, + FooNumberFormat nf = new FooNumberFormat(pattern, DecimalFormatSymbols.getInstance(locale)); - adjustForCurrencyDefaultFractionDigits(df); - return df; + adjustForCurrencyDefaultFractionDigits(nf); + return nf; } } throw new IllegalArgumentException("locale is not supported: "+locale); @@ -81,15 +83,15 @@ public class NumberFormatProviderImpl extends NumberFormatProvider { for (int i = 0; i < avail.length; i ++) { if (Utils.supportsLocale(avail[i], locale)) { String pattern = - MessageFormat.format(patterns[NUMBERSTYLE], + MessageFormat.format(patterns[INTEGERSTYLE], dialect[i], dialect[i]); - DecimalFormat df = new DecimalFormat(pattern, + FooNumberFormat nf = new FooNumberFormat(pattern, DecimalFormatSymbols.getInstance(locale)); - df.setMaximumFractionDigits(0); - df.setDecimalSeparatorAlwaysShown(false); - df.setParseIntegerOnly(true); - return df; + nf.setMaximumFractionDigits(0); + nf.setDecimalSeparatorAlwaysShown(false); + nf.setParseIntegerOnly(true); + return nf; } } throw new IllegalArgumentException("locale is not supported: "+locale); @@ -102,7 +104,7 @@ public class NumberFormatProviderImpl extends NumberFormatProvider { MessageFormat.format(patterns[NUMBERSTYLE], dialect[i], dialect[i]); - return new DecimalFormat(pattern, + return new FooNumberFormat(pattern, DecimalFormatSymbols.getInstance(locale)); } } @@ -115,7 +117,7 @@ public class NumberFormatProviderImpl extends NumberFormatProvider { String pattern = MessageFormat.format(patterns[PERCENTSTYLE], dialect[i]); - return new DecimalFormat(pattern, + return new FooNumberFormat(pattern, DecimalFormatSymbols.getInstance(locale)); } } @@ -126,8 +128,8 @@ public class NumberFormatProviderImpl extends NumberFormatProvider { * Adjusts the minimum and maximum fraction digits to values that * are reasonable for the currency's default fraction digits. */ - void adjustForCurrencyDefaultFractionDigits(DecimalFormat df) { - DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); + void adjustForCurrencyDefaultFractionDigits(FooNumberFormat nf) { + DecimalFormatSymbols dfs = nf.getDecimalFormatSymbols(); Currency currency = dfs.getCurrency(); if (currency == null) { try { @@ -138,15 +140,15 @@ public class NumberFormatProviderImpl extends NumberFormatProvider { if (currency != null) { int digits = currency.getDefaultFractionDigits(); if (digits != -1) { - int oldMinDigits = df.getMinimumFractionDigits(); + int oldMinDigits = nf.getMinimumFractionDigits(); // Common patterns are "#.##", "#.00", "#". // Try to adjust all of them in a reasonable way. - if (oldMinDigits == df.getMaximumFractionDigits()) { - df.setMinimumFractionDigits(digits); - df.setMaximumFractionDigits(digits); + if (oldMinDigits == nf.getMaximumFractionDigits()) { + nf.setMinimumFractionDigits(digits); + nf.setMaximumFractionDigits(digits); } else { - df.setMinimumFractionDigits(Math.min(digits, oldMinDigits)); - df.setMaximumFractionDigits(digits); + nf.setMinimumFractionDigits(Math.min(digits, oldMinDigits)); + nf.setMaximumFractionDigits(digits); } } } From 96734e403eed893debdbe96885b11cf048057b30 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Mon, 27 Dec 2010 15:28:08 +0300 Subject: [PATCH 52/94] 6959584: closed/javax/swing/JFileChooser/4847375/bug4847375.java : compilation failed Reviewed-by: alexp --- .../JFileChooser/4847375/bug4847375.java | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 jdk/test/javax/swing/JFileChooser/4847375/bug4847375.java diff --git a/jdk/test/javax/swing/JFileChooser/4847375/bug4847375.java b/jdk/test/javax/swing/JFileChooser/4847375/bug4847375.java new file mode 100644 index 00000000000..8a9af80b672 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/4847375/bug4847375.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4847375 + * @summary JFileChooser Create New Folder button is disabled incorrectly + * @author Pavel Porvatov + */ + +import sun.awt.OSInfo; +import sun.awt.shell.ShellFolder; + +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.Method; + +public class bug4847375 { + private final String newFolderToolTipText; + + private final String lookAndFeel; + + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) { + System.out.println("The test is suitable only for Windows OS. Skipped."); + + return; + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new bug4847375("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + + new bug4847375("javax.swing.plaf.metal.MetalLookAndFeel"); + } + }); + } + + private static Object[][] DIRECTORIES = new Object[][]{ + {"getDesktop", Boolean.TRUE}, + {"getDrives", Boolean.FALSE}, // My computer + {"getRecent", Boolean.TRUE}, + {"getNetwork", Boolean.FALSE}, + {"getPersonal", Boolean.TRUE}, + }; + + private bug4847375(String lookAndFeel) { + this.lookAndFeel = lookAndFeel; + + try { + UIManager.setLookAndFeel(lookAndFeel); + } catch (Exception e) { + fail("Cannot set LookAndFeel", e); + } + + JFileChooser fileChooser = new JFileChooser(); + + // Find button NewFolder + newFolderToolTipText = UIManager.getString("FileChooser.newFolderToolTipText", fileChooser.getLocale()); + + if (newFolderToolTipText == null || newFolderToolTipText.length() == 0) { + fail("Cannot find NewFolderButton in FileChooser (tooltip doesn't exist)"); + + return; + } + + JButton newFolderButton = findNewFolderButton(fileChooser); + + if (newFolderButton == null) { + fail("Cannot find NewFolderButton in FileChooser"); + + return; + } + + for (Object[] objects : DIRECTORIES) { + String getterName = (String) objects[0]; + Boolean enabledNewFolder = (Boolean) objects[1]; + + fileChooser.setCurrentDirectory(getWin32Folder(getterName)); + + if (newFolderButton.isEnabled() != enabledNewFolder) { + fail("Enabled state of NewFolderButton should be " + enabledNewFolder + + " for Win32ShellFolderManager2." + getterName + "()"); + } + } + } + + private JButton findNewFolderButton(Container container) { + JButton result = null; + + for (int i = 0; i < container.getComponentCount(); i++) { + Component c = container.getComponent(i); + + if (c instanceof JButton && newFolderToolTipText.equals(((JButton) c).getToolTipText())) { + if (result != null) { + fail("Two or more NewFolderButton found in FileChooser"); + } + + result = (JButton) c; + } + + if (c instanceof Container) { + JButton button = findNewFolderButton((Container) c); + + if (result == null) { + result = button; + } else { + if (button != null) { + fail("Two or more NewFolderButton found in FileChooser"); + } + } + } + } + + return result; + } + + private ShellFolder getWin32Folder(String getterName) { + try { + Class win32ShellFolderManager2 = Class.forName("sun.awt.shell.Win32ShellFolderManager2"); + + Method method = win32ShellFolderManager2.getDeclaredMethod(getterName); + method.setAccessible(true); + + return (ShellFolder) method.invoke(null); + } catch (Exception e) { + fail("Cannot call '" + getterName + "' in the Win32ShellFolderManager2 class", e); + + return null; + } + } + + private void fail(String s) { + throw new RuntimeException("Test failed: " + s); + } + + private void fail(String s, Throwable e) { + throw new RuntimeException("Test failed for LookAndFeel " + lookAndFeel + ": " + s, e); + } +} From ab1c0a938ea96fbcb50143a8c3e91d067302214b Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Mon, 27 Dec 2010 09:30:20 -0500 Subject: [PATCH 53/94] 6975480: VS2010 says _STATIC_CPPLIB is deprecated, may need to change this usage Disabled the warning message during compiling. Reviewed-by: coleenp, dholmes --- hotspot/make/windows/makefiles/compile.make | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/windows/makefiles/compile.make b/hotspot/make/windows/makefiles/compile.make index 7d7cb8642c3..a4cfd742e9b 100644 --- a/hotspot/make/windows/makefiles/compile.make +++ b/hotspot/make/windows/makefiles/compile.make @@ -138,7 +138,7 @@ MS_RUNTIME_OPTION = /MTd /D "_DEBUG" !endif # Always add the _STATIC_CPPLIB flag -STATIC_CPPLIB_OPTION = /D _STATIC_CPPLIB +STATIC_CPPLIB_OPTION = /D _STATIC_CPPLIB /D _DISABLE_DEPRECATE_STATIC_CPPLIB MS_RUNTIME_OPTION = $(MS_RUNTIME_OPTION) $(STATIC_CPPLIB_OPTION) CPP_FLAGS=$(CPP_FLAGS) $(MS_RUNTIME_OPTION) From 8d3bfc152b7fca458df12be620a29c3df580d2b2 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Mon, 27 Dec 2010 17:41:33 +0300 Subject: [PATCH 54/94] 6532833: PIT: Metal LAF - The right side border is not shown for the Spinner after the removing the buttons Reviewed-by: alexp --- .../swing/plaf/basic/BasicSpinnerUI.java | 8 ++ .../swing/JSpinner/6532833/bug6532833.java | 80 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 jdk/test/javax/swing/JSpinner/6532833/bug6532833.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java index b26f226c043..a57638e39eb 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -908,6 +908,14 @@ public class BasicSpinnerUI extends SpinnerUI int height = parent.getHeight(); Insets insets = parent.getInsets(); + + if (nextButton == null && previousButton == null) { + setBounds(editor, insets.left, insets.top, width - insets.left - insets.right, + height - insets.top - insets.bottom); + + return; + } + Dimension nextD = preferredSize(nextButton); Dimension previousD = preferredSize(previousButton); int buttonsWidth = Math.max(nextD.width, previousD.width); diff --git a/jdk/test/javax/swing/JSpinner/6532833/bug6532833.java b/jdk/test/javax/swing/JSpinner/6532833/bug6532833.java new file mode 100644 index 00000000000..184fe69d96d --- /dev/null +++ b/jdk/test/javax/swing/JSpinner/6532833/bug6532833.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6532833 + @summary PIT: Metal LAF - The right side border is not shown for the Spinner after the removing the buttons + @author Pavel Porvatov +*/ + +import javax.swing.*; +import java.awt.*; + +public class bug6532833 { + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + JSpinner[] spinners = new JSpinner[2]; + + for (int i = 0; i < spinners.length; i++) { + JSpinner spinner = new JSpinner(); + + spinner.setValue(2010); + + Component arrowUp = spinner.getComponent(0); + Component arrowDown = spinner.getComponent(1); + + LayoutManager layout = spinner.getLayout(); + + layout.removeLayoutComponent(arrowUp); + layout.removeLayoutComponent(arrowDown); + + if (i == 1) { + spinner.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + } + + spinners[i] = spinner; + } + + // Do layout of spinners components + JFrame frame = new JFrame(); + + for (JSpinner spinner : spinners) { + frame.getContentPane().add(spinner); + } + + frame.pack(); + + for (JSpinner spinner : spinners) { + Insets insets = spinner.getInsets(); + + if (spinner.getWidth() != insets.left + insets.right + spinner.getEditor().getWidth()) { + throw new RuntimeException("Spinner editor width is invalid"); + } + } + + frame.dispose(); + } + }); + } +} From b719528ce0d5f2f129fcbf2b1f5a2958d51ca3d4 Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Mon, 27 Dec 2010 18:37:06 +0300 Subject: [PATCH 55/94] 4887645: Remove "awt.threadgroup" system property Reviewed-by: art, anthony --- jdk/src/share/classes/sun/awt/SunToolkit.java | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 07b231951c4..46963541545 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -102,26 +102,6 @@ public abstract class SunToolkit extends Toolkit public final static int MAX_BUTTONS_SUPPORTED = 20; public SunToolkit() { - /* If awt.threadgroup is set to class name the instance of - * this class is created (should be subclass of ThreadGroup) - * and EventDispatchThread is created inside of it - * - * If loaded class overrides uncaughtException instance - * handles all uncaught exception on EventDispatchThread - */ - ThreadGroup threadGroup = null; - String tgName = System.getProperty("awt.threadgroup", ""); - - if (tgName.length() != 0) { - try { - Constructor ctor = Class.forName(tgName). - getConstructor(new Class[] {String.class}); - threadGroup = (ThreadGroup)ctor.newInstance(new Object[] {"AWT-ThreadGroup"}); - } catch (Exception e) { - System.err.println("Failed loading " + tgName + ": " + e); - } - } - Runnable initEQ = new Runnable() { public void run () { EventQueue eventQueue; @@ -144,17 +124,7 @@ public abstract class SunToolkit extends Toolkit } }; - if (threadGroup != null) { - Thread eqInitThread = new Thread(threadGroup, initEQ, "EventQueue-Init"); - eqInitThread.start(); - try { - eqInitThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } else { - initEQ.run(); - } + initEQ.run(); } public boolean useBufferPerWindow() { From 86b6ed4a42e67cd3fbe81567ea2c5f1d373911ee Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Mon, 27 Dec 2010 18:42:28 +0300 Subject: [PATCH 56/94] 6957765: Test Bug - javax/swing/SwingWorker/6480289/bug6480289.java failed on 1.7.0b94 but passed on previous Reviewed-by: art, alexp --- .../swing/SwingWorker/6480289/bug6480289.java | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 jdk/test/javax/swing/SwingWorker/6480289/bug6480289.java diff --git a/jdk/test/javax/swing/SwingWorker/6480289/bug6480289.java b/jdk/test/javax/swing/SwingWorker/6480289/bug6480289.java deleted file mode 100644 index 9ff34969a31..00000000000 --- a/jdk/test/javax/swing/SwingWorker/6480289/bug6480289.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * - * @bug 6480289 - * @author Igor Kushnirskiy - * @summary tests if consequent workers are executed on the same thread and that VM can exit. - */ - -import java.util.*; -import javax.swing.SwingWorker; - -public class bug6480289 { - private static final int ITERATIONS = 5; - private static final Map threadMap = - Collections.synchronizedMap(new HashMap()); - public static void main(String[] args) throws Exception { - - for (int i = 0; i < ITERATIONS; i++) { - if (i != 0) { - Thread.sleep(1000 * 5); - } - SwingWorker worker = - new SwingWorker() { - @Override - protected Void doInBackground() { - Integer value = threadMap.get(Thread.currentThread()); - value = Integer.valueOf( - ((value == null) ? 0 : value.intValue()) - + 1); - threadMap.put(Thread.currentThread(), value); - return null; - } - }; - worker.execute(); - } - if (threadMap.keySet().size() != 1) { - throw new RuntimeException("failed. More than one thread."); - } - } -} From a4142667f3d7238882c997c8401fccd86390575e Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Mon, 27 Dec 2010 18:43:55 +0300 Subject: [PATCH 57/94] 6866808: nsk/stress/jck12a/jck12a014 crashes with SIGSEGV at [libjvm.so+0xc5b10] Reviewed-by: art --- jdk/src/solaris/native/sun/xawt/XToolkit.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jdk/src/solaris/native/sun/xawt/XToolkit.c b/jdk/src/solaris/native/sun/xawt/XToolkit.c index 72024178041..4ea63143c70 100644 --- a/jdk/src/solaris/native/sun/xawt/XToolkit.c +++ b/jdk/src/solaris/native/sun/xawt/XToolkit.c @@ -187,7 +187,9 @@ Java_java_awt_Component_initIDs "()Ljava/awt/Point;"); keyclass = (*env)->FindClass(env, "java/awt/event/KeyEvent"); - DASSERT (keyclass != NULL); + if (JNU_IsNull(env, keyclass)) { + return; + } componentIDs.isProxyActive = (*env)->GetFieldID(env, keyclass, "isProxyActive", @@ -715,8 +717,10 @@ Window get_xawt_root_shell(JNIEnv *env) { if (xawt_root_shell == None){ if (classXRootWindow == NULL){ jclass cls_tmp = (*env)->FindClass(env, "sun/awt/X11/XRootWindow"); - classXRootWindow = (jclass)(*env)->NewGlobalRef(env, cls_tmp); - (*env)->DeleteLocalRef(env, cls_tmp); + if (!JNU_IsNull(env, cls_tmp)) { + classXRootWindow = (jclass)(*env)->NewGlobalRef(env, cls_tmp); + (*env)->DeleteLocalRef(env, cls_tmp); + } } if( classXRootWindow != NULL) { methodGetXRootWindow = (*env)->GetStaticMethodID(env, classXRootWindow, "getXRootWindow", "()J"); From 00c8b5c7a07ce3dc268c086856905235d21d1257 Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Mon, 27 Dec 2010 18:45:39 +0300 Subject: [PATCH 58/94] 6921598: PrinterDialog hidden behind other frames Reviewed-by: art --- .../windows/native/sun/windows/awt_Dialog.cpp | 64 +++++++++---------- .../windows/native/sun/windows/awt_Dialog.h | 4 +- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/jdk/src/windows/native/sun/windows/awt_Dialog.cpp b/jdk/src/windows/native/sun/windows/awt_Dialog.cpp index 628797f8af9..d42a0d0f2c2 100644 --- a/jdk/src/windows/native/sun/windows/awt_Dialog.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Dialog.cpp @@ -230,7 +230,7 @@ LRESULT CALLBACK AwtDialog::ModalFilterProc(int code, if (::IsIconic(hWnd)) { ::ShowWindow(hWnd, SW_RESTORE); } - PopupAllDialogs(blocker, TRUE, ::GetForegroundWindow(), FALSE); + PopupBlockers(blocker, TRUE, ::GetForegroundWindow(), FALSE); // return 1 to prevent the system from allowing the operation return 1; } @@ -256,7 +256,7 @@ LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode, HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd)); if (::IsWindow(blocker)) { BOOL onTaskbar = !(::WindowFromPoint(mhs->pt) == hWnd); - PopupAllDialogs(hWnd, FALSE, ::GetForegroundWindow(), onTaskbar); + PopupBlockers(blocker, FALSE, ::GetForegroundWindow(), onTaskbar); // return a nonzero value to prevent the system from passing // the message to the target window procedure return 1; @@ -268,60 +268,60 @@ LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode, } /* - * The function goes through the heirarchy of the blocker dialogs and - * popups all the dialogs. Note that the function starts from the top - * blocker dialog and goes down to the dialog which is the bottom dialog. - * Using another traversal may cause to the flickering issue as a bottom - * dialog will cover a top dialog for some period of time. + * The function goes through the hierarchy of the blockers and + * popups all the blockers. Note that the function starts from the top + * blocker and goes down to the blocker which is the bottom one. + * Using another traversal algorithm (bottom->top) may cause to flickering + * as the bottom blocker will cover the top blocker for a while. */ -void AwtDialog::PopupAllDialogs(HWND dialog, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar) +void AwtDialog::PopupBlockers(HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar) { - HWND blocker = AwtWindow::GetModalBlocker(dialog); - BOOL isBlocked = ::IsWindow(blocker); - if (isBlocked) { - PopupAllDialogs(blocker, isModalHook, prevFGWindow, onTaskbar); + HWND nextBlocker = AwtWindow::GetModalBlocker(blocker); + BOOL nextBlockerExists = ::IsWindow(nextBlocker); + if (nextBlockerExists) { + PopupBlockers(nextBlocker, isModalHook, prevFGWindow, onTaskbar); } - PopupOneDialog(dialog, blocker, isModalHook, prevFGWindow, onTaskbar); + PopupBlocker(blocker, nextBlocker, isModalHook, prevFGWindow, onTaskbar); } /* - * The function popups the dialog, it distinguishes non-blocked dialogs - * and activates the dialogs (sets as foreground window). If the dialog is - * blocked, then it changes the Z-order of the dialog. + * The function popups the blocker, for a non-blocked blocker we need + * to activate the blocker but if a blocker is blocked, then we need + * to change z-order of the blocker placing the blocker under the next blocker. */ -void AwtDialog::PopupOneDialog(HWND dialog, HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar) +void AwtDialog::PopupBlocker(HWND blocker, HWND nextBlocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar) { - if (dialog == AwtToolkit::GetInstance().GetHWnd()) { + if (blocker == AwtToolkit::GetInstance().GetHWnd()) { return; } // fix for 6494032 - if (isModalHook && !::IsWindowVisible(dialog)) { - ::ShowWindow(dialog, SW_SHOWNA); + if (isModalHook && !::IsWindowVisible(blocker)) { + ::ShowWindow(blocker, SW_SHOWNA); } - BOOL isBlocked = ::IsWindow(blocker); + BOOL nextBlockerExists = ::IsWindow(nextBlocker); UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; - if (isBlocked) { + if (nextBlockerExists) { // Fix for 6829546: if blocker is a top-most window, but window isn't, then // calling ::SetWindowPos(dialog, blocker, ...) makes window top-most as well - BOOL isBlockerTopmost = (::GetWindowLong(blocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; - BOOL isDialogTopmost = (::GetWindowLong(dialog, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; - if (!isBlockerTopmost || isDialogTopmost) { - ::SetWindowPos(dialog, blocker, 0, 0, 0, 0, flags); + BOOL topmostNextBlocker = (::GetWindowLong(nextBlocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; + BOOL topmostBlocker = (::GetWindowLong(blocker, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; + if (!topmostNextBlocker || topmostBlocker) { + ::SetWindowPos(blocker, nextBlocker, 0, 0, 0, 0, flags); } else { - ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags); + ::SetWindowPos(blocker, HWND_TOP, 0, 0, 0, 0, flags); } } else { - ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags); + ::SetWindowPos(blocker, HWND_TOP, 0, 0, 0, 0, flags); // no beep/flash if the mouse was clicked in the taskbar menu // or the dialog is currently inactive - if (!isModalHook && !onTaskbar && (dialog == prevFGWindow)) { - AnimateModalBlocker(dialog); + if (!isModalHook && !onTaskbar && (blocker == prevFGWindow)) { + AnimateModalBlocker(blocker); } - ::BringWindowToTop(dialog); - ::SetForegroundWindow(dialog); + ::BringWindowToTop(blocker); + ::SetForegroundWindow(blocker); } } diff --git a/jdk/src/windows/native/sun/windows/awt_Dialog.h b/jdk/src/windows/native/sun/windows/awt_Dialog.h index 5aa99dfcec3..15918a6fd88 100644 --- a/jdk/src/windows/native/sun/windows/awt_Dialog.h +++ b/jdk/src/windows/native/sun/windows/awt_Dialog.h @@ -113,8 +113,8 @@ private: */ static void ModalPerformActivation(HWND hWnd); - static void PopupAllDialogs(HWND dialog, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar); - static void PopupOneDialog(HWND dialog, HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar); + static void PopupBlockers(HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar); + static void PopupBlocker(HWND blocker, HWND nextBlocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar); public: From 43280aa63e8abe5cb7c8a7b6aafa5b13e51b2428 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Mon, 27 Dec 2010 21:51:31 -0800 Subject: [PATCH 59/94] 7009231: C1: Incorrect CAS code for longs on SPARC 32bit Fix CAS of longs on SPARC 32bit and cmove on SPARC 64bit. Reviewed-by: kvn --- .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 23 ++-- .../cpu/sparc/vm/c1_LIRGenerator_sparc.cpp | 6 +- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 2 +- .../src/cpu/x86/vm/c1_LIRGenerator_x86.cpp | 5 +- hotspot/src/share/vm/c1/c1_LIR.hpp | 9 +- hotspot/src/share/vm/c1/c1_LIRAssembler.cpp | 2 +- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 2 +- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 4 +- .../test/compiler/7009231/Test7009231.java | 100 ++++++++++++++++++ 9 files changed, 133 insertions(+), 20 deletions(-) create mode 100644 hotspot/test/compiler/7009231/Test7009231.java diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 1e02e0a68fd..15ca82f28fe 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -1705,8 +1705,7 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op } -void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { - +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { Assembler::Condition acond; switch (condition) { case lir_cond_equal: acond = Assembler::equal; break; @@ -1737,7 +1736,12 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L ShouldNotReachHere(); } Label skip; - __ br(acond, false, Assembler::pt, skip); +#ifdef _LP64 + if (type == T_INT) { + __ br(acond, false, Assembler::pt, skip); + } else +#endif + __ brx(acond, false, Assembler::pt, skip); // checks icc on 32bit and xcc on 64bit if (opr1->is_constant() && opr1->type() == T_INT) { Register dest = result->as_register(); if (Assembler::is_simm13(opr1->as_jint())) { @@ -2688,6 +2692,11 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { #ifdef _LP64 __ mov(cmp_value_lo, t1); __ mov(new_value_lo, t2); + // perform the compare and swap operation + __ casx(addr, t1, t2); + // generate condition code - if the swap succeeded, t2 ("new value" reg) was + // overwritten with the original value in "addr" and will be equal to t1. + __ cmp(t1, t2); #else // move high and low halves of long values into single registers __ sllx(cmp_value_hi, 32, t1); // shift high half into temp reg @@ -2696,13 +2705,15 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { __ sllx(new_value_hi, 32, t2); __ srl(new_value_lo, 0, new_value_lo); __ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap -#endif // perform the compare and swap operation __ casx(addr, t1, t2); // generate condition code - if the swap succeeded, t2 ("new value" reg) was // overwritten with the original value in "addr" and will be equal to t1. - __ cmp(t1, t2); - + // Produce icc flag for 32bit. + __ sub(t1, t2, t2); + __ srlx(t2, 32, t1); + __ orcc(t2, t1, G0); +#endif } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { Register addr = op->addr()->as_pointer_register(); Register cmp_value = op->cmp_value()->as_register(); diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 1abbdb51d49..8869de5e8bd 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -662,7 +662,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) { // generate conditional move of boolean result LIR_Opr result = rlock_result(x); - __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); + __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG); } @@ -699,10 +699,10 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { else { ShouldNotReachHere(); } - // generate conditional move of boolean result LIR_Opr result = rlock_result(x); - __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); + __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), + result, as_BasicType(type)); if (type == objectType) { // Write-barrier needed for Object fields. // Precise card mark since could either be object or array post_barrier(addr, val.result()); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 724d8411bb5..f3ba0a2ce02 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -2036,7 +2036,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { } } -void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { +void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { Assembler::Condition acond, ncond; switch (condition) { case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break; diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index d792a0f62a6..cdea66f3866 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -741,7 +741,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) { // generate conditional move of boolean result LIR_Opr result = rlock_result(x); - __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); + __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG); } @@ -810,7 +810,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { // generate conditional move of boolean result LIR_Opr result = rlock_result(x); - __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); + __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), + result, as_BasicType(type)); if (type == objectType) { // Write-barrier needed for Object fields. // Seems to be precise post_barrier(addr, val.result()); diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index 7a3574cfa95..50bf4c4e9ba 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -1568,15 +1568,16 @@ class LIR_Op2: public LIR_Op { assert(code == lir_cmp, "code check"); } - LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) + LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) : LIR_Op(code, result, NULL) , _opr1(opr1) , _opr2(opr2) - , _type(T_ILLEGAL) + , _type(type) , _condition(condition) , _fpu_stack_size(0) , _tmp(LIR_OprFact::illegalOpr) { assert(code == lir_cmove, "code check"); + assert(type != T_ILLEGAL, "cmove should have type"); } LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result = LIR_OprFact::illegalOpr, @@ -1993,8 +1994,8 @@ class LIR_List: public CompilationResourceObj { void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info); void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info); - void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst) { - append(new LIR_Op2(lir_cmove, condition, src1, src2, dst)); + void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) { + append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type)); } void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index c422819974a..1b57ea2f095 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -685,7 +685,7 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { break; case lir_cmove: - cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr()); + cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->type()); break; case lir_shl: diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 24f62862cdf..bb18c253eb5 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -217,7 +217,7 @@ class LIR_Assembler: public CompilationResourceObj { void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); - void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result); + void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type); void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); void ic_call( LIR_OpJavaCall* op); diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 56b22f686f1..8dc579d0dcc 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -856,7 +856,7 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) { __ cmove(lir_cond(cond), LIR_OprFact::intptrConst(taken_count_offset), LIR_OprFact::intptrConst(not_taken_count_offset), - data_offset_reg); + data_offset_reg, as_BasicType(if_instr->x()->type())); // MDO cells are intptr_t, so the data_reg width is arch-dependent. LIR_Opr data_reg = new_pointer_register(); @@ -2591,7 +2591,7 @@ void LIRGenerator::do_IfOp(IfOp* x) { LIR_Opr reg = rlock_result(x); __ cmp(lir_cond(x->cond()), left.result(), right.result()); - __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg); + __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type())); } diff --git a/hotspot/test/compiler/7009231/Test7009231.java b/hotspot/test/compiler/7009231/Test7009231.java new file mode 100644 index 00000000000..64afc6601ef --- /dev/null +++ b/hotspot/test/compiler/7009231/Test7009231.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7009231 + * @summary C1: Incorrect CAS code for longs on SPARC 32bit + * + * @run main/othervm -Xbatch Test7009231 + * + */ + +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; + + +public class Test7009231 { + public static void main(String[] args) throws InterruptedException { + doTest(8); + } + + private static void doTest(int nThreads) throws InterruptedException { + Thread[] aThreads = new Thread[nThreads]; + final AtomicLong atl = new AtomicLong(); + + for (int i = 0; i < nThreads; i++) { + aThreads[i] = new RunnerThread(atl, 1L << (8 * i)); + } + + for (int i = 0; i < nThreads; i++) { + aThreads[i].start(); + } + + for (int i = 0; i < nThreads; i++) { + aThreads[i].join(); + } + } + + public static class RunnerThread extends Thread { + public RunnerThread(AtomicLong atomic, long lMask) { + m_lMask = lMask; + m_atomic = atomic; + } + + public void run() { + AtomicLong atomic = m_atomic; + long lMask = m_lMask; + for (int i = 0; i < 100000; i++) { + setBit(atomic, lMask); + clearBit(atomic, lMask); + } + } + + protected void setBit(AtomicLong atomic, long lMask) { + long lWord; + do { + lWord = atomic.get(); + } while (!atomic.compareAndSet(lWord, lWord | lMask)); + + if ((atomic.get() & lMask) == 0L) { + throw new InternalError(); + } + } + + protected void clearBit(AtomicLong atomic, long lMask) { + long lWord; + do { + lWord = atomic.get(); + } while (!atomic.compareAndSet(lWord, lWord & ~lMask)); + + if ((atomic.get() & lMask) != 0L) { + throw new InternalError(); + } + } + + private long m_lMask; + private AtomicLong m_atomic; + } +} From d60b64b17cfa6af22f13d45519752996cd179d88 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Tue, 28 Dec 2010 16:37:15 +0300 Subject: [PATCH 60/94] 6842956: Assertion error in javax_sound on 64-bit RHEL 5.3 with 32-bit JDK Reviewed-by: bae --- .../sound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c index a2277bdb6a0..db4a30ca330 100644 --- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c @@ -32,6 +32,9 @@ #include #include "PlatformMidi.h" #include "PLATFORM_API_LinuxOS_ALSA_MidiUtils.h" +#if defined(i586) +#include +#endif /* * Helper methods @@ -73,9 +76,38 @@ char* MIDI_IN_GetErrorStr(INT32 err) { return (char*) getErrorStr(err); } - INT32 MIDI_IN_GetNumDevices() { +/* Workaround for 6842956: 32bit app on 64bit linux + * gets assertion failure trying to open midiIn ports. + * Untill the issue is fixed in ALSA + * (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4807) + * report no midi in devices in the configuration. + */ +#if defined(i586) + static int jre32onlinux64 = -1; + if (jre32onlinux64 < 0) { + jre32onlinux64 = 0; + /* The workaround may be disabled setting "JAVASOUND_ENABLE_MIDIIN" + * environment variable. + */ + if (getenv("JAVASOUND_ENABLE_MIDIIN") == NULL) { + struct utsname u; + jre32onlinux64 = 0; + if (uname(&u) == 0) { + if (strstr(u.machine, "64") != NULL) { + TRACE0("jre32 on linux64 detected - report no midiIn devices\n"); + jre32onlinux64 = 1; + } + } + } + } + if (jre32onlinux64) { + return 0; + } +#endif + TRACE0("MIDI_IN_GetNumDevices()\n"); + return getMidiDeviceCount(SND_RAWMIDI_STREAM_INPUT); } From 67712c83708b4e63ad24a4c3257c36e9be3f3939 Mon Sep 17 00:00:00 2001 From: Andrei Dmitriev Date: Tue, 28 Dec 2010 17:13:13 +0300 Subject: [PATCH 61/94] 6999766: Changes to correct c/c++ language issues for use of parfait Reviewed-by: uta, amenkov --- jdk/src/windows/native/sun/windows/Devices.h | 2 +- jdk/src/windows/native/sun/windows/awt.h | 2 +- .../windows/native/sun/windows/awt_Debug.cpp | 11 +++- .../windows/native/sun/windows/awt_Debug.h | 5 +- .../sun/windows/awt_DesktopProperties.cpp | 18 ++--- .../windows/native/sun/windows/awt_TextArea.h | 65 +++++++++---------- .../windows/native/sun/windows/awt_Toolkit.h | 2 +- 7 files changed, 57 insertions(+), 48 deletions(-) diff --git a/jdk/src/windows/native/sun/windows/Devices.h b/jdk/src/windows/native/sun/windows/Devices.h index e8324ce4c6c..748ded20a3f 100644 --- a/jdk/src/windows/native/sun/windows/Devices.h +++ b/jdk/src/windows/native/sun/windows/Devices.h @@ -54,7 +54,7 @@ static BOOL UpdateInstance(JNIEnv *env); InstanceAccess& operator=(const InstanceAccess&); InstanceAccess* operator&(); }; -friend InstanceAccess; +friend class InstanceAccess; private: Devices(int numElements); diff --git a/jdk/src/windows/native/sun/windows/awt.h b/jdk/src/windows/native/sun/windows/awt.h index 8fdef922369..b78a80272f2 100644 --- a/jdk/src/windows/native/sun/windows/awt.h +++ b/jdk/src/windows/native/sun/windows/awt.h @@ -173,7 +173,7 @@ extern JavaVM *jvm; // Platform encoding is Unicode (UTF-16), re-define JNU_ functions // to proper JNI functions. -#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast(x), static_cast(_tcslen(x))) +#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast(x), static_cast(_tcslen(x))) #define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast(env->GetStringChars(x, y)) #define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast(y)) diff --git a/jdk/src/windows/native/sun/windows/awt_Debug.cpp b/jdk/src/windows/native/sun/windows/awt_Debug.cpp index 3d6c424dbf2..42e099bb599 100644 --- a/jdk/src/windows/native/sun/windows/awt_Debug.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Debug.cpp @@ -47,12 +47,21 @@ void * operator new(size_t size, const char * filename, int linenumber) { return ptr; } +void * operator new[](size_t size, const char * filename, int linenumber) { + void * ptr = DMem_AllocateBlock(size, filename, linenumber); + if (ptr == NULL) { + throw std::bad_alloc(); + } + + return ptr; +} + #if _MSC_VER >= 1200 void operator delete(void *ptr, const char*, int) { DASSERTMSG(FALSE, "This version of 'delete' should never get called!!!"); } #endif -void operator delete(void *ptr) { +void operator delete(void *ptr) throw() { DMem_FreeBlock(ptr); } diff --git a/jdk/src/windows/native/sun/windows/awt_Debug.h b/jdk/src/windows/native/sun/windows/awt_Debug.h index 9fc4ab6b7d3..729e652621a 100644 --- a/jdk/src/windows/native/sun/windows/awt_Debug.h +++ b/jdk/src/windows/native/sun/windows/awt_Debug.h @@ -48,11 +48,14 @@ }; extern void * operator new(size_t size, const char * filename, int linenumber); + extern void * operator new[](size_t size, const char * filename, int linenumber); + #if _MSC_VER >= 1200 /* VC 6.0 is more strict about enforcing matching placement new & delete */ extern void operator delete(void *ptr, const char*, int); #endif - extern void operator delete(void *ptr); + + extern void operator delete(void *ptr) throw(); extern void DumpClipRectangle(const char * file, int line, int argc, const char * fmt, va_list arglist); extern void DumpUpdateRectangle(const char * file, int line, int argc, const char * fmt, va_list arglist); diff --git a/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp index 0e6148d058a..8eeeae5bc9e 100644 --- a/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp +++ b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp @@ -650,7 +650,7 @@ UINT AwtDesktopProperties::GetIntegerParameter(UINT spi) { } void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) { - jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); + jstring key = JNU_NewStringPlatform(GetEnv(), propName); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setStringPropertyID, key, JNU_NewStringPlatform(GetEnv(), value)); @@ -658,7 +658,7 @@ void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) { } void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) { - jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); + jstring key = JNU_NewStringPlatform(GetEnv(), propName); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setIntegerPropertyID, key, (jint)value); @@ -666,7 +666,7 @@ void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) { } void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) { - jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); + jstring key = JNU_NewStringPlatform(GetEnv(), propName); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setBooleanPropertyID, key, value ? JNI_TRUE : JNI_FALSE); @@ -674,7 +674,7 @@ void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) { } void AwtDesktopProperties::SetColorProperty(LPCTSTR propName, DWORD value) { - jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); + jstring key = JNU_NewStringPlatform(GetEnv(), propName); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setColorPropertyID, key, GetRValue(value), GetGValue(value), @@ -726,7 +726,7 @@ void AwtDesktopProperties::SetFontProperty(HDC dc, int fontID, style |= java_awt_Font_ITALIC; } - jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); + jstring key = JNU_NewStringPlatform(GetEnv(), propName); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID, key, fontName, style, pointSize); @@ -744,7 +744,7 @@ void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & fon jint pointSize; jint style; - fontName = JNU_NewStringPlatform(GetEnv(), const_cast(font.lfFaceName)); + fontName = JNU_NewStringPlatform(GetEnv(), font.lfFaceName); #if 0 HDC hdc; @@ -767,7 +767,7 @@ void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & fon style |= java_awt_Font_ITALIC; } - jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); + jstring key = JNU_NewStringPlatform(GetEnv(), propName); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID, key, fontName, style, pointSize); @@ -776,8 +776,8 @@ void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & fon } void AwtDesktopProperties::SetSoundProperty(LPCTSTR propName, LPCTSTR winEventName) { - jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); - jstring event = JNU_NewStringPlatform(GetEnv(), const_cast(winEventName)); + jstring key = JNU_NewStringPlatform(GetEnv(), propName); + jstring event = JNU_NewStringPlatform(GetEnv(), winEventName); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setSoundPropertyID, key, event); diff --git a/jdk/src/windows/native/sun/windows/awt_TextArea.h b/jdk/src/windows/native/sun/windows/awt_TextArea.h index 27b7b004b97..19a44e7681b 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextArea.h +++ b/jdk/src/windows/native/sun/windows/awt_TextArea.h @@ -41,9 +41,6 @@ class AwtTextArea : public AwtTextComponent { - // inner classes - class OleCallback; - public: /* java.awt.TextArea fields ids */ @@ -89,6 +86,37 @@ public: static void _ReplaceText(void *param); protected: + + /***************************************************************** + * Inner class OleCallback declaration. + */ + class OleCallback : public IRichEditOleCallback { + public: + OleCallback(); + + STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + STDMETHODIMP GetNewStorage(LPSTORAGE FAR * ppstg); + STDMETHODIMP GetInPlaceContext(LPOLEINPLACEFRAME FAR * ppipframe, + LPOLEINPLACEUIWINDOW FAR* ppipuiDoc, + LPOLEINPLACEFRAMEINFO pipfinfo); + STDMETHODIMP ShowContainerUI(BOOL fShow); + STDMETHODIMP QueryInsertObject(LPCLSID pclsid, LPSTORAGE pstg, LONG cp); + STDMETHODIMP DeleteObject(LPOLEOBJECT poleobj); + STDMETHODIMP QueryAcceptData(LPDATAOBJECT pdataobj, CLIPFORMAT *pcfFormat, + DWORD reco, BOOL fReally, HGLOBAL hMetaPict); + STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode); + STDMETHODIMP GetClipboardData(CHARRANGE *pchrg, DWORD reco, + LPDATAOBJECT *ppdataobj); + STDMETHODIMP GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, + LPDWORD pdwEffect); + STDMETHODIMP GetContextMenu(WORD seltype, LPOLEOBJECT poleobj, + CHARRANGE FAR * pchrg, HMENU FAR * phmenu); + private: + ULONG m_refs; // Reference count + };//OleCallback class + INLINE static OleCallback& GetOleCallback() { return sm_oleCallback; } void EditSetSel(CHARRANGE &cr); void EditGetSel(CHARRANGE &cr); @@ -114,37 +142,6 @@ protected: static OleCallback sm_oleCallback; - /***************************************************************** - * Inner class OleCallback declaration. - */ - - class AwtTextArea::OleCallback : public IRichEditOleCallback { - public: - OleCallback(); - - STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj); - STDMETHODIMP_(ULONG) AddRef(); - STDMETHODIMP_(ULONG) Release(); - STDMETHODIMP GetNewStorage(LPSTORAGE FAR * ppstg); - STDMETHODIMP GetInPlaceContext(LPOLEINPLACEFRAME FAR * ppipframe, - LPOLEINPLACEUIWINDOW FAR* ppipuiDoc, - LPOLEINPLACEFRAMEINFO pipfinfo); - STDMETHODIMP ShowContainerUI(BOOL fShow); - STDMETHODIMP QueryInsertObject(LPCLSID pclsid, LPSTORAGE pstg, LONG cp); - STDMETHODIMP DeleteObject(LPOLEOBJECT poleobj); - STDMETHODIMP QueryAcceptData(LPDATAOBJECT pdataobj, CLIPFORMAT *pcfFormat, - DWORD reco, BOOL fReally, HGLOBAL hMetaPict); - STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode); - STDMETHODIMP GetClipboardData(CHARRANGE *pchrg, DWORD reco, - LPDATAOBJECT *ppdataobj); - STDMETHODIMP GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, - LPDWORD pdwEffect); - STDMETHODIMP GetContextMenu(WORD seltype, LPOLEOBJECT poleobj, - CHARRANGE FAR * pchrg, HMENU FAR * phmenu); - private: - ULONG m_refs; // Reference count - }; - }; #endif /* AWT_TEXTAREA_H */ diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.h b/jdk/src/windows/native/sun/windows/awt_Toolkit.h index 01219d610e2..74bdc3ee965 100644 --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h @@ -110,7 +110,7 @@ class CriticalSection { private: const CriticalSection& critSec; }; - friend Lock; + friend class Lock; private: CRITICAL_SECTION rep; From 4286ac7947daddc05b17b1874b2cfec2fa48337c Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 28 Dec 2010 17:34:02 -0800 Subject: [PATCH 62/94] 7009359: HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected Bailout StringConcat optimization if null is passed to StringBuffer constructor. Reviewed-by: iveresov --- hotspot/src/share/vm/opto/stringopts.cpp | 43 +++++++++++++-- .../test/compiler/7009359/Test7009359.java | 52 +++++++++++++++++++ 2 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 hotspot/test/compiler/7009359/Test7009359.java diff --git a/hotspot/src/share/vm/opto/stringopts.cpp b/hotspot/src/share/vm/opto/stringopts.cpp index 93516d5d092..658fc05b11c 100644 --- a/hotspot/src/share/vm/opto/stringopts.cpp +++ b/hotspot/src/share/vm/opto/stringopts.cpp @@ -59,7 +59,8 @@ class StringConcat : public ResourceObj { enum { StringMode, IntMode, - CharMode + CharMode, + StringNullCheckMode }; StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): @@ -114,6 +115,9 @@ class StringConcat : public ResourceObj { void push_string(Node* value) { push(value, StringMode); } + void push_string_null_check(Node* value) { + push(value, StringNullCheckMode); + } void push_int(Node* value) { push(value, IntMode); } @@ -416,7 +420,19 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) { if (sig == ciSymbol::string_void_signature()) { // StringBuilder(String) so pick this up as the first argument assert(use->in(TypeFunc::Parms + 1) != NULL, "what?"); - sc->push_string(use->in(TypeFunc::Parms + 1)); + const Type* type = _gvn->type(use->in(TypeFunc::Parms + 1)); + if (type == TypePtr::NULL_PTR) { + // StringBuilder(null) throws exception. +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print("giving up because StringBuilder(null) throws exception"); + alloc->jvms()->dump_spec(tty); tty->cr(); + } +#endif + return NULL; + } + // StringBuilder(str) argument needs null check. + sc->push_string_null_check(use->in(TypeFunc::Parms + 1)); } // The int variant takes an initial size for the backing // array so just treat it like the void version. @@ -436,7 +452,7 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) { #ifndef PRODUCT if (PrintOptimizeStringConcat) { tty->print("giving up because couldn't find constructor "); - alloc->jvms()->dump_spec(tty); + alloc->jvms()->dump_spec(tty); tty->cr(); } #endif break; @@ -1269,6 +1285,25 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { string_sizes->init_req(argi, string_size); break; } + case StringConcat::StringNullCheckMode: { + const Type* type = kit.gvn().type(arg); + assert(type != TypePtr::NULL_PTR, "missing check"); + if (!type->higher_equal(TypeInstPtr::NOTNULL)) { + // Null check with uncommont trap since + // StringBuilder(null) throws exception. + // Use special uncommon trap instead of + // calling normal do_null_check(). + Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); + IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); + overflow->add_req(__ IfFalse(iff)); + Node* notnull = __ IfTrue(iff); + kit.set_control(notnull); // set control for the cast_not_null + arg = kit.cast_not_null(arg, false); + sc->set_argument(argi, arg); + } + assert(kit.gvn().type(arg)->higher_equal(TypeInstPtr::NOTNULL), "sanity"); + // Fallthrough to add string length. + } case StringConcat::StringMode: { const Type* type = kit.gvn().type(arg); if (type == TypePtr::NULL_PTR) { @@ -1328,6 +1363,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { // Hook PreserveJVMState pjvms(&kit); kit.set_control(overflow); + C->record_for_igvn(overflow); kit.uncommon_trap(Deoptimization::Reason_intrinsic, Deoptimization::Action_make_not_entrant); } @@ -1363,6 +1399,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { start = end; break; } + case StringConcat::StringNullCheckMode: case StringConcat::StringMode: { start = copy_string(kit, arg, char_array, start); break; diff --git a/hotspot/test/compiler/7009359/Test7009359.java b/hotspot/test/compiler/7009359/Test7009359.java new file mode 100644 index 00000000000..408fd713e3e --- /dev/null +++ b/hotspot/test/compiler/7009359/Test7009359.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7009359 + * @summary HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected + * + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=exclude,Test7009359,main Test7009359 + * + */ + +public class Test7009359 { + public static void main (String[] args) { + for(int i = 0; i < 1000000; i++) { + if(!stringmakerBUG(null).equals("NPE")) { + System.out.println("StringBuffer(null) does not throw NPE"); + System.exit(97); + } + } + } + + public static String stringmakerBUG(String str) { + try { + return new StringBuffer(str).toString(); + } catch (NullPointerException e) { + return "NPE"; + } + } +} + From 25a7d0c26f8963853a5d9ed0a392b0e9adba56ec Mon Sep 17 00:00:00 2001 From: Andrei Dmitriev Date: Wed, 29 Dec 2010 15:13:00 +0300 Subject: [PATCH 63/94] 7008106: com/sun/awt/Translucency/WindowOpacity.java test fails just against jdk7 b122 Reviewed-by: dcherepanov --- jdk/test/com/sun/awt/Translucency/WindowOpacity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/com/sun/awt/Translucency/WindowOpacity.java b/jdk/test/com/sun/awt/Translucency/WindowOpacity.java index bf4e74dd48f..a5d80265d60 100644 --- a/jdk/test/com/sun/awt/Translucency/WindowOpacity.java +++ b/jdk/test/com/sun/awt/Translucency/WindowOpacity.java @@ -64,6 +64,7 @@ public class WindowOpacity boolean passed; Frame f = new Frame("Opacity test"); + f.setUndecorated(true); passed = false; try { From e56a2bc8d29d844d277e519c109f2ec40e9d4d75 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Wed, 29 Dec 2010 16:26:23 +0300 Subject: [PATCH 64/94] 7006997: A typo in MidiSystem.getTransmitter() implementation code Reviewed-by: dav --- jdk/src/share/classes/javax/sound/midi/MidiSystem.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/javax/sound/midi/MidiSystem.java b/jdk/src/share/classes/javax/sound/midi/MidiSystem.java index 8c0b5d9ebb5..b2a47dc9654 100644 --- a/jdk/src/share/classes/javax/sound/midi/MidiSystem.java +++ b/jdk/src/share/classes/javax/sound/midi/MidiSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -310,7 +310,7 @@ public class MidiSystem { } else { transmitter = device.getTransmitter(); } - if (!(transmitter instanceof MidiDeviceReceiver)) { + if (!(transmitter instanceof MidiDeviceTransmitter)) { transmitter = new MidiDeviceTransmitterEnvelope(device, transmitter); } return transmitter; From e611aef5630fc8e5907c04c4177fc07ff742ee0f Mon Sep 17 00:00:00 2001 From: Andrei Dmitriev Date: Wed, 29 Dec 2010 17:36:31 +0300 Subject: [PATCH 65/94] 6963357: After clicking the "Load" button,the case FileDialogUserFilterTest.html crashes in jdk7 b98 Reviewed-by: dcherepanov --- .../solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c index 1832401e4fb..63addde831c 100644 --- a/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c +++ b/jdk/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c @@ -191,7 +191,7 @@ Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, fp_gdk_threads_enter(); - const char *title = (*env)->GetStringUTFChars(env, jtitle, 0); + const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0); if (mode == 1) { /* Save action */ @@ -212,7 +212,9 @@ Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, } } - (*env)->ReleaseStringUTFChars(env, jtitle, title); + if (jtitle != NULL) { + (*env)->ReleaseStringUTFChars(env, jtitle, title); + } /* Set the directory */ if (jdir != NULL) { From 28050800c08299a598f47bc5d98a8f4d1c042ca1 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 29 Dec 2010 10:41:43 -0800 Subject: [PATCH 66/94] 7008325: CodeCache exhausted on sparc starting from hs20b04 Remove clear_scratch_buffer_blob and let init_scratch_buffer_blob free and allocate a new blob if required. Reviewed-by: twisti --- hotspot/src/share/vm/code/codeCache.cpp | 6 ++-- hotspot/src/share/vm/code/codeCache.hpp | 1 + hotspot/src/share/vm/memory/heap.cpp | 9 +++++ hotspot/src/share/vm/memory/heap.hpp | 1 + hotspot/src/share/vm/opto/compile.cpp | 45 +++++++++++++------------ hotspot/src/share/vm/opto/output.cpp | 3 -- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index f7e09b2581c..db35aea6e19 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -939,7 +939,9 @@ void CodeCache::print_bounds(outputStream* st) { _heap->high(), _heap->high_boundary()); st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT - " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT, + " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT + " largest_free_block=" SIZE_FORMAT, CodeCache::nof_blobs(), CodeCache::nof_nmethods(), - CodeCache::nof_adapters(), CodeCache::unallocated_capacity()); + CodeCache::nof_adapters(), CodeCache::unallocated_capacity(), + CodeCache::largest_free_block()); } diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index acb288efe7e..df8de7f3f2d 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -158,6 +158,7 @@ class CodeCache : AllStatic { static size_t capacity() { return _heap->capacity(); } static size_t max_capacity() { return _heap->max_capacity(); } static size_t unallocated_capacity() { return _heap->unallocated_capacity(); } + static size_t largest_free_block() { return _heap->largest_free_block(); } static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; } static bool needs_cache_clean() { return _needs_cache_clean; } diff --git a/hotspot/src/share/vm/memory/heap.cpp b/hotspot/src/share/vm/memory/heap.cpp index b6d6484f0e3..94676f78dcc 100644 --- a/hotspot/src/share/vm/memory/heap.cpp +++ b/hotspot/src/share/vm/memory/heap.cpp @@ -315,6 +315,15 @@ size_t CodeHeap::allocated_capacity() const { return l; } +size_t CodeHeap::largest_free_block() const { + size_t len = 0; + for (FreeBlock* b = _freelist; b != NULL; b = b->link()) { + if (b->length() > len) + len = b->length(); + } + return size(len); +} + // Free list management FreeBlock *CodeHeap::following_block(FreeBlock *b) { diff --git a/hotspot/src/share/vm/memory/heap.hpp b/hotspot/src/share/vm/memory/heap.hpp index 95199aac9e7..4f592a20ce2 100644 --- a/hotspot/src/share/vm/memory/heap.hpp +++ b/hotspot/src/share/vm/memory/heap.hpp @@ -161,6 +161,7 @@ class CodeHeap : public CHeapObj { size_t max_capacity() const; size_t allocated_capacity() const; size_t unallocated_capacity() const { return max_capacity() - allocated_capacity(); } + size_t largest_free_block() const; // Debugging void verify(); diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 0ca15e168a3..cad5224e62d 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -444,22 +444,32 @@ void Compile::print_compile_messages() { } +//-----------------------init_scratch_buffer_blob------------------------------ +// Construct a temporary BufferBlob and cache it for this compile. void Compile::init_scratch_buffer_blob(int const_size) { - if (scratch_buffer_blob() != NULL) return; + // If there is already a scratch buffer blob allocated and the + // constant section is big enough, use it. Otherwise free the + // current and allocate a new one. + BufferBlob* blob = scratch_buffer_blob(); + if ((blob != NULL) && (const_size <= _scratch_const_size)) { + // Use the current blob. + } else { + if (blob != NULL) { + BufferBlob::free(blob); + } - // Construct a temporary CodeBuffer to have it construct a BufferBlob - // Cache this BufferBlob for this compile. - ResourceMark rm; - _scratch_const_size = const_size; - int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size); - BufferBlob* blob = BufferBlob::create("Compile::scratch_buffer", size); - // Record the buffer blob for next time. - set_scratch_buffer_blob(blob); - // Have we run out of code space? - if (scratch_buffer_blob() == NULL) { - // Let CompilerBroker disable further compilations. - record_failure("Not enough space for scratch buffer in CodeCache"); - return; + ResourceMark rm; + _scratch_const_size = const_size; + int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size); + blob = BufferBlob::create("Compile::scratch_buffer", size); + // Record the buffer blob for next time. + set_scratch_buffer_blob(blob); + // Have we run out of code space? + if (scratch_buffer_blob() == NULL) { + // Let CompilerBroker disable further compilations. + record_failure("Not enough space for scratch buffer in CodeCache"); + return; + } } // Initialize the relocation buffers @@ -468,13 +478,6 @@ void Compile::init_scratch_buffer_blob(int const_size) { } -void Compile::clear_scratch_buffer_blob() { - assert(scratch_buffer_blob(), "no BufferBlob set"); - set_scratch_buffer_blob(NULL); - set_scratch_locs_memory(NULL); -} - - //-----------------------scratch_emit_size------------------------------------- // Helper function that computes size by emitting code uint Compile::scratch_emit_size(const Node* n) { diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index e2ddd974f1e..de294231621 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -1746,9 +1746,6 @@ void Compile::ScheduleAndBundle() { // Walk backwards over each basic block, computing the needed alignment // Walk over all the basic blocks scheduling.DoScheduling(); - - // Clear the BufferBlob used for scheduling. - clear_scratch_buffer_blob(); } //------------------------------ComputeLocalLatenciesForward------------------- From ec54e400eedcddfde53cd27a2a90d05b7767dd0a Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Thu, 30 Dec 2010 11:33:10 +0300 Subject: [PATCH 67/94] 7003434: test/closed/java/awt/FullScreen/DisplayChangeVITest/DisplayChangeVITest.java fails with ClassCastExc Reviewed-by: jgodinez, prr --- .../classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java b/jdk/src/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java index ba655bf00ba..7c4fde1b640 100644 --- a/jdk/src/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java +++ b/jdk/src/windows/classes/sun/java2d/opengl/WGLVolatileSurfaceManager.java @@ -133,7 +133,9 @@ public class WGLVolatileSurfaceManager @Override protected boolean isConfigValid(GraphicsConfiguration gc) { - return ((gc == null) || (gc == vImg.getGraphicsConfig())); + return ((gc == null) || + ((gc instanceof WGLGraphicsConfig) && + (gc == vImg.getGraphicsConfig()))); } @Override From 528a4138bbf269ade5ae43b570abca62865e2d17 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Thu, 30 Dec 2010 14:57:29 +0300 Subject: [PATCH 68/94] 6989702: sound native code compiler warnings Reviewed-by: bae --- .../PLATFORM_API_LinuxOS_ALSA_CommonUtils.c | 62 ++++++++++--------- .../PLATFORM_API_LinuxOS_ALSA_MidiUtils.c | 4 +- .../sound/PLATFORM_API_LinuxOS_ALSA_PCM.c | 56 +++-------------- .../PLATFORM_API_LinuxOS_ALSA_PCMUtils.h | 3 +- .../sound/PLATFORM_API_LinuxOS_ALSA_Ports.c | 4 +- 5 files changed, 45 insertions(+), 84 deletions(-) diff --git a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c index 3128efe252e..73ec25671d1 100644 --- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c @@ -137,41 +137,43 @@ void getALSAVersion(char* buffer, int len) { file = fopen(ALSA_VERSION_PROC_FILE, "r"); ALSAVersionString[0] = 0; if (file) { - fgets(ALSAVersionString, ALSAVersionString_LENGTH, file); - // parse for version number - totalLen = strlen(ALSAVersionString); - inVersionString = FALSE; - len = 0; - curr = 0; - while (curr < totalLen) { - if (!inVersionString) { - // is this char the beginning of a version string ? - if (ALSAVersionString[curr] >= '0' - && ALSAVersionString[curr] <= '9') { - inVersionString = TRUE; + if (NULL != fgets(ALSAVersionString, ALSAVersionString_LENGTH, file)) { + // parse for version number + totalLen = strlen(ALSAVersionString); + inVersionString = FALSE; + len = 0; + curr = 0; + while (curr < totalLen) { + if (!inVersionString) { + // is this char the beginning of a version string ? + if (ALSAVersionString[curr] >= '0' + && ALSAVersionString[curr] <= '9') { + inVersionString = TRUE; + } } + if (inVersionString) { + // the version string ends with white space + if (ALSAVersionString[curr] <= 32) { + break; + } + if (curr != len) { + // copy this char to the beginning of the string + ALSAVersionString[len] = ALSAVersionString[curr]; + } + len++; + } + curr++; } - if (inVersionString) { - // the version string ends with white space - if (ALSAVersionString[curr] <= 32) { - break; - } - if (curr != len) { - // copy this char to the beginning of the string - ALSAVersionString[len] = ALSAVersionString[curr]; - } - len++; + // remove trailing dots + while ((len > 0) && (ALSAVersionString[len - 1] == '.')) { + len--; } - curr++; + // null terminate + ALSAVersionString[len] = 0; } - // remove trailing dots - while ((len > 0) && (ALSAVersionString[len - 1] == '.')) { - len--; - } - // null terminate - ALSAVersionString[len] = 0; + fclose(file); + hasGottenALSAVersion = TRUE; } - hasGottenALSAVersion = TRUE; } strncpy(buffer, ALSAVersionString, len); } diff --git a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c index 74af23ef042..7d2ac119234 100644 --- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -372,7 +372,7 @@ INT32 openMidiDevice(snd_rawmidi_stream_t direction, INT32 deviceIndex, snd_rawmidi_t* native_handle; snd_midi_event_t* event_parser = NULL; int err; - UINT32 deviceID; + UINT32 deviceID = 0; char devicename[100]; #ifdef ALSA_MIDI_USE_PLUGHW int usePlugHw = 1; diff --git a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c index 58ca8abfcc2..fb2ba3c5da3 100644 --- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,7 +127,7 @@ void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* cre int ret; int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc; int origSampleSizeInBytes, origSignificantBits; - int channels, minChannels, maxChannels; + unsigned int channels, minChannels, maxChannels; int rate, bitIndex; for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE; @@ -152,7 +152,6 @@ void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* cre } } snd_pcm_hw_params_get_format_mask(hwParams, formatMask); -#ifdef ALSA_PCM_NEW_HW_PARAMS_API if (ret == 0) { ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels); if (ret != 0) { @@ -165,13 +164,6 @@ void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* cre ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret); } } -#else - minChannels = snd_pcm_hw_params_get_channels_min(hwParams); - maxChannels = snd_pcm_hw_params_get_channels_max(hwParams); - if (minChannels > maxChannels) { - ERROR2("MinChannels=%d, maxChannels=%d\n", minChannels, maxChannels); - } -#endif // since we queried the hw: device, for many soundcards, it will only // report the maximum number of channels (which is the only way to talk @@ -222,7 +214,7 @@ void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* cre } else { for (channels = minChannels; channels <= maxChannels; channels++) { DAUDIO_AddAudioFormat(creator, significantBits, - (channels < 0)?-1:(sampleSizeInBytes * channels), + sampleSizeInBytes * channels, channels, rate, enc, isSigned, isBigEndian); } @@ -254,7 +246,7 @@ typedef struct tag_AlsaPcmInfo { snd_pcm_sw_params_t* swParams; int bufferSizeInBytes; int frameSize; // storage size in Bytes - int periods; + unsigned int periods; snd_pcm_uframes_t periodSize; #ifdef GET_POSITION_METHOD2 // to be used exclusively by getBytePosition! @@ -305,8 +297,8 @@ int setHWParams(AlsaPcmInfo* info, int channels, int bufferSizeInFrames, snd_pcm_format_t format) { - unsigned int rrate; - int ret, dir, periods, periodTime; + unsigned int rrate, periodTime, periods; + int ret, dir; snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames; /* choose all parameters */ @@ -335,12 +327,8 @@ int setHWParams(AlsaPcmInfo* info, } /* set the stream rate */ rrate = (int) (sampleRate + 0.5f); -#ifdef ALSA_PCM_NEW_HW_PARAMS_API dir = 0; ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir); -#else - ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, rrate, 0); -#endif if (ret < 0) { ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret)); return FALSE; @@ -350,12 +338,7 @@ int setHWParams(AlsaPcmInfo* info, return FALSE; } /* set the buffer time */ -#ifdef ALSA_PCM_NEW_HW_PARAMS_API - ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames); -#else - ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, alsaBufferSizeInFrames); -#endif if (ret < 0) { ERROR2("Unable to set buffer size to %d frames: %s\n", (int) alsaBufferSizeInFrames, snd_strerror(ret)); @@ -366,12 +349,7 @@ int setHWParams(AlsaPcmInfo* info, if (bufferSizeInFrames > 1024) { dir = 0; periodTime = DEFAULT_PERIOD_TIME; -#ifdef ALSA_PCM_NEW_HW_PARAMS_API ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir); -#else - periodTime = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, periodTime, &dir); - ret = periodTime; -#endif if (ret < 0) { ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret)); return FALSE; @@ -380,12 +358,7 @@ int setHWParams(AlsaPcmInfo* info, /* set the period count for very small buffer sizes to 2 */ dir = 0; periods = 2; -#ifdef ALSA_PCM_NEW_HW_PARAMS_API ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir); -#else - periods = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, periods, &dir); - ret = periods; -#endif if (ret < 0) { ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret)); return FALSE; @@ -421,12 +394,6 @@ int setSWParams(AlsaPcmInfo* info) { ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret)); return FALSE; } - /* align all transfers to 1 sample */ - ret = snd_pcm_sw_params_set_xfer_align(info->handle, info->swParams, 1); - if (ret < 0) { - ERROR1("Unable to set transfer align: %s\n", snd_strerror(ret)); - return FALSE; - } /* write the parameters to the playback device */ ret = snd_pcm_sw_params(info->handle, info->swParams); if (ret < 0) { @@ -448,7 +415,6 @@ void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, int ret = 0; AlsaPcmInfo* info = NULL; /* snd_pcm_uframes_t is 64 bit on 64-bit systems */ - snd_pcm_uframes_t alsaPeriodSize = 0; snd_pcm_uframes_t alsaBufferSizeInFrames = 0; @@ -484,21 +450,13 @@ void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, bufferSizeInBytes / frameSize, format)) { info->frameSize = frameSize; -#ifdef ALSA_PCM_NEW_HW_PARAMS_API - ret = snd_pcm_hw_params_get_period_size(info->hwParams, &alsaPeriodSize, &dir); - info->periodSize = (int) alsaPeriodSize; + ret = snd_pcm_hw_params_get_period_size(info->hwParams, &info->periodSize, &dir); if (ret < 0) { ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret)); } snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir); snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames); info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize; -#else - info->periodSize = snd_pcm_hw_params_get_period_size(info->hwParams, &dir); - info->periods = snd_pcm_hw_params_get_periods(info->hwParams, &dir); - info->bufferSizeInBytes = snd_pcm_hw_params_get_buffer_size(info->hwParams) * frameSize; - ret = 0; -#endif TRACE3(" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n", (int) info->periodSize, info->periods, info->bufferSizeInBytes); } diff --git a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h index c8d920f8de6..ca911d2f486 100644 --- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ */ // define this with a later version of ALSA than 0.9.0rc3 +// (starting from 1.0.0 it became default behaviour) #define ALSA_PCM_NEW_HW_PARAMS_API #include #include "Utilities.h" diff --git a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_Ports.c b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_Ports.c index 465ecadf0f9..0db0e6c4b53 100644 --- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_Ports.c +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_Ports.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -380,7 +380,7 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { void* controls[10]; int numControls; char* portName; - int isPlayback; + int isPlayback = 0; int isMono; int isStereo; char* type; From f02562388c2ef68b404a8374b7a92c2ecb1e1fa5 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 30 Dec 2010 09:36:03 -0800 Subject: [PATCH 69/94] 6928562: Assert(_no_handle_mark_nesting==0,"allocating handle inside NoHandleMark") Reset NoHandleMark before going into VM. Reviewed-by: iveresov --- hotspot/src/share/vm/compiler/abstractCompiler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hotspot/src/share/vm/compiler/abstractCompiler.cpp b/hotspot/src/share/vm/compiler/abstractCompiler.cpp index 5594d1afa4a..942c168e512 100644 --- a/hotspot/src/share/vm/compiler/abstractCompiler.cpp +++ b/hotspot/src/share/vm/compiler/abstractCompiler.cpp @@ -33,6 +33,7 @@ void AbstractCompiler::initialize_runtimes(initializer f, volatile int* state) { bool do_initialization = false; { ThreadInVMfromNative tv(thread); + ResetNoHandleMark rnhm; MutexLocker only_one(CompileThread_lock, thread); if ( *state == uninitialized) { do_initialization = true; @@ -53,6 +54,7 @@ void AbstractCompiler::initialize_runtimes(initializer f, volatile int* state) { // To in_vm so we can use the lock ThreadInVMfromNative tv(thread); + ResetNoHandleMark rnhm; MutexLocker only_one(CompileThread_lock, thread); assert(*state == initializing, "wrong state"); *state = initialized; From 34b0ff28e89da2205b9eb7226bfd64c1e12c01a4 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 30 Dec 2010 23:44:45 -0800 Subject: [PATCH 70/94] 7009849: C1: Incorrect frame size computation Fix frame size computation Reviewed-by: phh, kvn --- hotspot/src/share/vm/c1/c1_FrameMap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_FrameMap.cpp b/hotspot/src/share/vm/c1/c1_FrameMap.cpp index 75975bb2bc3..5b10b966db1 100644 --- a/hotspot/src/share/vm/c1/c1_FrameMap.cpp +++ b/hotspot/src/share/vm/c1/c1_FrameMap.cpp @@ -92,7 +92,7 @@ CallingConvention* FrameMap::java_calling_convention(const BasicTypeArray* signa if (opr->is_address()) { LIR_Address* addr = opr->as_address_ptr(); assert(addr->disp() == (int)addr->disp(), "out of range value"); - out_preserve = MAX2(out_preserve, (intptr_t)addr->disp() / 4); + out_preserve = MAX2(out_preserve, (intptr_t)(addr->disp() - STACK_BIAS) / 4); } i += type2size[t]; } @@ -143,7 +143,7 @@ CallingConvention* FrameMap::c_calling_convention(const BasicTypeArray* signatur args->append(opr); if (opr->is_address()) { LIR_Address* addr = opr->as_address_ptr(); - out_preserve = MAX2(out_preserve, (intptr_t)addr->disp() / 4); + out_preserve = MAX2(out_preserve, (intptr_t)(addr->disp() - STACK_BIAS) / 4); } i += type2size[t]; } From dec384330b68716e88da10e8ec305f10a22be180 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 3 Jan 2011 14:09:11 -0500 Subject: [PATCH 71/94] 6302804: Hotspot VM dies ungraceful death when C heap is exhausted in various places Enhance the error reporting mechanism to help user to fix the problem rather than making it look like a VM error. Reviewed-by: kvn, kamg --- .../solaris_sparc/vm/os_solaris_sparc.cpp | 7 ++ .../os_cpu/solaris_x86/vm/os_solaris_x86.cpp | 7 ++ hotspot/src/share/vm/runtime/arguments.cpp | 7 +- hotspot/src/share/vm/utilities/debug.cpp | 2 +- hotspot/src/share/vm/utilities/vmError.cpp | 67 ++++++++++++++----- hotspot/src/share/vm/utilities/vmError.hpp | 4 +- 6 files changed, 71 insertions(+), 23 deletions(-) diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index 889f7549f80..3b83be3ebba 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -585,6 +585,13 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_ sigaddset(&newset, sig); sigprocmask(SIG_UNBLOCK, &newset, NULL); + // Determine which sort of error to throw. Out of swap may signal + // on the thread stack, which could get a mapping error when touched. + address addr = (address) info->si_addr; + if (sig == SIGBUS && info->si_code == BUS_OBJERR && info->si_errno == ENOMEM) { + vm_exit_out_of_memory(0, "Out of swap space to map in thread stack."); + } + VMError err(t, sig, pc, info, ucVoid); err.report_and_die(); diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 91c7e75a0b4..d9bb0eb58c3 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -742,6 +742,13 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_ sigaddset(&newset, sig); sigprocmask(SIG_UNBLOCK, &newset, NULL); + // Determine which sort of error to throw. Out of swap may signal + // on the thread stack, which could get a mapping error when touched. + address addr = (address) info->si_addr; + if (sig == SIGBUS && info->si_code == BUS_OBJERR && info->si_errno == ENOMEM) { + vm_exit_out_of_memory(0, "Out of swap space to map in thread stack."); + } + VMError err(t, sig, pc, info, ucVoid); err.report_and_die(); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 0a3f9207f0a..09b41b5b0b1 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2297,14 +2297,15 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, } else if (match_option(option, "-Xoss", &tail)) { // HotSpot does not have separate native and Java stacks, ignore silently for compatibility // -Xmaxjitcodesize - } else if (match_option(option, "-Xmaxjitcodesize", &tail)) { + } else if (match_option(option, "-Xmaxjitcodesize", &tail) || + match_option(option, "-XX:ReservedCodeCacheSize=", &tail)) { julong long_ReservedCodeCacheSize = 0; ArgsRange errcode = parse_memory_size(tail, &long_ReservedCodeCacheSize, (size_t)InitialCodeCacheSize); if (errcode != arg_in_range) { jio_fprintf(defaultStream::error_stream(), - "Invalid maximum code cache size: %s\n", - option->optionString); + "Invalid maximum code cache size: %s. Should be greater than InitialCodeCacheSize=%dK\n", + option->optionString, InitialCodeCacheSize/K); describe_range_error(errcode); return JNI_EINVAL; } diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index 484dcf581a7..cb44189fd4a 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -226,7 +226,7 @@ static jint _exiting_out_of_mem = 0; void report_vm_out_of_memory(const char* file, int line, size_t size, const char* message) { - if (Debugging || error_is_suppressed(file, line)) return; + if (Debugging) return; // We try to gather additional information for the first out of memory // error only; gathering additional data might cause an allocation and a diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 37111503621..4b8e055d496 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -67,7 +67,7 @@ const char *env_list[] = { // threads are blocked forever inside report_and_die(). // Constructor for crashes -VMError::VMError(Thread* thread, int sig, address pc, void* siginfo, void* context) { +VMError::VMError(Thread* thread, unsigned int sig, address pc, void* siginfo, void* context) { _thread = thread; _id = sig; _pc = pc; @@ -322,29 +322,51 @@ void VMError::report(outputStream* st) { STEP(10, "(printing fatal error message)") - st->print_cr("#"); - st->print_cr("# A fatal error has been detected by the Java Runtime Environment:"); + st->print_cr("#"); + if (should_report_bug(_id)) { + st->print_cr("# A fatal error has been detected by the Java Runtime Environment:"); + } else { + st->print_cr("# There is insufficient memory for the Java " + "Runtime Environment to continue."); + } STEP(15, "(printing type of error)") switch(_id) { case oom_error: - st->print_cr("#"); - st->print("# java.lang.OutOfMemoryError: "); if (_size) { - st->print("requested "); - sprintf(buf,SIZE_FORMAT,_size); + st->print("# Native memory allocation (malloc) failed to allocate "); + jio_snprintf(buf, sizeof(buf), SIZE_FORMAT, _size); st->print(buf); st->print(" bytes"); if (_message != NULL) { st->print(" for "); st->print(_message); } - st->print_cr(". Out of swap space?"); + st->cr(); } else { if (_message != NULL) + st->print("# "); st->print_cr(_message); } + // In error file give some solutions + if (_verbose) { + st->print_cr("# Possible reasons:"); + st->print_cr("# The system is out of physical RAM or swap space"); + st->print_cr("# In 32 bit mode, the process size limit was hit"); + st->print_cr("# Possible solutions:"); + st->print_cr("# Reduce memory load on the system"); + st->print_cr("# Increase physical memory or swap space"); + st->print_cr("# Check if swap backing store is full"); + st->print_cr("# Use 64 bit Java on a 64 bit OS"); + st->print_cr("# Decrease Java heap size (-Xmx/-Xms)"); + st->print_cr("# Decrease number of Java threads"); + st->print_cr("# Decrease Java thread stack sizes (-Xss)"); + st->print_cr("# Set larger code cache with -XX:ReservedCodeCacheSize="); + st->print_cr("# This output file may be truncated or incomplete."); + } else { + return; // that's enough for the screen + } break; case internal_error: default: @@ -361,7 +383,11 @@ void VMError::report(outputStream* st) { st->print(" (0x%x)", _id); // signal number st->print(" at pc=" PTR_FORMAT, _pc); } else { - st->print("Internal Error"); + if (should_report_bug(_id)) { + st->print("Internal Error"); + } else { + st->print("Out of Memory Error"); + } if (_filename != NULL && _lineno > 0) { #ifdef PRODUCT // In product mode chop off pathname? @@ -393,12 +419,14 @@ void VMError::report(outputStream* st) { STEP(40, "(printing error message)") - // error message - if (_detail_msg) { - st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg); - } else if (_message) { - st->print_cr("# Error: %s", _message); - } + if (should_report_bug(_id)) { // already printed the message. + // error message + if (_detail_msg) { + st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg); + } else if (_message) { + st->print_cr("# Error: %s", _message); + } + } STEP(50, "(printing Java version string)") @@ -428,7 +456,9 @@ void VMError::report(outputStream* st) { STEP(65, "(printing bug submit message)") - if (_verbose) print_bug_submit_message(st, _thread); + if (should_report_bug(_id) && _verbose) { + print_bug_submit_message(st, _thread); + } STEP(70, "(printing thread)" ) @@ -906,7 +936,7 @@ void VMError::report_and_die() { OnError = NULL; } - static bool skip_bug_url = false; + static bool skip_bug_url = !should_report_bug(first_error->_id); if (!skip_bug_url) { skip_bug_url = true; @@ -919,7 +949,8 @@ void VMError::report_and_die() { static bool skip_os_abort = false; if (!skip_os_abort) { skip_os_abort = true; - os::abort(); + bool dump_core = should_report_bug(first_error->_id); + os::abort(dump_core); } // if os::abort() doesn't abort, try os::die(); diff --git a/hotspot/src/share/vm/utilities/vmError.hpp b/hotspot/src/share/vm/utilities/vmError.hpp index 3d80ce321d9..e9d60b3a121 100644 --- a/hotspot/src/share/vm/utilities/vmError.hpp +++ b/hotspot/src/share/vm/utilities/vmError.hpp @@ -87,10 +87,12 @@ class VMError : public StackObj { // accessor const char* message() const { return _message; } const char* detail_msg() const { return _detail_msg; } + bool should_report_bug(unsigned int id) { return id != oom_error; } public: // Constructor for crashes - VMError(Thread* thread, int sig, address pc, void* siginfo, void* context); + VMError(Thread* thread, unsigned int sig, address pc, void* siginfo, + void* context); // Constructor for VM internal errors VMError(Thread* thread, const char* filename, int lineno, const char* message, const char * detail_msg); From 21c037bb9bb7ca2c1990812a512aae22b9737f7a Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 5 Jan 2011 09:59:01 +0000 Subject: [PATCH 72/94] 7010194: several langtools regression failures after JSR 292 changes (b123) Some regression tests rely on unsupported JSR 292 features Reviewed-by: jjg --- .../TypeParameterOnPolymorphicSignature.java | 6 +- .../test/tools/javac/meth/InvokeDyn.java | 64 ------------------- .../test/tools/javac/meth/InvokeDynTrans.java | 59 ----------------- .../test/tools/javac/meth/XlintWarn.java | 8 +-- 4 files changed, 7 insertions(+), 130 deletions(-) delete mode 100644 langtools/test/tools/javac/meth/InvokeDyn.java delete mode 100644 langtools/test/tools/javac/meth/InvokeDynTrans.java diff --git a/langtools/test/tools/javac/diags/examples/TypeParameterOnPolymorphicSignature.java b/langtools/test/tools/javac/diags/examples/TypeParameterOnPolymorphicSignature.java index 77a02b9c52e..fc23fde5412 100644 --- a/langtools/test/tools/javac/diags/examples/TypeParameterOnPolymorphicSignature.java +++ b/langtools/test/tools/javac/diags/examples/TypeParameterOnPolymorphicSignature.java @@ -24,8 +24,10 @@ // key: compiler.warn.type.parameter.on.polymorphic.signature // key: compiler.err.unreported.exception.need.to.catch.or.throw -import java.dyn.InvokeDynamic; +import java.dyn.MethodHandle; class TypeParameterOnPolymorphicSignature { - { InvokeDynamic.call("",123); } + void test(MethodHandle mh) { + mh.invokeExact("",123); + } } diff --git a/langtools/test/tools/javac/meth/InvokeDyn.java b/langtools/test/tools/javac/meth/InvokeDyn.java deleted file mode 100644 index 6285e8c1be1..00000000000 --- a/langtools/test/tools/javac/meth/InvokeDyn.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6754038 6979327 - * @summary Generate call sites for method handle - * @author jrose - * - * @library .. - * @compile -source 7 -target 7 -XDinvokedynamic -XDallowTransitionalJSR292=no InvokeDyn.java - */ -//No: @run main/othervm -XX:+EnableInvokeDynamic meth.InvokeDyn - -/* - * Standalone testing: - * - * $ cd $MY_REPO_DIR/langtools - * $ (cd make; make) - * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/meth/InvokeDyn.java - * $ javap -c -classpath dist meth.InvokeDyn - * - */ - -package meth; - -import java.dyn.*; - -public class InvokeDyn { - class CS extends CallSite { - CS(Object x, Object y, Object z) { throw new RuntimeException(); } - } - //@BootstrapMethod(CS.class) //note: requires 6964498 - void test() throws Throwable { - Object x = "hello"; - Object ojunk; int ijunk; - ojunk = InvokeDynamic.greet(x, "world", 123); - ojunk = InvokeDynamic.greet(x, "mundus", 456); - ojunk = InvokeDynamic.greet(x, "kosmos", 789); - ojunk = (String) InvokeDynamic.cogitate(10.11121, 3.14); - //InvokeDynamic.#"yow: what I mean to say is, please treat this one specially"(null); - ijunk = (int) InvokeDynamic.invoke("goodbye"); - } -} diff --git a/langtools/test/tools/javac/meth/InvokeDynTrans.java b/langtools/test/tools/javac/meth/InvokeDynTrans.java deleted file mode 100644 index 092d649923b..00000000000 --- a/langtools/test/tools/javac/meth/InvokeDynTrans.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6754038 6979327 - * @summary Generate call sites for method handle - * @author jrose - * - * @library .. - * @compile/fail/ref=InvokeDynTrans.out -Werror -XDrawDiagnostics -source 7 -target 7 InvokeDynTrans.java - */ -//No: @run main/othervm -XX:+EnableInvokeDynamic meth.InvokeDyn - -/* - * Standalone testing: - * - * $ cd $MY_REPO_DIR/langtools - * $ (cd make; make) - * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/meth/InvokeDyn.java - * $ javap -c -classpath dist meth.InvokeDyn - * - */ - -package meth; - -import java.dyn.InvokeDynamic; - -public class InvokeDynTrans { - void test() throws Throwable { - Object x = "hello"; - InvokeDynamic.greet(x, "world", 123); - InvokeDynamic.greet(x, "mundus", 456); - InvokeDynamic.greet(x, "kosmos", 789); - InvokeDynamic.cogitate(10.11121, 3.14); - //InvokeDynamic.#"yow: what I mean to say is, please treat this one specially"(null); - InvokeDynamic.invoke("goodbye"); - } -} diff --git a/langtools/test/tools/javac/meth/XlintWarn.java b/langtools/test/tools/javac/meth/XlintWarn.java index 294cd34f106..844994b8e69 100644 --- a/langtools/test/tools/javac/meth/XlintWarn.java +++ b/langtools/test/tools/javac/meth/XlintWarn.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6999067 + * @bug 6999067 7010194 * @summary cast for invokeExact call gets redundant cast to warnings * @author mcimadamore * @@ -34,9 +34,7 @@ import java.dyn.*; class XlintWarn { void test(MethodHandle mh) throws Throwable { - int i1 = (int)mh.invoke(); - int i2 = (int)mh.invokeExact(); - int i3 = (int)mh.invokeVarargs(); - int i4 = (int)InvokeDynamic.test(); + int i1 = (int)mh.invokeExact(); + int i2 = (int)mh.invokeVarargs(); } } From 1f42cca35e309fbbf87372bb1fe8ffd894fe9843 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 5 Jan 2011 21:23:15 -0500 Subject: [PATCH 73/94] 6583275: Hotspot crash in vm_perform_shutdown_actions due to uninitialized TLS during out of memory handling Call get_thread_slow() in vm_perform_shutdown actions and add null check. Reviewed-by: kvn, dholmes, jcoomes --- hotspot/src/share/vm/runtime/java.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index 6abdd64d599..f6b20a7b79e 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -515,8 +515,8 @@ void before_exit(JavaThread * thread) { } void vm_exit(int code) { - Thread* thread = ThreadLocalStorage::thread_index() == -1 ? NULL - : ThreadLocalStorage::get_thread_slow(); + Thread* thread = ThreadLocalStorage::is_initialized() ? + ThreadLocalStorage::get_thread_slow() : NULL; if (thread == NULL) { // we have serious problems -- just exit vm_direct_exit(code); @@ -553,8 +553,9 @@ void vm_perform_shutdown_actions() { // Calling 'exit_globals()' will disable thread-local-storage and cause all // kinds of assertions to trigger in debug mode. if (is_init_completed()) { - Thread* thread = Thread::current(); - if (thread->is_Java_thread()) { + Thread* thread = ThreadLocalStorage::is_initialized() ? + ThreadLocalStorage::get_thread_slow() : NULL; + if (thread != NULL && thread->is_Java_thread()) { // We are leaving the VM, set state to native (in case any OS exit // handlers call back to the VM) JavaThread* jt = (JavaThread*)thread; From aa5ca5f2355474701ecf5a5cb081c31ede7f09cb Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Jan 2011 20:10:13 -0800 Subject: [PATCH 74/94] Added tag jdk7-b124 for changeset a8d5f59bbae6 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 6a03d78b921..7855d830bea 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -98,3 +98,4 @@ a12a9e78df8a9d534da0b4a244ed68f0de0bd58e jdk7-b118 2c2d4f88637b488014c37e1a2eb401f68bca8838 jdk7-b121 f1591eed71f64f6eba79fb7426f5616cc4dfea73 jdk7-b122 ed6950da30cf1e8904b4bdb034d471647942271f jdk7-b123 +024a6755895bf91b5a3c98984c89ee018efbf538 jdk7-b124 From f3af82e899668e3d300093581bfabeec84d50702 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Jan 2011 20:10:14 -0800 Subject: [PATCH 75/94] Added tag jdk7-b124 for changeset aec650969dd5 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 6a4b3aa44b1..b913322417c 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -98,3 +98,4 @@ cff5a173ec1e89013359e804a3e31736ef6fb462 jdk7-b120 2cc9f32992101732b23730b737740e64ebc5fa89 jdk7-b121 1523a060032c8a5b7840198da8911abeff88118f jdk7-b122 a230c142628cea22475ab9dc5cd544266ddf2466 jdk7-b123 +f90b3e014e831eb4f32ef035a1dad2b8ba87949f jdk7-b124 From ebfb6cb15aa79383989b1c2730b81f7151426685 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Jan 2011 20:10:19 -0800 Subject: [PATCH 76/94] Added tag jdk7-b124 for changeset 5f31baaff55b --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index cb26cd3520f..f84e3b8757d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -138,3 +138,4 @@ f5603a6e50422046ebc0d2f1671d55cb8f1bf1e9 jdk7-b120 5484e7c53fa7da5e869902437ee08a9ae10c1c69 hs20-b03 9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 jdk7-b123 9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 hs20-b04 +0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 jdk7-b124 From 8c9c66c2dc4f7ab53d4af016ecb73f9077157887 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Jan 2011 20:10:25 -0800 Subject: [PATCH 77/94] Added tag jdk7-b124 for changeset b715439429dd --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 0f0294e388f..d23d6dd50ad 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -98,3 +98,4 @@ b2f6d9c4f12ffd307a5de40455b2b61b31a5cb79 jdk7-b118 63dae40fa19fd3bf4689ea2f3c1d9d690e1abcee jdk7-b121 03ff13d19c8fa983cbab6542930a7f352e9b5b33 jdk7-b122 e2aedea6495d61557326928de20dbb2d78fdd9aa jdk7-b123 +57ed1f3bec72924cdad102f9bf90f7449ea7bb83 jdk7-b124 From b4949bba8bf01711e0552b77f7e40bbd03a057ed Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Jan 2011 20:10:25 -0800 Subject: [PATCH 78/94] Added tag jdk7-b124 for changeset d08eedd613c1 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index ea04e0a4aee..276dec1d6a1 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -98,3 +98,4 @@ a4f2e1ca67163ef79555082809d7cd719893c338 jdk7-b120 0fa950117faac7bdbc94e6c46b88f6f892031c17 jdk7-b121 17b6c48a344968880925dcef1178fec282feb335 jdk7-b122 5a8e43bcce56b7cd5576419067a929b74575ae71 jdk7-b123 +86f60e5b3975840968f3147ddce047a27a9fc83e jdk7-b124 From 7ce7f859c26335e5897c50149106df798fff5fae Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Jan 2011 20:10:32 -0800 Subject: [PATCH 79/94] Added tag jdk7-b124 for changeset 3ebe17bda998 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index e12216bcd6b..ba484226185 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -98,3 +98,4 @@ ecab7eefb8f2326fd90fb632f47f1b6f81e928f8 jdk7-b119 a661d8587b5d8986aacae086f5df66af9e1a96b1 jdk7-b121 ac311eb325bfc763698219252bf3cee9e091f3af jdk7-b122 869190935eedee7750d955019ab2a1b80f0a13a8 jdk7-b123 +1c72adc9d5f331cb882cf5354ba0dcb118a60b23 jdk7-b124 From 8365212a9fc534a2a89904a0bb8443cafe147502 Mon Sep 17 00:00:00 2001 From: Christine Lu Date: Thu, 6 Jan 2011 20:10:44 -0800 Subject: [PATCH 80/94] Added tag jdk7-b124 for changeset 1f0819a3341f --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 96a41b87352..4a2cb3facf6 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -98,3 +98,4 @@ c491eec0acc73fa41b77e1619ed03e56d8a75b83 jdk7-b118 1bf969e9792f977a8593496681539840a54fe644 jdk7-b121 11e7b4c0476e4d6085d8d28c4aa2833d46714a2a jdk7-b122 a3b5b531542a372f30e014b1543a619a15a90780 jdk7-b123 +4868a36f6fd8972505c466013813eeb28f0482ea jdk7-b124 From 6f2c2c3272d9b84afc4b8596d9304495fa20cc3e Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 7 Jan 2011 03:38:19 -0800 Subject: [PATCH 81/94] 7009975: Large file support broken in hs20-b04 Reviewed-by: phh, acorn, kamg --- hotspot/src/os/solaris/vm/os_solaris.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 7b08e979d2f..dd8ea2c603d 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -5197,7 +5197,7 @@ int os::open(const char *path, int oflag, int mode) { int o_delete = (oflag & O_DELETE); oflag = oflag & ~O_DELETE; - fd = ::open(path, oflag, mode); + fd = ::open64(path, oflag, mode); if (fd == -1) return -1; //If the open succeeded, the file might still be a directory From 7b0134a7cbfd53cd1e97d8b53930617f8b19412d Mon Sep 17 00:00:00 2001 From: Paul Hohensee Date: Fri, 7 Jan 2011 10:42:32 -0500 Subject: [PATCH 82/94] 7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis Track allocated bytes in Thread's, update on TLAB retirement and direct allocation in Eden and tenured, add JNI methods for ThreadMXBean. Reviewed-by: coleenp, kvn, dholmes, ysr --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 24 +++- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 3 +- .../cpu/sparc/vm/c1_MacroAssembler_sparc.cpp | 5 +- .../cpu/sparc/vm/c1_MacroAssembler_sparc.hpp | 2 +- .../src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 7 +- .../src/cpu/sparc/vm/templateTable_sparc.cpp | 27 +++-- hotspot/src/cpu/x86/vm/assembler_x86.cpp | 108 ++++++++++------- hotspot/src/cpu/x86/vm/assembler_x86.hpp | 31 ++--- .../src/cpu/x86/vm/c1_MacroAssembler_x86.cpp | 5 +- hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp | 19 ++- .../src/cpu/x86/vm/templateTable_x86_32.cpp | 18 +-- .../src/cpu/x86/vm/templateTable_x86_64.cpp | 4 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 4 +- .../os/solaris/vm/thread_solaris.inline.hpp | 8 +- .../vm/gc_interface/collectedHeap.inline.hpp | 3 +- .../vm/memory/threadLocalAllocBuffer.cpp | 7 +- .../vm/memory/threadLocalAllocBuffer.hpp | 4 +- hotspot/src/share/vm/opto/macro.cpp | 111 +++++++++++------- hotspot/src/share/vm/prims/jvmti.xml | 4 +- hotspot/src/share/vm/prims/jvmtiEnv.cpp | 10 +- hotspot/src/share/vm/runtime/thread.cpp | 18 +-- hotspot/src/share/vm/runtime/thread.hpp | 78 +++++++----- hotspot/src/share/vm/services/jmm.h | 33 ++++-- hotspot/src/share/vm/services/management.cpp | 106 ++++++++++++++--- .../src/share/vm/services/threadService.cpp | 14 ++- .../src/share/vm/services/threadService.hpp | 6 +- 26 files changed, 447 insertions(+), 212 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 8512afcba95..0436b4e2e66 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -4083,11 +4083,15 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case store_klass(t2, top); verify_oop(top); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1); + sub(top, t1, t1); // size of tlab's allocated portion + incr_allocated_bytes(t1, 0, t2); + // refill the tlab with an eden allocation bind(do_refill); ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t1); sll_ptr(t1, LogHeapWordSize, t1); - // add object_size ?? + // allocate new tlab, address returned in top eden_allocate(top, t1, 0, t2, t3, slow_case); st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_start_offset())); @@ -4115,6 +4119,22 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case delayed()->nop(); } +void MacroAssembler::incr_allocated_bytes(Register var_size_in_bytes, + int con_size_in_bytes, + Register t1) { + // Bump total bytes allocated by this thread + assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch + assert_different_registers(var_size_in_bytes, t1); + // v8 support has gone the way of the dodo + ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1); + if (var_size_in_bytes->is_valid()) { + add(t1, var_size_in_bytes, t1); + } else { + add(t1, con_size_in_bytes, t1); + } + stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset())); +} + Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { switch (cond) { // Note some conditions are synonyms for others diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index ae4357edd76..e50e1784bfb 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2388,6 +2388,7 @@ public: Label& slow_case // continuation point if fast allocation fails ); void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); + void incr_allocated_bytes(Register var_size_in_bytes, int con_size_in_bytes, Register t1); // interface method calling void lookup_interface_method(Register recv_klass, diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index 6340156f779..85eb668337c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -166,7 +166,7 @@ void C1_MacroAssembler::try_allocate( Register obj, // result: pointer to object after successful allocation Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise int con_size_in_bytes, // object size in bytes if known at compile time - Register t1, // temp register + Register t1, // temp register, must be global register for incr_allocated_bytes Register t2, // temp register Label& slow_case // continuation point if fast allocation fails ) { @@ -174,6 +174,7 @@ void C1_MacroAssembler::try_allocate( tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case); } else { eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); + incr_allocated_bytes(var_size_in_bytes, con_size_in_bytes, t1); } } @@ -214,7 +215,7 @@ void C1_MacroAssembler::initialize_body(Register base, Register index) { void C1_MacroAssembler::allocate_object( Register obj, // result: pointer to object after successful allocation Register t1, // temp register - Register t2, // temp register + Register t2, // temp register, must be a global register for try_allocate Register t3, // temp register int hdr_size, // object header size in words int obj_size, // object size in words diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp index b8b063928ab..c0178e5e0f8 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 7dabe35c23e..7ce9a73b610 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -448,7 +448,9 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // get the instance size __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size); + __ tlab_allocate(O0_obj, G1_obj_size, 0, G3_t1, slow_path); + __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); __ verify_oop(O0_obj); __ mov(O0, I0); @@ -459,6 +461,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // get the instance size __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size); __ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path); + __ incr_allocated_bytes(G1_obj_size, 0, G3_t1); + __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); __ verify_oop(O0_obj); __ mov(O0, I0); @@ -573,6 +577,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size); __ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size + __ incr_allocated_bytes(G1_arr_size, 0, G3_t1); __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2); __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset); diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 89637223745..6bfaccd64e3 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3393,21 +3393,21 @@ void TemplateTable::_new() { __ delayed()->st_ptr(RnewTopValue, G2_thread, in_bytes(JavaThread::tlab_top_offset())); if (allow_shared_alloc) { - // Check if tlab should be discarded (refill_waste_limit >= free) - __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), RtlabWasteLimitValue); - __ sub(RendValue, RoldTopValue, RfreeValue); + // Check if tlab should be discarded (refill_waste_limit >= free) + __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), RtlabWasteLimitValue); + __ sub(RendValue, RoldTopValue, RfreeValue); #ifdef _LP64 - __ srlx(RfreeValue, LogHeapWordSize, RfreeValue); + __ srlx(RfreeValue, LogHeapWordSize, RfreeValue); #else - __ srl(RfreeValue, LogHeapWordSize, RfreeValue); + __ srl(RfreeValue, LogHeapWordSize, RfreeValue); #endif - __ cmp(RtlabWasteLimitValue, RfreeValue); - __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, slow_case); // tlab waste is small - __ delayed()->nop(); + __ cmp(RtlabWasteLimitValue, RfreeValue); + __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, slow_case); // tlab waste is small + __ delayed()->nop(); - // increment waste limit to prevent getting stuck on this slow path - __ add(RtlabWasteLimitValue, ThreadLocalAllocBuffer::refill_waste_limit_increment(), RtlabWasteLimitValue); - __ st_ptr(RtlabWasteLimitValue, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset())); + // increment waste limit to prevent getting stuck on this slow path + __ add(RtlabWasteLimitValue, ThreadLocalAllocBuffer::refill_waste_limit_increment(), RtlabWasteLimitValue); + __ st_ptr(RtlabWasteLimitValue, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset())); } else { // No allocation in the shared eden. __ br(Assembler::always, false, Assembler::pt, slow_case); @@ -3445,6 +3445,9 @@ void TemplateTable::_new() { __ cmp(RoldTopValue, RnewTopValue); __ brx(Assembler::notEqual, false, Assembler::pn, retry); __ delayed()->nop(); + + // bump total bytes allocated by this thread + __ incr_allocated_bytes(Roffset, 0, G1_scratch); } if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 85dc5411f02..4c87f23cd13 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -820,7 +820,20 @@ void Assembler::emit_farith(int b1, int b2, int i) { } -// Now the Assembler instruction (identical for 32/64 bits) +// Now the Assembler instructions (identical for 32/64 bits) + +void Assembler::adcl(Address dst, int32_t imm32) { + InstructionMark im(this); + prefix(dst); + emit_arith_operand(0x81, rdx, dst, imm32); +} + +void Assembler::adcl(Address dst, Register src) { + InstructionMark im(this); + prefix(dst, src); + emit_byte(0x11); + emit_operand(src, dst); +} void Assembler::adcl(Register dst, int32_t imm32) { prefix(dst); @@ -2195,9 +2208,7 @@ void Assembler::notl(Register dst) { void Assembler::orl(Address dst, int32_t imm32) { InstructionMark im(this); prefix(dst); - emit_byte(0x81); - emit_operand(rcx, dst, 4); - emit_long(imm32); + emit_arith_operand(0x81, rcx, dst, imm32); } void Assembler::orl(Register dst, int32_t imm32) { @@ -2205,7 +2216,6 @@ void Assembler::orl(Register dst, int32_t imm32) { emit_arith(0x81, 0xC8, dst, imm32); } - void Assembler::orl(Register dst, Address src) { InstructionMark im(this); prefix(src, dst); @@ -2213,7 +2223,6 @@ void Assembler::orl(Register dst, Address src) { emit_operand(dst, src); } - void Assembler::orl(Register dst, Register src) { (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x0B, 0xC0, dst, src); @@ -2692,20 +2701,7 @@ void Assembler::stmxcsr( Address dst) { void Assembler::subl(Address dst, int32_t imm32) { InstructionMark im(this); prefix(dst); - if (is8bit(imm32)) { - emit_byte(0x83); - emit_operand(rbp, dst, 1); - emit_byte(imm32 & 0xFF); - } else { - emit_byte(0x81); - emit_operand(rbp, dst, 4); - emit_long(imm32); - } -} - -void Assembler::subl(Register dst, int32_t imm32) { - prefix(dst); - emit_arith(0x81, 0xE8, dst, imm32); + emit_arith_operand(0x81, rbp, dst, imm32); } void Assembler::subl(Address dst, Register src) { @@ -2715,6 +2711,11 @@ void Assembler::subl(Address dst, Register src) { emit_operand(src, dst); } +void Assembler::subl(Register dst, int32_t imm32) { + prefix(dst); + emit_arith(0x81, 0xE8, dst, imm32); +} + void Assembler::subl(Register dst, Address src) { InstructionMark im(this); prefix(src, dst); @@ -4333,6 +4334,7 @@ void Assembler::sarq(Register dst) { emit_byte(0xD3); emit_byte(0xF8 | encode); } + void Assembler::sbbq(Address dst, int32_t imm32) { InstructionMark im(this); prefixq(dst); @@ -4392,20 +4394,7 @@ void Assembler::shrq(Register dst) { void Assembler::subq(Address dst, int32_t imm32) { InstructionMark im(this); prefixq(dst); - if (is8bit(imm32)) { - emit_byte(0x83); - emit_operand(rbp, dst, 1); - emit_byte(imm32 & 0xFF); - } else { - emit_byte(0x81); - emit_operand(rbp, dst, 4); - emit_long(imm32); - } -} - -void Assembler::subq(Register dst, int32_t imm32) { - (void) prefixq_and_encode(dst->encoding()); - emit_arith(0x81, 0xE8, dst, imm32); + emit_arith_operand(0x81, rbp, dst, imm32); } void Assembler::subq(Address dst, Register src) { @@ -4415,6 +4404,11 @@ void Assembler::subq(Address dst, Register src) { emit_operand(src, dst); } +void Assembler::subq(Register dst, int32_t imm32) { + (void) prefixq_and_encode(dst->encoding()); + emit_arith(0x81, 0xE8, dst, imm32); +} + void Assembler::subq(Register dst, Address src) { InstructionMark im(this); prefixq(src, dst); @@ -7136,9 +7130,9 @@ void MacroAssembler::tlab_allocate(Register obj, } // Preserves rbx, and rdx. -void MacroAssembler::tlab_refill(Label& retry, - Label& try_eden, - Label& slow_case) { +Register MacroAssembler::tlab_refill(Label& retry, + Label& try_eden, + Label& slow_case) { Register top = rax; Register t1 = rcx; Register t2 = rsi; @@ -7185,7 +7179,7 @@ void MacroAssembler::tlab_refill(Label& retry, // if tlab is currently allocated (top or end != null) then // fill [top, end + alignment_reserve) with array object - testptr (top, top); + testptr(top, top); jcc(Assembler::zero, do_refill); // set up the mark word @@ -7197,16 +7191,20 @@ void MacroAssembler::tlab_refill(Label& retry, movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); // set klass to intArrayKlass // dubious reloc why not an oop reloc? - movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); + movptr(t1, ExternalAddress((address)Universe::intArrayKlassObj_addr())); // store klass last. concurrent gcs assumes klass length is valid if // klass field is not null. store_klass(top, t1); + movptr(t1, top); + subptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); + incr_allocated_bytes(thread_reg, t1, 0); + // refill the tlab with an eden allocation bind(do_refill); movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); shlptr(t1, LogHeapWordSize); - // add object_size ?? + // allocate new tlab, address returned in top eden_allocate(top, t1, 0, t2, slow_case); // Check that t1 was preserved in eden_allocate. @@ -7234,6 +7232,34 @@ void MacroAssembler::tlab_refill(Label& retry, movptr(Address(thread_reg, in_bytes(JavaThread::tlab_end_offset())), top); verify_tlab(); jmp(retry); + + return thread_reg; // for use by caller +} + +void MacroAssembler::incr_allocated_bytes(Register thread, + Register var_size_in_bytes, + int con_size_in_bytes, + Register t1) { +#ifdef _LP64 + if (var_size_in_bytes->is_valid()) { + addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); + } else { + addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); + } +#else + if (!thread->is_valid()) { + assert(t1->is_valid(), "need temp reg"); + thread = t1; + get_thread(thread); + } + + if (var_size_in_bytes->is_valid()) { + addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); + } else { + addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); + } + adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0); +#endif } static const double pi_4 = 0.7853981633974483; diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index b9fcc2eff00..a1a8a96dee6 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -674,12 +674,14 @@ private: // Utilities #ifdef _LP64 - static bool is_simm(int64_t x, int nbits) { return -( CONST64(1) << (nbits-1) ) <= x && x < ( CONST64(1) << (nbits-1) ); } + static bool is_simm(int64_t x, int nbits) { return -(CONST64(1) << (nbits-1)) <= x && + x < (CONST64(1) << (nbits-1)); } static bool is_simm32(int64_t x) { return x == (int64_t)(int32_t)x; } #else - static bool is_simm(int32_t x, int nbits) { return -( 1 << (nbits-1) ) <= x && x < ( 1 << (nbits-1) ); } + static bool is_simm(int32_t x, int nbits) { return -(1 << (nbits-1)) <= x && + x < (1 << (nbits-1)); } static bool is_simm32(int32_t x) { return true; } -#endif // LP64 +#endif // _LP64 // Generic instructions // Does 32bit or 64bit as needed for the platform. In some sense these @@ -705,7 +707,6 @@ private: void push(void* v); void pop(void* v); - // These do register sized moves/scans void rep_mov(); void rep_set(); @@ -716,6 +717,8 @@ private: // Vanilla instructions in lexical order + void adcl(Address dst, int32_t imm32); + void adcl(Address dst, Register src); void adcl(Register dst, int32_t imm32); void adcl(Register dst, Address src); void adcl(Register dst, Register src); @@ -724,7 +727,6 @@ private: void adcq(Register dst, Address src); void adcq(Register dst, Register src); - void addl(Address dst, int32_t imm32); void addl(Address dst, Register src); void addl(Register dst, int32_t imm32); @@ -737,7 +739,6 @@ private: void addq(Register dst, Address src); void addq(Register dst, Register src); - void addr_nop_4(); void addr_nop_5(); void addr_nop_7(); @@ -759,7 +760,6 @@ private: void andq(Register dst, Address src); void andq(Register dst, Register src); - // Bitwise Logical AND of Packed Double-Precision Floating-Point Values void andpd(XMMRegister dst, Address src); void andpd(XMMRegister dst, XMMRegister src); @@ -1151,7 +1151,7 @@ private: #ifdef _LP64 void movq(Register dst, Register src); void movq(Register dst, Address src); - void movq(Address dst, Register src); + void movq(Address dst, Register src); #endif void movq(Address dst, MMXRegister src ); @@ -1177,7 +1177,7 @@ private: void movsbq(Register dst, Register src); // Move signed 32bit immediate to 64bit extending sign - void movslq(Address dst, int32_t imm64); + void movslq(Address dst, int32_t imm64); void movslq(Register dst, int32_t imm64); void movslq(Register dst, Address src); @@ -1857,7 +1857,10 @@ class MacroAssembler: public Assembler { Register t2, // temp register Label& slow_case // continuation point if fast allocation fails ); - void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); + Register tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); // returns TLS address + void incr_allocated_bytes(Register thread, + Register var_size_in_bytes, int con_size_in_bytes, + Register t1 = noreg); // interface method calling void lookup_interface_method(Register recv_klass, @@ -2180,9 +2183,9 @@ public: void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); } void divss(XMMRegister dst, AddressLiteral src) { Assembler::divss(dst, as_Address(src)); } - void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } - void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } - void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } void movsd(XMMRegister dst, AddressLiteral src) { Assembler::movsd(dst, as_Address(src)); } void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); } diff --git a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp index 48d117b3fd5..d386a99a096 100644 --- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,6 +141,7 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); } else { eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case); + incr_allocated_bytes(noreg, var_size_in_bytes, con_size_in_bytes, t1); } } @@ -234,7 +235,7 @@ void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) { assert(obj == rax, "obj must be in rax, for cmpxchg"); - assert(obj != t1 && obj != t2 && t1 != t2, "registers must be different"); // XXX really? + assert_different_registers(obj, t1, t2); // XXX really? assert(header_size >= 0 && object_size >= header_size, "illegal sizes"); try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case); diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index ce51fea3add..0a56804258d 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -977,7 +977,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // verify that that there is really a valid exception in rax, __ verify_not_null_oop(exception_oop); - oop_maps = new OopMapSet(); OopMap* oop_map = generate_oop_map(sasm, 1); generate_handle_exception(sasm, oop_maps, oop_map); @@ -1037,13 +1036,16 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // if we got here then the TLAB allocation failed, so try // refilling the TLAB or allocating directly from eden. Label retry_tlab, try_eden; - __ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass) + const Register thread = + __ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass), returns rdi __ bind(retry_tlab); // get the instance size (size is postive so movl is fine for 64bit) __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); + __ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path); + __ initialize_object(obj, klass, obj_size, 0, t1, t2); __ verify_oop(obj); __ pop(rbx); @@ -1053,7 +1055,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ bind(try_eden); // get the instance size (size is postive so movl is fine for 64bit) __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); + __ eden_allocate(obj, obj_size, 0, t1, slow_path); + __ incr_allocated_bytes(thread, obj_size, 0); + __ initialize_object(obj, klass, obj_size, 0, t1, t2); __ verify_oop(obj); __ pop(rbx); @@ -1143,12 +1148,13 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // if we got here then the TLAB allocation failed, so try // refilling the TLAB or allocating directly from eden. Label retry_tlab, try_eden; - __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx, & rdx + const Register thread = + __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx & rdx, returns rdi __ bind(retry_tlab); // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) - // since size is postive movl does right thing on 64bit + // since size is positive movl does right thing on 64bit __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); // since size is postive movl does right thing on 64bit __ movl(arr_size, length); @@ -1175,7 +1181,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ bind(try_eden); // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) - // since size is postive movl does right thing on 64bit + // since size is positive movl does right thing on 64bit __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); // since size is postive movl does right thing on 64bit __ movl(arr_size, length); @@ -1188,6 +1194,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ andptr(arr_size, ~MinObjAlignmentInBytesMask); __ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size + __ incr_allocated_bytes(thread, arr_size, 0); __ initialize_header(obj, klass, length, t1, t2); __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte))); diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index 898069bc948..345b5f62c5e 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3203,10 +3203,12 @@ void TemplateTable::_new() { const bool allow_shared_alloc = Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode; - if (UseTLAB) { - const Register thread = rcx; - + const Register thread = rcx; + if (UseTLAB || allow_shared_alloc) { __ get_thread(thread); + } + + if (UseTLAB) { __ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset()))); __ lea(rbx, Address(rax, rdx, Address::times_1)); __ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset()))); @@ -3247,6 +3249,8 @@ void TemplateTable::_new() { // if someone beat us on the allocation, try again, otherwise continue __ jcc(Assembler::notEqual, retry); + + __ incr_allocated_bytes(thread, rdx, 0); } if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { @@ -3256,12 +3260,12 @@ void TemplateTable::_new() { __ decrement(rdx, sizeof(oopDesc)); __ jcc(Assembler::zero, initialize_header); - // Initialize topmost object field, divide rdx by 8, check if odd and - // test if zero. + // Initialize topmost object field, divide rdx by 8, check if odd and + // test if zero. __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) __ shrl(rdx, LogBytesPerLong); // divide by 2*oopSize and set carry flag if odd - // rdx must have been multiple of 8 + // rdx must have been multiple of 8 #ifdef ASSERT // make sure rdx was multiple of 8 Label L; diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index a396e88da8b..cd45253d592 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3266,6 +3266,8 @@ void TemplateTable::_new() { // if someone beat us on the allocation, try again, otherwise continue __ jcc(Assembler::notEqual, retry); + + __ incr_allocated_bytes(r15_thread, rdx, 0); } if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index dd8ea2c603d..79a030b5f21 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -283,7 +283,7 @@ Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id, is_error_reported(), "sp must be inside of selected thread stack"); - thread->_self_raw_id = raw_id; // mark for quick retrieval + thread->set_self_raw_id(raw_id); // mark for quick retrieval _get_thread_cache[ index ] = thread; } return thread; diff --git a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp index 94c51676d7a..903be9ddc1d 100644 --- a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,10 +53,10 @@ inline Thread* ThreadLocalStorage::thread() { uintptr_t raw = pd_raw_thread_id(); int ix = pd_cache_index(raw); - Thread *Candidate = ThreadLocalStorage::_get_thread_cache[ix]; - if (Candidate->_self_raw_id == raw) { + Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix]; + if (candidate->self_raw_id() == raw) { // hit - return Candidate; + return candidate; } else { return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix); } diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp index c9f5f011126..73f54d98130 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,6 +153,7 @@ HeapWord* CollectedHeap::common_mem_allocate_noinit(size_t size, bool is_noref, check_for_non_bad_heap_word_value(result, size)); assert(!HAS_PENDING_EXCEPTION, "Unexpected exception, will result in uninitialized storage"); + THREAD->incr_allocated_bytes(size * HeapWordSize); return result; } diff --git a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp index f3eec576c2e..74f2c44d412 100644 --- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp +++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,11 @@ void ThreadLocalAllocBuffer::accumulate_statistics() { void ThreadLocalAllocBuffer::make_parsable(bool retire) { if (end() != NULL) { invariants(); + + if (retire) { + myThread()->incr_allocated_bytes(used_bytes()); + } + CollectedHeap::fill_with_object(top(), hard_end(), retire); if (retire || ZeroTLAB) { // "Reset" the TLAB diff --git a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp index 2d091f6931c..4b88835db72 100644 --- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp +++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,6 +112,8 @@ public: HeapWord* top() const { return _top; } HeapWord* pf_top() const { return _pf_top; } size_t desired_size() const { return _desired_size; } + size_t used() const { return pointer_delta(top(), start()); } + size_t used_bytes() const { return pointer_delta(top(), start(), 1); } size_t free() const { return pointer_delta(end(), top()); } // Don't discard tlab if remaining space is larger than this. size_t refill_waste_limit() const { return _refill_waste_limit; } diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 3c95bf0eade..465c8babdd5 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1158,7 +1158,7 @@ void PhaseMacroExpand::expand_allocate_common( // Note: We set the control input on "eden_end" and "old_eden_top" when using // a TLAB to work around a bug where these values were being moved across // a safepoint. These are not oops, so they cannot be include in the oop - // map, but the can be changed by a GC. The proper way to fix this would + // map, but they can be changed by a GC. The proper way to fix this would // be to set the raw memory state when generating a SafepointNode. However // this will require extensive changes to the loop optimization in order to // prevent a degradation of the optimization. @@ -1167,24 +1167,24 @@ void PhaseMacroExpand::expand_allocate_common( // allocate the Region and Phi nodes for the result result_region = new (C, 3) RegionNode(3); - result_phi_rawmem = new (C, 3) PhiNode( result_region, Type::MEMORY, TypeRawPtr::BOTTOM ); - result_phi_rawoop = new (C, 3) PhiNode( result_region, TypeRawPtr::BOTTOM ); - result_phi_i_o = new (C, 3) PhiNode( result_region, Type::ABIO ); // I/O is used for Prefetch + result_phi_rawmem = new (C, 3) PhiNode(result_region, Type::MEMORY, TypeRawPtr::BOTTOM); + result_phi_rawoop = new (C, 3) PhiNode(result_region, TypeRawPtr::BOTTOM); + result_phi_i_o = new (C, 3) PhiNode(result_region, Type::ABIO); // I/O is used for Prefetch // We need a Region for the loop-back contended case. enum { fall_in_path = 1, contended_loopback_path = 2 }; Node *contended_region; Node *contended_phi_rawmem; - if( UseTLAB ) { + if (UseTLAB) { contended_region = toobig_false; contended_phi_rawmem = mem; } else { contended_region = new (C, 3) RegionNode(3); - contended_phi_rawmem = new (C, 3) PhiNode( contended_region, Type::MEMORY, TypeRawPtr::BOTTOM); + contended_phi_rawmem = new (C, 3) PhiNode(contended_region, Type::MEMORY, TypeRawPtr::BOTTOM); // Now handle the passing-too-big test. We fall into the contended // loop-back merge point. - contended_region ->init_req( fall_in_path, toobig_false ); - contended_phi_rawmem->init_req( fall_in_path, mem ); + contended_region ->init_req(fall_in_path, toobig_false); + contended_phi_rawmem->init_req(fall_in_path, mem); transform_later(contended_region); transform_later(contended_phi_rawmem); } @@ -1192,78 +1192,101 @@ void PhaseMacroExpand::expand_allocate_common( // Load(-locked) the heap top. // See note above concerning the control input when using a TLAB Node *old_eden_top = UseTLAB - ? new (C, 3) LoadPNode ( ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ) - : new (C, 3) LoadPLockedNode( contended_region, contended_phi_rawmem, eden_top_adr ); + ? new (C, 3) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM) + : new (C, 3) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr); transform_later(old_eden_top); // Add to heap top to get a new heap top - Node *new_eden_top = new (C, 4) AddPNode( top(), old_eden_top, size_in_bytes ); + Node *new_eden_top = new (C, 4) AddPNode(top(), old_eden_top, size_in_bytes); transform_later(new_eden_top); // Check for needing a GC; compare against heap end - Node *needgc_cmp = new (C, 3) CmpPNode( new_eden_top, eden_end ); + Node *needgc_cmp = new (C, 3) CmpPNode(new_eden_top, eden_end); transform_later(needgc_cmp); - Node *needgc_bol = new (C, 2) BoolNode( needgc_cmp, BoolTest::ge ); + Node *needgc_bol = new (C, 2) BoolNode(needgc_cmp, BoolTest::ge); transform_later(needgc_bol); - IfNode *needgc_iff = new (C, 2) IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN ); + IfNode *needgc_iff = new (C, 2) IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN); transform_later(needgc_iff); // Plug the failing-heap-space-need-gc test into the slow-path region - Node *needgc_true = new (C, 1) IfTrueNode( needgc_iff ); + Node *needgc_true = new (C, 1) IfTrueNode(needgc_iff); transform_later(needgc_true); - if( initial_slow_test ) { - slow_region ->init_req( need_gc_path, needgc_true ); + if (initial_slow_test) { + slow_region->init_req(need_gc_path, needgc_true); // This completes all paths into the slow merge point transform_later(slow_region); } else { // No initial slow path needed! // Just fall from the need-GC path straight into the VM call. - slow_region = needgc_true; + slow_region = needgc_true; } // No need for a GC. Setup for the Store-Conditional - Node *needgc_false = new (C, 1) IfFalseNode( needgc_iff ); + Node *needgc_false = new (C, 1) IfFalseNode(needgc_iff); transform_later(needgc_false); // Grab regular I/O before optional prefetch may change it. // Slow-path does no I/O so just set it to the original I/O. - result_phi_i_o->init_req( slow_result_path, i_o ); + result_phi_i_o->init_req(slow_result_path, i_o); i_o = prefetch_allocation(i_o, needgc_false, contended_phi_rawmem, old_eden_top, new_eden_top, length); + // Name successful fast-path variables + Node* fast_oop = old_eden_top; + Node* fast_oop_ctrl; + Node* fast_oop_rawmem; + // Store (-conditional) the modified eden top back down. // StorePConditional produces flags for a test PLUS a modified raw // memory state. - Node *store_eden_top; - Node *fast_oop_ctrl; - if( UseTLAB ) { - store_eden_top = new (C, 4) StorePNode( needgc_false, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, new_eden_top ); + if (UseTLAB) { + Node* store_eden_top = + new (C, 4) StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr, + TypeRawPtr::BOTTOM, new_eden_top); transform_later(store_eden_top); fast_oop_ctrl = needgc_false; // No contention, so this is the fast path + fast_oop_rawmem = store_eden_top; } else { - store_eden_top = new (C, 5) StorePConditionalNode( needgc_false, contended_phi_rawmem, eden_top_adr, new_eden_top, old_eden_top ); + Node* store_eden_top = + new (C, 5) StorePConditionalNode(needgc_false, contended_phi_rawmem, eden_top_adr, + new_eden_top, fast_oop/*old_eden_top*/); transform_later(store_eden_top); - Node *contention_check = new (C, 2) BoolNode( store_eden_top, BoolTest::ne ); + Node *contention_check = new (C, 2) BoolNode(store_eden_top, BoolTest::ne); transform_later(contention_check); store_eden_top = new (C, 1) SCMemProjNode(store_eden_top); transform_later(store_eden_top); // If not using TLABs, check to see if there was contention. - IfNode *contention_iff = new (C, 2) IfNode ( needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN ); + IfNode *contention_iff = new (C, 2) IfNode (needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN); transform_later(contention_iff); - Node *contention_true = new (C, 1) IfTrueNode( contention_iff ); + Node *contention_true = new (C, 1) IfTrueNode(contention_iff); transform_later(contention_true); // If contention, loopback and try again. - contended_region->init_req( contended_loopback_path, contention_true ); - contended_phi_rawmem->init_req( contended_loopback_path, store_eden_top ); + contended_region->init_req(contended_loopback_path, contention_true); + contended_phi_rawmem->init_req(contended_loopback_path, store_eden_top); // Fast-path succeeded with no contention! - Node *contention_false = new (C, 1) IfFalseNode( contention_iff ); + Node *contention_false = new (C, 1) IfFalseNode(contention_iff); transform_later(contention_false); fast_oop_ctrl = contention_false; + + // Bump total allocated bytes for this thread + Node* thread = new (C, 1) ThreadLocalNode(); + transform_later(thread); + Node* alloc_bytes_adr = basic_plus_adr(top()/*not oop*/, thread, + in_bytes(JavaThread::allocated_bytes_offset())); + Node* alloc_bytes = make_load(fast_oop_ctrl, store_eden_top, alloc_bytes_adr, + 0, TypeLong::LONG, T_LONG); +#ifdef _LP64 + Node* alloc_size = size_in_bytes; +#else + Node* alloc_size = new (C, 2) ConvI2LNode(size_in_bytes); + transform_later(alloc_size); +#endif + Node* new_alloc_bytes = new (C, 3) AddLNode(alloc_bytes, alloc_size); + transform_later(new_alloc_bytes); + fast_oop_rawmem = make_store(fast_oop_ctrl, store_eden_top, alloc_bytes_adr, + 0, new_alloc_bytes, T_LONG); } - // Rename successful fast-path variables to make meaning more obvious - Node* fast_oop = old_eden_top; - Node* fast_oop_rawmem = store_eden_top; fast_oop_rawmem = initialize_object(alloc, fast_oop_ctrl, fast_oop_rawmem, fast_oop, klass_node, length, size_in_bytes); @@ -1282,11 +1305,11 @@ void PhaseMacroExpand::expand_allocate_common( call->init_req(TypeFunc::Parms+0, thread); call->init_req(TypeFunc::Parms+1, fast_oop); - call->init_req( TypeFunc::Control, fast_oop_ctrl ); - call->init_req( TypeFunc::I_O , top() ) ; // does no i/o - call->init_req( TypeFunc::Memory , fast_oop_rawmem ); - call->init_req( TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr) ); - call->init_req( TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr) ); + call->init_req(TypeFunc::Control, fast_oop_ctrl); + call->init_req(TypeFunc::I_O , top()); // does no i/o + call->init_req(TypeFunc::Memory , fast_oop_rawmem); + call->init_req(TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr)); + call->init_req(TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr)); transform_later(call); fast_oop_ctrl = new (C, 1) ProjNode(call,TypeFunc::Control); transform_later(fast_oop_ctrl); @@ -1295,10 +1318,10 @@ void PhaseMacroExpand::expand_allocate_common( } // Plug in the successful fast-path into the result merge point - result_region ->init_req( fast_result_path, fast_oop_ctrl ); - result_phi_rawoop->init_req( fast_result_path, fast_oop ); - result_phi_i_o ->init_req( fast_result_path, i_o ); - result_phi_rawmem->init_req( fast_result_path, fast_oop_rawmem ); + result_region ->init_req(fast_result_path, fast_oop_ctrl); + result_phi_rawoop->init_req(fast_result_path, fast_oop); + result_phi_i_o ->init_req(fast_result_path, i_o); + result_phi_rawmem->init_req(fast_result_path, fast_oop_rawmem); } else { slow_region = ctrl; } diff --git a/hotspot/src/share/vm/prims/jvmti.xml b/hotspot/src/share/vm/prims/jvmti.xml index 672a59380f6..9e24fb64b1c 100644 --- a/hotspot/src/share/vm/prims/jvmti.xml +++ b/hotspot/src/share/vm/prims/jvmti.xml @@ -1,7 +1,7 @@