OpenJDK / portola / portola
changeset 7992:42ed82f1c067
Merge
author | lana |
---|---|
date | Wed, 19 Jan 2011 19:00:30 -0800 |
parents | 96cdf8806d96 f1df06807698 |
children | 8778b8786a81 059b8737ff55 |
files | jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.html jdk/test/java/awt/Insets/WindowWithWarningTest/WindowWithWarningTest.java jdk/test/javax/swing/SwingWorker/6480289/bug6480289.java langtools/test/tools/javac/meth/InvokeDyn.java langtools/test/tools/javac/meth/InvokeDynTrans.java |
diffstat | 199 files changed, 7146 insertions(+), 2410 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Mon Jan 17 13:29:12 2011 +0530 +++ b/.hgtags Wed Jan 19 19:00:30 2011 -0800 @@ -98,3 +98,5 @@ 0ce0a2c3a6926677dc507839a820ab6625541e5a jdk7-b121 6f09ea1c034f087916d2a8cf0d22be768400118f jdk7-b122 142129d8599d1f56b29387e7f9a5fad53b6d61df jdk7-b123 +aa894c225b1a517b665ac2a58295217ea2245134 jdk7-b124 +f658ec2730fa29323c36d23c27e54c7219ef5e16 jdk7-b125
--- a/.hgtags-top-repo Mon Jan 17 13:29:12 2011 +0530 +++ b/.hgtags-top-repo Wed Jan 19 19:00:30 2011 -0800 @@ -98,3 +98,5 @@ 2c2d4f88637b488014c37e1a2eb401f68bca8838 jdk7-b121 f1591eed71f64f6eba79fb7426f5616cc4dfea73 jdk7-b122 ed6950da30cf1e8904b4bdb034d471647942271f jdk7-b123 +024a6755895bf91b5a3c98984c89ee018efbf538 jdk7-b124 +5c4df7e992775c102f08e9f1c0a124b324641b70 jdk7-b125
--- a/corba/.hgtags Mon Jan 17 13:29:12 2011 +0530 +++ b/corba/.hgtags Wed Jan 19 19:00:30 2011 -0800 @@ -98,3 +98,5 @@ 2cc9f32992101732b23730b737740e64ebc5fa89 jdk7-b121 1523a060032c8a5b7840198da8911abeff88118f jdk7-b122 a230c142628cea22475ab9dc5cd544266ddf2466 jdk7-b123 +f90b3e014e831eb4f32ef035a1dad2b8ba87949f jdk7-b124 +1ce58c72b7892cb813eb920276c7e7f17a1b79fe jdk7-b125
--- a/hotspot/.hgtags Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/.hgtags Wed Jan 19 19:00:30 2011 -0800 @@ -138,3 +138,6 @@ 5484e7c53fa7da5e869902437ee08a9ae10c1c69 hs20-b03 9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 jdk7-b123 9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 hs20-b04 +0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 jdk7-b124 +0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 hs20-b05 +e24ab3fa6aafad3efabbe7dba9918c5f461a20b1 jdk7-b125
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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 @@ 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 {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ sizeOfUninitializedData = readInt(); addressOfEntryPoint = readInt(); baseOfCode = readInt(); - if (isPE32Plus) { + if (!isPE32Plus) { + // only available in PE32 baseOfData = readInt(); } } @@ -433,7 +442,10 @@ 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 @@ } class ExportDirectoryTableImpl implements ExportDirectoryTable { + private int exportDataDirRVA; private int offset; private int size; @@ -548,8 +561,9 @@ 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 @@ 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 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 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 @@ 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 @@ 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 @@ 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) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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) + "'" + : ""); } } }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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()); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ throw new DebuggerException("Unimplemented"); } - private static String DTFWHome; private static String imagePath; private static String symbolPath; private static boolean useNativeLookup; @@ -514,81 +513,143 @@ 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. + * + * 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: * - * 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. + * - 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); + // 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"; + + // second place to search is specified by an environment variable: + String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS"); + if (DTFWHome != null) { + searchList.add(DTFWHome); } - } - if (DTFWHome == null) { - // The files better be in the system dir. - String sysDir = System.getenv("SYSTEMROOT") + - File.separator + "system32"; - 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."); - } + // 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) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Wed Jan 19 19:00:30 2011 -0800 @@ -30,6 +30,7 @@ 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 @@ 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 {
--- a/hotspot/make/hotspot_version Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/make/hotspot_version Wed Jan 19 19:00:30 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -31,11 +31,11 @@ # # Don't put quotes (fail windows build). -HOTSPOT_VM_COPYRIGHT=Copyright 2010 +HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=20 HS_MINOR_VER=0 -HS_BUILD_NUMBER=05 +HS_BUILD_NUMBER=06 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/hotspot/make/jprt.properties Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/make/jprt.properties Wed Jan 19 19:00:30 2011 -0800 @@ -150,6 +150,7 @@ 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}-{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.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}-{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.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}-{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.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}-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.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}-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.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}-{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}-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.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}-{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, \
--- a/hotspot/make/solaris/makefiles/buildtree.make Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/make/solaris/makefiles/buildtree.make Wed Jan 19 19:00:30 2011 -0800 @@ -61,7 +61,7 @@ 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
--- a/hotspot/make/solaris/makefiles/vm.make Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/make/solaris/makefiles/vm.make Wed Jan 19 19:00:30 2011 -0800 @@ -119,6 +119,10 @@ LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle 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
--- a/hotspot/make/windows/makefiles/compile.make Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/make/windows/makefiles/compile.make Wed Jan 19 19:00:30 2011 -0800 @@ -152,7 +152,7 @@ !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)
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -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 @@ } -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 @@ } } +// 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 @@ } } -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.) @@ -4083,11 +4102,15 @@ 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 +4138,22 @@ 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
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -1884,23 +1884,24 @@ 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); } @@ -2388,6 +2389,7 @@ 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,
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -1705,8 +1705,7 @@ } -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 @@ 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 @@ #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 @@ __ 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();
--- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -662,7 +662,7 @@ // 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 @@ 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());
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -166,7 +166,7 @@ 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 @@ 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::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
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ // 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 @@ // 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 @@ __ 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);
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -395,18 +395,23 @@ // // 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 @@ 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 @@ // 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 @@ __ 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:
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Jan 19 19:00:30 2011 -0800 @@ -1086,9 +1086,9 @@ 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 @@ 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,9 +3553,10 @@ interface(CONST_INTER); %} -// Pointer Immediate: 32 or 64-bit +#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); @@ -3564,10 +3565,10 @@ 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_niagara_plus() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3))); match(ConP); op_cost(5); @@ -3576,6 +3577,18 @@ interface(CONST_INTER); %} +// Pointer Immediate: 64-bit +operand immP_no_oop_cheap() %{ + 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); + // 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 @@ // 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_niagara_plus() || MacroAssembler::insts_for_set64(n->get_long()) <= 3); match(ConL); op_cost(0); @@ -3683,7 +3696,7 @@ // 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_niagara_plus() && MacroAssembler::insts_for_set64(n->get_long()) > 3); match(ConL); op_cost(0); @@ -6094,8 +6107,18 @@ 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); %}
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ __ 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(); - - // 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())); + __ 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())); } else { // No allocation in the shared eden. __ br(Assembler::always, false, Assembler::pt, slow_case); @@ -3445,6 +3445,9 @@ __ 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()) {
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ _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 @@ 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 @@ } } #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 @@ #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 @@ 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 @@ 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);
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -41,7 +41,12 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; }
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ } -// 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::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 @@ emit_arith(0x81, 0xC8, dst, imm32); } - void Assembler::orl(Register dst, Address src) { InstructionMark im(this); prefix(src, dst); @@ -2213,7 +2223,6 @@ 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::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 @@ 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 @@ 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::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 @@ 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 @@ } // 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 @@ // 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 @@ 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 @@ 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;
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ // 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 @@ void push(void* v); void pop(void* v); - // These do register sized moves/scans void rep_mov(); void rep_set(); @@ -716,6 +717,8 @@ // 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 @@ 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 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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); }
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -2036,7 +2036,7 @@ } } -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;
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -741,7 +741,7 @@ // 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 @@ // 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());
--- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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::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);
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ // 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 @@ // 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 @@ __ 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 @@ // 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 @@ __ 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 @@ __ 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)));
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -385,9 +385,12 @@ // 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 @@ // - 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 @@ 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 @@ __ 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 @@ __ 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 @@ __ 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
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ const bool allow_shared_alloc = Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode; + const Register thread = rcx; + if (UseTLAB || allow_shared_alloc) { + __ get_thread(thread); + } + if (UseTLAB) { - const Register thread = rcx; - - __ get_thread(thread); __ 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 @@ // 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 @@ __ 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;
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ // 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()) {
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -635,7 +635,29 @@ 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
--- a/hotspot/src/os/posix/launcher/java_md.c Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os/posix/launcher/java_md.c Wed Jan 19 19:00:30 2011 -0800 @@ -28,7 +28,6 @@ #include <dlfcn.h> #include <fcntl.h> #include <inttypes.h> -#include <stdint.h> #include <stdio.h> #include <string.h> #include <stdlib.h>
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -80,6 +80,7 @@ // put OS-includes here # include <dlfcn.h> # include <errno.h> +# include <exception> # include <link.h> # include <poll.h> # include <pthread.h> @@ -282,7 +283,7 @@ 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; @@ -1475,6 +1476,13 @@ 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 @@ // use the dynamic check for T2 libthread. os::Solaris::init_thread_fpu_state(); + std::set_terminate(_handle_uncaught_cxx_exception); } @@ -3081,7 +3090,7 @@ 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); } @@ -5188,7 +5197,7 @@ 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
--- a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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); }
--- a/hotspot/src/os/windows/vm/os_windows.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -2004,6 +2004,16 @@ 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), @@ -2028,6 +2038,7 @@ def_excpt(EXCEPTION_INVALID_DISPOSITION), def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), + def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), NULL, 0 }; @@ -2261,7 +2272,6 @@ } } - if (t != NULL && t->is_Java_thread()) { JavaThread* thread = (JavaThread*) t; bool in_java = thread->thread_state() == _thread_in_Java; @@ -2465,8 +2475,9 @@ } // 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; @@ -2490,6 +2501,7 @@ 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); }
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -585,6 +585,13 @@ 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();
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -29,6 +29,7 @@ # include <sys/auxv.h> # include <sys/auxv_SPARC.h> # include <sys/systeminfo.h> +# include <kstat.h> // We need to keep these here as long as we have to build on Solaris // versions before 10. @@ -96,11 +97,23 @@ #ifndef AV_SPARC_ASI_BLK_INIT #define AV_SPARC_ASI_BLK_INIT 0x0080 /* ASI_BLK_INIT_xxx ASI */ #endif + if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m; + #ifndef AV_SPARC_FMAF -#define AV_SPARC_FMAF 0x0100 /* Sparc64 Fused Multiply-Add */ +#define AV_SPARC_FMAF 0x0100 /* Fused Multiply-Add */ #endif - if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m; 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 @@ // 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; }
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -742,6 +742,13 @@ 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();
--- a/hotspot/src/share/vm/adlc/dict2.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/adlc/dict2.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ // Precompute table of null character hashes if( !initflag ) { // Not initializated yet? xsum[0] = (1<<shft[0])+1; // Initialize - for( i = 1; i < MAXID + 1; i++) { + for( i = 1; i < MAXID; i++) { xsum[i] = (1<<shft[i])+1+xsum[i-1]; } initflag = 1; // Never again @@ -291,7 +291,7 @@ c = (c<<1)+1; // Characters are always odd! sum += c + (c<<shft[k++]); // Universal hash function } - assert( k < (MAXID + 1), "Exceeded maximum name length"); + assert( k < (MAXID), "Exceeded maximum name length"); return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size }
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -245,7 +245,7 @@ } -void Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) { +bool Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) { // Preinitialize the consts section to some large size: int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo)); char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); @@ -253,15 +253,20 @@ locs_buffer_size / sizeof(relocInfo)); code->initialize_consts_size(Compilation::desired_max_constant_size()); // Call stubs + two deopt handlers (regular and MH) + exception handler - code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) + - LIR_Assembler::exception_handler_size + - 2 * LIR_Assembler::deopt_handler_size); + int stub_size = (call_stub_estimate * LIR_Assembler::call_stub_size) + + LIR_Assembler::exception_handler_size + + (2 * LIR_Assembler::deopt_handler_size); + if (stub_size >= code->insts_capacity()) return false; + code->initialize_stubs_size(stub_size); + return true; } int Compilation::emit_code_body() { // emit code - setup_code_buffer(code(), allocator()->num_calls()); + if (!setup_code_buffer(code(), allocator()->num_calls())) { + BAILOUT_("size requested greater than avail code buffer size", 0); + } code()->initialize_oop_recorder(env()->oop_recorder()); _masm = new C1_MacroAssembler(code());
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -192,7 +192,7 @@ return desired_max_code_buffer_size() / 10; } - static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate); + static bool setup_code_buffer(CodeBuffer* cb, int call_stub_estimate); // timers static void print_timers();
--- a/hotspot/src/share/vm/c1/c1_FrameMap.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_FrameMap.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -92,7 +92,7 @@ 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 @@ 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]; }
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -1568,15 +1568,16 @@ 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 @@ 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,
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -685,7 +685,7 @@ 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:
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -217,7 +217,7 @@ 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);
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -856,7 +856,7 @@ __ 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 @@ 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())); }
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -90,6 +90,7 @@ , _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::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 @@ } } _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 @@ 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 @@ } _sorted_intervals = combined_list; + assert(is_sorted(_sorted_intervals), "intervals unsorted"); } @@ -1825,6 +1843,8 @@ 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 @@ } } 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); } }
--- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -148,6 +148,7 @@ 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
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -2386,19 +2386,21 @@ 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); } }
--- a/hotspot/src/share/vm/code/codeCache.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/code/codeCache.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -939,7 +939,9 @@ _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()); }
--- a/hotspot/src/share/vm/code/codeCache.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/code/codeCache.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -158,6 +158,7 @@ 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; }
--- a/hotspot/src/share/vm/code/nmethod.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -811,9 +811,11 @@ _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 @@ 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");
--- a/hotspot/src/share/vm/compiler/abstractCompiler.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/compiler/abstractCompiler.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -33,6 +33,7 @@ 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 @@ // 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;
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -332,7 +332,7 @@ "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 @@ 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 @@ 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);
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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; }
--- a/hotspot/src/share/vm/memory/heap.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/memory/heap.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -315,6 +315,15 @@ 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) {
--- a/hotspot/src/share/vm/memory/heap.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/memory/heap.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -161,6 +161,7 @@ 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();
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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::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
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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; }
--- a/hotspot/src/share/vm/memory/universe.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/memory/universe.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -934,7 +934,8 @@ // 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 @@ // 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 @@ 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(); }
--- a/hotspot/src/share/vm/opto/compile.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -444,22 +444,32 @@ } +//-----------------------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::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) {
--- a/hotspot/src/share/vm/opto/escape.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/opto/escape.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -1609,10 +1609,11 @@ // // Normally only 1-3 passes needed to build // Connection Graph depending on graph complexity. - // Set limit to 10 to catch situation when something + // Observed 8 passes in jvm2008 compiler.compiler. + // Set limit to 20 to catch situation when something // did go wrong and recompile the method without EA. -#define CG_BUILD_ITER_LIMIT 10 +#define CG_BUILD_ITER_LIMIT 20 uint length = worklist.length(); int iterations = 0;
--- a/hotspot/src/share/vm/opto/macro.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/opto/macro.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ // 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 @@ // 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 @@ // 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 @@ 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 @@ } // 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; }
--- a/hotspot/src/share/vm/opto/output.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/opto/output.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -1746,9 +1746,6 @@ // 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-------------------
--- a/hotspot/src/share/vm/opto/stringopts.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/opto/stringopts.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -59,7 +59,8 @@ enum { StringMode, IntMode, - CharMode + CharMode, + StringNullCheckMode }; StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): @@ -114,6 +115,9 @@ 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 @@ 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 @@ #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 @@ 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 @@ // 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 @@ start = end; break; } + case StringConcat::StringNullCheckMode: case StringConcat::StringMode: { start = copy_string(kit, arg, char_array, start); break;
--- a/hotspot/src/share/vm/prims/jvmti.xml Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/prims/jvmti.xml Wed Jan 19 19:00:30 2011 -0800 @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="jvmti.xsl"?> <!-- - 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 @@ -10697,7 +10697,7 @@ <internallink id="mUTF">modified UTF-8</internallink> string. </description> </param> - <param id="value"> + <param id="value_ptr"> <inbuf> <char/> <nullok>
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -1802,7 +1802,7 @@ // depth - pre-checked as non-negative // value - pre-checked for NULL jvmtiError -JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value){ +JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value_ptr){ JavaThread* current_thread = JavaThread::current(); // rm object is created to clean up the javaVFrame created in // doit_prologue(), but after doit() is finished with it. @@ -1814,7 +1814,7 @@ if (err != JVMTI_ERROR_NONE) { return err; } else { - *value = op.value().l; + *value_ptr = op.value().l; return JVMTI_ERROR_NONE; } } /* end GetLocalInstance */ @@ -3440,12 +3440,12 @@ // property - pre-checked for NULL // value - NULL is a valid value, must be checked jvmtiError -JvmtiEnv::SetSystemProperty(const char* property, const char* value) { +JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) { jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE; for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { if (strcmp(property, p->key()) == 0) { - if (p->set_value((char *)value)) { + if (p->set_value((char *)value_ptr)) { err = JVMTI_ERROR_NONE; } }
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -111,7 +111,7 @@ //------------------------------------------------------------------------------ // 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 @@ 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 @@ MethodHandles::set_enabled(true); } } + + // Generate method handles adapters if enabled. + if (MethodHandles::enabled()) { + MethodHandles::generate_adapters(CHECK); + } } JVM_END
--- a/hotspot/src/share/vm/prims/methodHandles.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/prims/methodHandles.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -294,11 +294,11 @@ 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 @@ public: MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} - void generate(); + void generate(TRAPS); }; #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
--- a/hotspot/src/share/vm/runtime/arguments.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -2297,14 +2297,15 @@ } 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; }
--- a/hotspot/src/share/vm/runtime/init.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/runtime/init.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -125,9 +125,6 @@ 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.
--- a/hotspot/src/share/vm/runtime/java.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -515,8 +515,8 @@ } 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 @@ // 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;
--- a/hotspot/src/share/vm/runtime/thread.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -177,20 +177,19 @@ Thread::Thread() { - // stack - _stack_base = NULL; - _stack_size = 0; - _self_raw_id = 0; - _lgrp_id = -1; - _osthread = NULL; + // stack and get_thread + set_stack_base(NULL); + set_stack_size(0); + set_self_raw_id(0); + set_lgrp_id(-1); // allocated data structures + set_osthread(NULL); set_resource_area(new ResourceArea()); set_handle_area(new HandleArea(NULL)); set_active_handles(NULL); set_free_handle_block(NULL); set_last_handle_mark(NULL); - set_osthread(NULL); // This initial value ==> never claimed. _oops_do_parity = 0; @@ -205,6 +204,7 @@ NOT_PRODUCT(_skip_gcalot = false;) CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) _jvmti_env_iteration_count = 0; + set_allocated_bytes(0); _vm_operation_started_count = 0; _vm_operation_completed_count = 0; _current_pending_monitor = NULL; @@ -3231,7 +3231,7 @@ warning("java.lang.ArithmeticException has not been initialized"); warning("java.lang.StackOverflowError has not been initialized"); } - } + } // See : bugid 4211085. // Background : the static initializer of java.lang.Compiler tries to read
--- a/hotspot/src/share/vm/runtime/thread.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/runtime/thread.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -60,7 +60,7 @@ class JvmtiGetLoadedClassesClosure; class ThreadStatistics; class ConcurrentLocksDump; -class ParkEvent ; +class ParkEvent; class Parker; class ciEnv; @@ -170,7 +170,7 @@ // // suspend/resume lock: used for self-suspend - Monitor* _SR_lock; + Monitor* _SR_lock; protected: enum SuspendFlags { @@ -194,7 +194,7 @@ public: void enter_signal_handler() { _num_nested_signal++; } void leave_signal_handler() { _num_nested_signal--; } - bool is_inside_signal_handler() const { return _num_nested_signal > 0; } + bool is_inside_signal_handler() const { return _num_nested_signal > 0; } private: // Debug tracing @@ -215,7 +215,7 @@ public: void set_last_handle_mark(HandleMark* mark) { _last_handle_mark = mark; } - HandleMark* last_handle_mark() const { return _last_handle_mark; } + HandleMark* last_handle_mark() const { return _last_handle_mark; } private: // debug support for checking if code does allow safepoints or not @@ -227,11 +227,11 @@ // // The two classes No_Safepoint_Verifier and No_Allocation_Verifier are used to set these counters. // - NOT_PRODUCT(int _allow_safepoint_count;) // If 0, thread allow a safepoint to happen - debug_only (int _allow_allocation_count;) // If 0, the thread is allowed to allocate oops. + NOT_PRODUCT(int _allow_safepoint_count;) // If 0, thread allow a safepoint to happen + debug_only (int _allow_allocation_count;) // If 0, the thread is allowed to allocate oops. // Used by SkipGCALot class. - NOT_PRODUCT(bool _skip_gcalot;) // Should we elide gc-a-lot? + NOT_PRODUCT(bool _skip_gcalot;) // Should we elide gc-a-lot? // Record when GC is locked out via the GC_locker mechanism CHECK_UNHANDLED_OOPS_ONLY(int _gc_locked_out_count;) @@ -242,24 +242,26 @@ friend class ThreadLocalStorage; friend class GC_locker; - ThreadLocalAllocBuffer _tlab; // Thread-local eden + ThreadLocalAllocBuffer _tlab; // Thread-local eden + jlong _allocated_bytes; // Cumulative number of bytes allocated on + // the Java heap - int _vm_operation_started_count; // VM_Operation support - int _vm_operation_completed_count; // VM_Operation support + int _vm_operation_started_count; // VM_Operation support + int _vm_operation_completed_count; // VM_Operation support - ObjectMonitor* _current_pending_monitor; // ObjectMonitor this thread - // is waiting to lock - bool _current_pending_monitor_is_from_java; // locking is from Java code + ObjectMonitor* _current_pending_monitor; // ObjectMonitor this thread + // is waiting to lock + bool _current_pending_monitor_is_from_java; // locking is from Java code // ObjectMonitor on which this thread called Object.wait() ObjectMonitor* _current_waiting_monitor; // Private thread-local objectmonitor list - a simple cache organized as a SLL. public: - ObjectMonitor * omFreeList ; - int omFreeCount ; // length of omFreeList - int omFreeProvision ; // reload chunk size - ObjectMonitor * omInUseList; // SLL to track monitors in circulation + ObjectMonitor* omFreeList; + int omFreeCount; // length of omFreeList + int omFreeProvision; // reload chunk size + ObjectMonitor* omInUseList; // SLL to track monitors in circulation int omInUseCount; // length of omInUseList public: @@ -280,7 +282,6 @@ // Testers virtual bool is_VM_thread() const { return false; } virtual bool is_Java_thread() const { return false; } - // Remove this ifdef when C1 is ported to the compiler interface. virtual bool is_Compiler_thread() const { return false; } virtual bool is_hidden_from_external_view() const { return false; } virtual bool is_jvmti_agent_thread() const { return false; } @@ -344,15 +345,15 @@ // Support for Unhandled Oop detection #ifdef CHECK_UNHANDLED_OOPS private: - UnhandledOops *_unhandled_oops; + UnhandledOops* _unhandled_oops; public: - UnhandledOops* unhandled_oops() { return _unhandled_oops; } + UnhandledOops* unhandled_oops() { return _unhandled_oops; } // Mark oop safe for gc. It may be stack allocated but won't move. - void allow_unhandled_oop(oop *op) { + void allow_unhandled_oop(oop *op) { if (CheckUnhandledOops) unhandled_oops()->allow_unhandled_oop(op); } // Clear oops at safepoint so crashes point to unhandled oop violator - void clear_unhandled_oops() { + void clear_unhandled_oops() { if (CheckUnhandledOops) unhandled_oops()->clear_unhandled_oops(); } bool is_gc_locked_out() { return _gc_locked_out_count > 0; } @@ -392,6 +393,22 @@ } } + jlong allocated_bytes() { return _allocated_bytes; } + void set_allocated_bytes(jlong value) { _allocated_bytes = value; } + void incr_allocated_bytes(jlong size) { _allocated_bytes += size; } + jlong cooked_allocated_bytes() { + jlong allocated_bytes = OrderAccess::load_acquire(&_allocated_bytes); + if (UseTLAB) { + size_t used_bytes = tlab().used_bytes(); + if ((ssize_t)used_bytes > 0) { + // More-or-less valid tlab. The load_acquire above should ensure + // that the result of the add is <= the instantaneous value + return allocated_bytes + used_bytes; + } + } + return allocated_bytes; + } + // VM operation support int vm_operation_ticket() { return ++_vm_operation_started_count; } int vm_operation_completed_count() { return _vm_operation_completed_count; } @@ -489,8 +506,11 @@ return (_stack_base >= adr && adr >= (_stack_base - _stack_size)); } - int lgrp_id() const { return _lgrp_id; } - void set_lgrp_id(int value) { _lgrp_id = value; } + uintptr_t self_raw_id() { return _self_raw_id; } + void set_self_raw_id(uintptr_t value) { _self_raw_id = value; } + + int lgrp_id() const { return _lgrp_id; } + void set_lgrp_id(int value) { _lgrp_id = value; } // Printing void print_on(outputStream* st) const; @@ -502,7 +522,7 @@ #ifdef ASSERT private: // Deadlock detection support for Mutex locks. List of locks own by thread. - Monitor *_owned_locks; + Monitor* _owned_locks; // Mutex::set_owner_implementation is the only place where _owned_locks is modified, // thus the friendship friend class Mutex; @@ -511,7 +531,7 @@ public: void print_owned_locks_on(outputStream* st) const; void print_owned_locks() const { print_owned_locks_on(tty); } - Monitor * owned_locks() const { return _owned_locks; } + Monitor* owned_locks() const { return _owned_locks; } bool owns_locks() const { return owned_locks() != NULL; } bool owns_locks_but_compiled_lock() const; @@ -538,7 +558,7 @@ static ByteSize stack_size_offset() { return byte_offset_of(Thread, _stack_size ); } #define TLAB_FIELD_OFFSET(name) \ - static ByteSize tlab_##name##_offset() { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); } + static ByteSize tlab_##name##_offset() { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); } TLAB_FIELD_OFFSET(start) TLAB_FIELD_OFFSET(end) @@ -552,6 +572,8 @@ #undef TLAB_FIELD_OFFSET + static ByteSize allocated_bytes_offset() { return byte_offset_of(Thread, _allocated_bytes ); } + public: volatile intptr_t _Stalled ; volatile int _TypeTag ;
--- a/hotspot/src/share/vm/services/jmm.h Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/services/jmm.h Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -60,7 +60,8 @@ unsigned int isBootClassPathSupported : 1; unsigned int isObjectMonitorUsageSupported : 1; unsigned int isSynchronizerUsageSupported : 1; - unsigned int : 24; + unsigned int isThreadAllocatedMemorySupported : 1; + unsigned int : 23; } jmmOptionalSupport; typedef enum { @@ -105,7 +106,8 @@ JMM_VERBOSE_GC = 21, JMM_VERBOSE_CLASS = 22, JMM_THREAD_CONTENTION_MONITORING = 23, - JMM_THREAD_CPU_TIME = 24 + JMM_THREAD_CPU_TIME = 24, + JMM_THREAD_ALLOCATED_MEMORY = 25 } jmmBoolAttribute; @@ -213,7 +215,10 @@ jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool); jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool); - void* reserved4; + void (JNICALL *GetThreadAllocatedMemory) + (JNIEnv *env, + jlongArray ids, + jlongArray sizeArray); jobject (JNICALL *GetMemoryUsage) (JNIEnv* env, jboolean heap); @@ -228,6 +233,8 @@ jlong* result); jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env); + + // Not used in JDK 6 or JDK 7 jlong (JNICALL *GetThreadCpuTime) (JNIEnv *env, jlong thread_id); jobjectArray (JNICALL *GetVMGlobalNames) (JNIEnv *env); @@ -262,14 +269,22 @@ void (JNICALL *GetLastGCStat) (JNIEnv *env, jobject mgr, jmmGCStat *gc_stat); - jlong (JNICALL *GetThreadCpuTimeWithKind) (JNIEnv *env, - jlong thread_id, - jboolean user_sys_cpu_time); - void* reserved5; + + jlong (JNICALL *GetThreadCpuTimeWithKind) + (JNIEnv *env, + jlong thread_id, + jboolean user_sys_cpu_time); + void (JNICALL *GetThreadCpuTimesWithKind) + (JNIEnv *env, + jlongArray ids, + jlongArray timeArray, + jboolean user_sys_cpu_time); + jint (JNICALL *DumpHeap0) (JNIEnv *env, jstring outputfile, jboolean live); - jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env, jboolean object_monitors_only); + jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env, + jboolean object_monitors_only); void (JNICALL *SetVMGlobal) (JNIEnv *env, jstring flag_name, jvalue new_value);
--- a/hotspot/src/share/vm/services/management.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/services/management.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -101,12 +101,14 @@ _optional_support.isCurrentThreadCpuTimeSupported = 0; _optional_support.isOtherThreadCpuTimeSupported = 0; } + _optional_support.isBootClassPathSupported = 1; _optional_support.isObjectMonitorUsageSupported = 1; #ifndef SERVICES_KERNEL // This depends on the heap inspector _optional_support.isSynchronizerUsageSupported = 1; #endif // SERVICES_KERNEL + _optional_support.isThreadAllocatedMemorySupported = 1; } void Management::initialize(TRAPS) { @@ -386,11 +388,6 @@ static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) { int num_threads = ids_ah->length(); - // should be non-empty array - if (num_threads == 0) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Empty array of thread IDs"); - } // Validate input thread IDs int i = 0; @@ -402,11 +399,9 @@ "Invalid thread ID entry"); } } - } static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) { - // check if the element of infoArray is of type ThreadInfo class klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK); klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass(); @@ -414,7 +409,6 @@ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "infoArray element type is not ThreadInfo class"); } - } @@ -770,6 +764,45 @@ return prev; JVM_END +// Gets an array containing the amount of memory allocated on the Java +// heap for a set of threads (in bytes). Each element of the array is +// the amount of memory allocated for the thread ID specified in the +// corresponding entry in the given array of thread IDs; or -1 if the +// thread does not exist or has terminated. +JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids, + jlongArray sizeArray)) + // Check if threads is null + if (ids == NULL || sizeArray == NULL) { + THROW(vmSymbols::java_lang_NullPointerException()); + } + + ResourceMark rm(THREAD); + typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); + typeArrayHandle ids_ah(THREAD, ta); + + typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray)); + typeArrayHandle sizeArray_h(THREAD, sa); + + // validate the thread id array + validate_thread_id_array(ids_ah, CHECK); + + // sizeArray must be of the same length as the given array of thread IDs + int num_threads = ids_ah->length(); + if (num_threads != sizeArray_h->length()) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "The length of the given long array does not match the length of " + "the given array of thread IDs"); + } + + MutexLockerEx ml(Threads_lock); + for (int i = 0; i < num_threads; i++) { + JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i)); + if (java_thread != NULL) { + sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes()); + } + } +JVM_END + // Returns a java/lang/management/MemoryUsage object representing // the memory usage for the heap or non-heap memory. JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)) @@ -834,6 +867,8 @@ return ThreadService::is_thread_monitoring_contention(); case JMM_THREAD_CPU_TIME: return ThreadService::is_thread_cpu_time_enabled(); + case JMM_THREAD_ALLOCATED_MEMORY: + return ThreadService::is_thread_allocated_memory_enabled(); default: assert(0, "Unrecognized attribute"); return false; @@ -851,6 +886,8 @@ return ThreadService::set_thread_monitoring_contention(flag != 0); case JMM_THREAD_CPU_TIME: return ThreadService::set_thread_cpu_time_enabled(flag != 0); + case JMM_THREAD_ALLOCATED_MEMORY: + return ThreadService::set_thread_allocated_memory_enabled(flag != 0); default: assert(0, "Unrecognized attribute"); return false; @@ -1096,6 +1133,7 @@ // maxDepth == 0 requests no stack trace. // infoArray - array of ThreadInfo objects // +// QQQ - Why does this method return a value instead of void? JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray)) // Check if threads is null if (ids == NULL || infoArray == NULL) { @@ -1159,7 +1197,6 @@ } } else { // obtain thread dump with the specific list of threads with stack trace - do_thread_dump(&dump_result, ids_ah, num_threads, @@ -1252,8 +1289,6 @@ continue; } - - ThreadStackTrace* stacktrace = ts->get_stack_trace(); assert(stacktrace != NULL, "Must have a stack trace dumped"); @@ -1500,6 +1535,49 @@ return -1; JVM_END +// Gets an array containing the CPU times consumed by a set of threads +// (in nanoseconds). Each element of the array is the CPU time for the +// thread ID specified in the corresponding entry in the given array +// of thread IDs; or -1 if the thread does not exist or has terminated. +// If user_sys_cpu_time = true, the sum of user level and system CPU time +// for the given thread is returned; otherwise, only user level CPU time +// is returned. +JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids, + jlongArray timeArray, + jboolean user_sys_cpu_time)) + // Check if threads is null + if (ids == NULL || timeArray == NULL) { + THROW(vmSymbols::java_lang_NullPointerException()); + } + + ResourceMark rm(THREAD); + typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); + typeArrayHandle ids_ah(THREAD, ta); + + typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray)); + typeArrayHandle timeArray_h(THREAD, tia); + + // validate the thread id array + validate_thread_id_array(ids_ah, CHECK); + + // timeArray must be of the same length as the given array of thread IDs + int num_threads = ids_ah->length(); + if (num_threads != timeArray_h->length()) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "The length of the given long array does not match the length of " + "the given array of thread IDs"); + } + + MutexLockerEx ml(Threads_lock); + for (int i = 0; i < num_threads; i++) { + JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i)); + if (java_thread != NULL) { + timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread, + user_sys_cpu_time != 0)); + } + } +JVM_END + // Returns a String array of all VM global flag names JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) // last flag entry is always NULL, so subtract 1 @@ -2020,7 +2098,7 @@ jmm_GetMemoryManagers, jmm_GetMemoryPoolUsage, jmm_GetPeakMemoryPoolUsage, - NULL, + jmm_GetThreadAllocatedMemory, jmm_GetMemoryUsage, jmm_GetLongAttribute, jmm_GetBoolAttribute, @@ -2038,7 +2116,7 @@ jmm_GetGCExtAttributeInfo, jmm_GetLastGCStat, jmm_GetThreadCpuTimeWithKind, - NULL, + jmm_GetThreadCpuTimesWithKind, jmm_DumpHeap0, jmm_FindDeadlockedThreads, jmm_SetVMGlobal,
--- a/hotspot/src/share/vm/services/threadService.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/services/threadService.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -46,6 +46,7 @@ // Default is disabled. bool ThreadService::_thread_monitoring_contention_enabled = false; bool ThreadService::_thread_cpu_time_enabled = false; +bool ThreadService::_thread_allocated_memory_enabled = false; PerfCounter* ThreadService::_total_threads_count = NULL; PerfVariable* ThreadService::_live_threads_count = NULL; @@ -84,6 +85,8 @@ if (os::is_thread_cpu_time_supported()) { _thread_cpu_time_enabled = true; } + + _thread_allocated_memory_enabled = true; // Always on, so enable it } void ThreadService::reset_peak_thread_count() { @@ -181,6 +184,15 @@ return prev; } +bool ThreadService::set_thread_allocated_memory_enabled(bool flag) { + MutexLocker m(Management_lock); + + bool prev = _thread_allocated_memory_enabled; + _thread_allocated_memory_enabled = flag; + + return prev; +} + // GC support void ThreadService::oops_do(OopClosure* f) { for (ThreadDumpResult* dump = _threaddump_list; dump != NULL; dump = dump->next()) {
--- a/hotspot/src/share/vm/services/threadService.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/services/threadService.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ -65,6 +65,7 @@ static bool _thread_monitoring_contention_enabled; static bool _thread_cpu_time_enabled; + static bool _thread_allocated_memory_enabled; // Need to keep the list of thread dump result that // keep references to methodOop since thread dump can be @@ -83,6 +84,9 @@ static bool set_thread_cpu_time_enabled(bool flag); static bool is_thread_cpu_time_enabled() { return _thread_cpu_time_enabled; } + static bool set_thread_allocated_memory_enabled(bool flag); + static bool is_thread_allocated_memory_enabled() { return _thread_cpu_time_enabled; } + static jlong get_total_thread_count() { return _total_threads_count->get_value(); } static jlong get_peak_thread_count() { return _peak_threads_count->get_value(); } static jlong get_live_thread_count() { return _live_threads_count->get_value() - _exiting_threads_count; }
--- a/hotspot/src/share/vm/utilities/debug.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/utilities/debug.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -226,7 +226,7 @@ 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
--- a/hotspot/src/share/vm/utilities/vmError.cpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Wed Jan 19 19:00:30 2011 -0800 @@ -67,7 +67,7 @@ // 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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();
--- a/hotspot/src/share/vm/utilities/vmError.hpp Mon Jan 17 13:29:12 2011 +0530 +++ b/hotspot/src/share/vm/utilities/vmError.hpp Wed Jan 19 19:00:30 2011 -0800 @@ -87,10 +87,12 @@ // 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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/6579789/Test6579789.java Wed Jan 19 19:00:30 2011 -0800 @@ -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++; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/7009231/Test7009231.java Wed Jan 19 19:00:30 2011 -0800 @@ -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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/7009359/Test7009359.java Wed Jan 19 19:00:30 2011 -0800 @@ -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"; + } + } +} +
--- a/jaxp/.hgtags Mon Jan 17 13:29:12 2011 +0530 +++ b/jaxp/.hgtags Wed Jan 19 19:00:30 2011 -0800 @@ -98,3 +98,5 @@ 63dae40fa19fd3bf4689ea2f3c1d9d690e1abcee jdk7-b121 03ff13d19c8fa983cbab6542930a7f352e9b5b33 jdk7-b122 e2aedea6495d61557326928de20dbb2d78fdd9aa jdk7-b123 +57ed1f3bec72924cdad102f9bf90f7449ea7bb83 jdk7-b124 +6c9bdee0cc3a8912acc5189cc092b8cba6851f9d jdk7-b125
--- a/jaxp/jaxp.properties Mon Jan 17 13:29:12 2011 +0530 +++ b/jaxp/jaxp.properties Wed Jan 19 19:00:30 2011 -0800 @@ -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
--- a/jaxws/.hgtags Mon Jan 17 13:29:12 2011 +0530 +++ b/jaxws/.hgtags Wed Jan 19 19:00:30 2011 -0800 @@ -98,3 +98,5 @@ 0fa950117faac7bdbc94e6c46b88f6f892031c17 jdk7-b121 17b6c48a344968880925dcef1178fec282feb335 jdk7-b122 5a8e43bcce56b7cd5576419067a929b74575ae71 jdk7-b123 +86f60e5b3975840968f3147ddce047a27a9fc83e jdk7-b124 +d72eea121c3bc2b649272a37b80d9417855b7146 jdk7-b125
--- a/jaxws/jaxws.properties Mon Jan 17 13:29:12 2011 +0530 +++ b/jaxws/jaxws.properties Wed Jan 19 19:00:30 2011 -0800 @@ -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
--- a/jdk/.hgtags Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/.hgtags Wed Jan 19 19:00:30 2011 -0800 @@ -98,3 +98,5 @@ a661d8587b5d8986aacae086f5df66af9e1a96b1 jdk7-b121 ac311eb325bfc763698219252bf3cee9e091f3af jdk7-b122 869190935eedee7750d955019ab2a1b80f0a13a8 jdk7-b123 +1c72adc9d5f331cb882cf5354ba0dcb118a60b23 jdk7-b124 +0a56bdd709d01c1663047e55201d19152ffd3d69 jdk7-b125
--- a/jdk/make/sun/Makefile Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/make/sun/Makefile Wed Jan 19 19:00:30 2011 -0800 @@ -42,7 +42,15 @@ 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
--- a/jdk/make/sun/awt/Makefile Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/make/sun/awt/Makefile Wed Jan 19 19:00:30 2011 -0800 @@ -175,6 +175,10 @@ 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 @@ $(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)
--- a/jdk/make/sun/awt/make.depend Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/make/sun/awt/make.depend Wed Jan 19 19:00:30 2011 -0800 @@ -224,7 +224,7 @@ $(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)/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)/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
--- a/jdk/make/sun/awt/mapfile-vers Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/make/sun/awt/mapfile-vers Wed Jan 19 19:00:30 2011 -0800 @@ -118,6 +118,8 @@ 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;
--- a/jdk/make/sun/awt/mapfile-vers-linux Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/make/sun/awt/mapfile-vers-linux Wed Jan 19 19:00:30 2011 -0800 @@ -115,6 +115,8 @@ 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;
--- a/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/make/tools/src/build/tools/javazic/Zoneinfo.java Wed Jan 19 19:00:30 2011 -0800 @@ -222,6 +222,7 @@ boolean continued = false; Zone zone = null; String l; + lineNum = 0; try { while ((line = in.readLine()) != null) {
--- a/jdk/src/share/classes/java/awt/SplashScreen.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/awt/SplashScreen.java Wed Jan 19 19:00:30 2011 -0800 @@ -33,27 +33,17 @@ 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). * <P> - * There are two ways to show the native splash screen: - * <P> - * <UL> - * <LI>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. - * <BR> - * For example: - * <PRE> - * java -splash:filename.gif Test - * </PRE> - * <LI>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 @@ * Main-Class: Test * SplashScreen-Image: filename.gif * </PRE> + * <P> + * 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. + * <BR> + * For example: + * <PRE> + * java -splash:filename.gif Test + * </PRE> * The command line interface has higher precedence over the manifest * setting. - * </UL> + * <p> + * 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. + * <p> + * 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.) * <p> * 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. * <p> * 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 <code>getSplashScreen</code> method returns <code>null</code>. @@ -91,7 +102,7 @@ /** * 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 @@ * <p> * You cannot control the size or position of the splash screen. * The splash screen size is adjusted automatically when the image changes. + * <p> + * 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 @@ * <p> * You cannot control the size or position of the splash screen. * The splash screen size is adjusted automatically when the image changes. + * <p> + * 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 @@ * screen window. You should call {@code update()} on the * <code>SplashScreen</code> when you want the splash screen to be * updated immediately. + * <p> + * 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 @@ * 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. + * <p> + * 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
--- a/jdk/src/share/classes/java/awt/font/NumericShaper.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/awt/font/NumericShaper.java Wed Jan 19 19:00:30 2011 -0800 @@ -58,20 +58,20 @@ * It is also possible to perform numeric shaping explicitly using instances * of <code>NumericShaper</code>, as this code snippet demonstrates:<br> * <blockquote><pre> - * 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); * </pre></blockquote> * * <p><b>Bit mask- and enum-based Unicode ranges</b></p> @@ -99,6 +99,37 @@ * values are specified, such as {@code NumericShaper.Range.BALINESE}, * those ranges are ignored. * + * <p><b>Decimal Digits Precedence</b></p> + * + * <p>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. + * + * <table border=1 cellspacing=3 cellpadding=0 summary="NumericShaper constants precedence."> + * <tr> + * <th class="TableHeadingColor">Unicode Range</th> + * <th class="TableHeadingColor"><code>NumericShaper</code> Constants</th> + * <th class="TableHeadingColor">Precedence</th> + * </tr> + * <tr> + * <td rowspan="2">Arabic</td> + * <td>{@link NumericShaper#ARABIC NumericShaper.ARABIC}<br> + * {@link NumericShaper#EASTERN_ARABIC NumericShaper.EASTERN_ARABIC}</td> + * <td>{@link NumericShaper#EASTERN_ARABIC NumericShaper.EASTERN_ARABIC}</td> + * </tr> + * <tr> + * <td>{@link NumericShaper.Range#ARABIC}<br> + * {@link NumericShaper.Range#EASTERN_ARABIC}</td> + * <td>{@link NumericShaper.Range#EASTERN_ARABIC}</td> + * </tr> + * <tr> + * <td>Tai Tham</td> + * <td>{@link NumericShaper.Range#TAI_THAM_HORA}<br> + * {@link NumericShaper.Range#TAI_THAM_THAM}</td> + * <td>{@link NumericShaper.Range#TAI_THAM_THAM}</td> + * </tr> + * </table> + * * @since 1.4 */
--- a/jdk/src/share/classes/java/awt/image/IndexColorModel.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/awt/image/IndexColorModel.java Wed Jan 19 19:00:30 2011 -0800 @@ -625,7 +625,7 @@ } nBits[0] = nBits[1] = nBits[2] = 8; } - return nBits; + return nBits.clone(); } /**
--- a/jdk/src/share/classes/java/awt/image/SampleModel.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/awt/image/SampleModel.java Wed Jan 19 19:00:30 2011 -0800 @@ -121,7 +121,7 @@ */ 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");
--- a/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java Wed Jan 19 19:00:30 2011 -0800 @@ -92,7 +92,8 @@ * 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 @@ * 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 @@ 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<numBands; i++) { int bitOffset = 0, bitSize = 0, mask; - mask = bitMasks[i]; - + this.bitMasks[i] &= maxMask; + mask = this.bitMasks[i]; if (mask != 0) { while ((mask & 1) == 0) { mask = mask >>> 1; @@ -243,30 +247,12 @@ /** 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<numBands; i++) { - sampleSize[i] = 0; - mask = bitMasks[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).
--- a/jdk/src/share/classes/java/text/MessageFormat.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/text/MessageFormat.java Wed Jan 19 19:00:30 2011 -0800 @@ -93,73 +93,65 @@ * currency * percent * <i>SubformatPattern</i> - * - * <i>String:</i> - * <i>StringPart<sub>opt</sub></i> - * <i>String</i> <i>StringPart</i> - * - * <i>StringPart:</i> - * '' - * ' <i>QuotedString</i> ' - * <i>UnquotedString</i> - * - * <i>SubformatPattern:</i> - * <i>SubformatPatternPart<sub>opt</sub></i> - * <i>SubformatPattern</i> <i>SubformatPatternPart</i> - * - * <i>SubFormatPatternPart:</i> - * ' <i>QuotedPattern</i> ' - * <i>UnquotedPattern</i> * </pre></blockquote> * - * <p> - * Within a <i>String</i>, <code>"''"</code> represents a single - * quote. A <i>QuotedString</i> can contain arbitrary characters - * except single quotes; the surrounding single quotes are removed. - * An <i>UnquotedString</i> 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 - * <code>"'''{'0}''"</code> or <code>"'''{0}'''"</code>. - * <p> - * Within a <i>SubformatPattern</i>, different rules apply. - * A <i>QuotedPattern</i> can contain arbitrary characters - * except single quotes; but the surrounding single quotes are - * <strong>not</strong> removed, so they may be interpreted by the - * subformat. For example, <code>"{1,number,$'#',##}"</code> will - * produce a number format with the pound-sign quoted, with a result - * such as: "$#31,45". - * An <i>UnquotedPattern</i> can contain arbitrary characters - * except single quotes, but curly braces within it must be balanced. - * For example, <code>"ab {0} de"</code> and <code>"ab '}' de"</code> - * are valid subformat patterns, but <code>"ab {0'}' de"</code> and - * <code>"ab } de"</code> are not. + * <p>Within a <i>String</i>, a pair of single quotes can be used to + * quote any arbitrary characters except single quotes. For example, + * pattern string <code>"'{0}'"</code> represents string + * <code>"{0}"</code>, not a <i>FormatElement</i>. A single quote itself + * must be represented by doubled single quotes {@code ''} throughout a + * <i>String</i>. For example, pattern string <code>"'{''}'"</code> is + * interpreted as a sequence of <code>'{</code> (start of quoting and a + * left curly brace), <code>''</code> (a single quote), and + * <code>}'</code> (a right curly brace and end of quoting), + * <em>not</em> <code>'{'</code> and <code>'}'</code> (quoted left and + * right curly braces): representing string <code>"{'}"</code>, + * <em>not</em> <code>"{}"</code>. + * + * <p>A <i>SubformatPattern</i> is interpreted by its corresponding + * subformat, and subformat-dependent pattern rules apply. For example, + * pattern string <code>"{1,number,<u>$'#',##</u>}"</code> + * (<i>SubformatPattern</i> 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. + * + * <p>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}'"}. + * + * <p>Any curly braces within an unquoted pattern must be balanced. For + * example, <code>"ab {0} de"</code> and <code>"ab '}' de"</code> are + * valid patterns, but <code>"ab {0'}' de"</code>, <code>"ab } de"</code> + * and <code>"''{''"</code> are not. + * * <p> * <dl><dt><b>Warning:</b><dd>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. * </dl> * <p> * The <i>ArgumentIndex</i> value is a non-negative integer written - * using the digits '0' through '9', and represents an index into the - * <code>arguments</code> array passed to the <code>format</code> methods - * or the result array returned by the <code>parse</code> 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. * <p> * The <i>FormatType</i> and <i>FormatStyle</i> values are used to create - * a <code>Format</code> 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 <i>SubformatPattern</i> must - * be a valid pattern string for the Format subclass used. + * be a valid pattern string for the {@code Format} subclass used. * <p> * <table border=1 summary="Shows how FormatType and FormatStyle values map to Format instances"> * <tr> - * <th id="ft">Format Type - * <th id="fs">Format Style - * <th id="sc">Subformat Created + * <th id="ft" class="TableHeadingColor">FormatType + * <th id="fs" class="TableHeadingColor">FormatStyle + * <th id="sc" class="TableHeadingColor">Subformat Created * <tr> * <td headers="ft"><i>(none)</i> * <td headers="fs"><i>(none)</i> @@ -167,61 +159,61 @@ * <tr> * <td headers="ft" rowspan=5><code>number</code> * <td headers="fs"><i>(none)</i> - * <td headers="sc"><code>NumberFormat.getInstance(getLocale())</code> + * <td headers="sc">{@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())} * <tr> * <td headers="fs"><code>integer</code> - * <td headers="sc"><code>NumberFormat.getIntegerInstance(getLocale())</code> + * <td headers="sc">{@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())} * <tr> * <td headers="fs"><code>currency</code> - * <td headers="sc"><code>NumberFormat.getCurrencyInstance(getLocale())</code> + * <td headers="sc">{@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())} * <tr> * <td headers="fs"><code>percent</code> - * <td headers="sc"><code>NumberFormat.getPercentInstance(getLocale())</code> + * <td headers="sc">{@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())} * <tr> * <td headers="fs"><i>SubformatPattern</i> - * <td headers="sc"><code>new DecimalFormat(subformatPattern, DecimalFormatSymbols.getInstance(getLocale()))</code> + * <td headers="sc">{@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))} * <tr> * <td headers="ft" rowspan=6><code>date</code> * <td headers="fs"><i>(none)</i> - * <td headers="sc"><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code> + * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * <tr> * <td headers="fs"><code>short</code> - * <td headers="sc"><code>DateFormat.getDateInstance(DateFormat.SHORT, getLocale())</code> + * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} * <tr> * <td headers="fs"><code>medium</code> - * <td headers="sc"><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code> + * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * <tr> * <td headers="fs"><code>long</code> - * <td headers="sc"><code>DateFormat.getDateInstance(DateFormat.LONG, getLocale())</code> + * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} * <tr> * <td headers="fs"><code>full</code> - * <td headers="sc"><code>DateFormat.getDateInstance(DateFormat.FULL, getLocale())</code> + * <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} * <tr> * <td headers="fs"><i>SubformatPattern</i> - * <td headers="sc"><code>new SimpleDateFormat(subformatPattern, getLocale())</code> + * <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} * <tr> * <td headers="ft" rowspan=6><code>time</code> * <td headers="fs"><i>(none)</i> - * <td headers="sc"><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code> + * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * <tr> * <td headers="fs"><code>short</code> - * <td headers="sc"><code>DateFormat.getTimeInstance(DateFormat.SHORT, getLocale())</code> + * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())} * <tr> * <td headers="fs"><code>medium</code> - * <td headers="sc"><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code> + * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())} * <tr> * <td headers="fs"><code>long</code> - * <td headers="sc"><code>DateFormat.getTimeInstance(DateFormat.LONG, getLocale())</code> + * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())} * <tr> * <td headers="fs"><code>full</code> - * <td headers="sc"><code>DateFormat.getTimeInstance(DateFormat.FULL, getLocale())</code> + * <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())} * <tr> * <td headers="fs"><i>SubformatPattern</i> - * <td headers="sc"><code>new SimpleDateFormat(subformatPattern, getLocale())</code> + * <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())} * <tr> * <td headers="ft"><code>choice</code> * <td headers="fs"><i>SubformatPattern</i> - * <td headers="sc"><code>new ChoiceFormat(subformatPattern)</code> + * <td headers="sc">{@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)} * </table> * <p> * @@ -321,7 +313,7 @@ * </pre></blockquote> * * <p> - * 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, * <blockquote><pre> @@ -343,7 +335,11 @@ * @see Format * @see NumberFormat * @see DecimalFormat + * @see DecimalFormatSymbols * @see ChoiceFormat + * @see DateFormat + * @see SimpleDateFormat + * * @author Mark Davis */ @@ -427,18 +423,19 @@ * @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) == '\'') { @@ -448,43 +445,61 @@ 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; + 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; } } } @@ -506,65 +521,57 @@ 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; + } } - } else if (formats[i] instanceof ChoiceFormat) { - result.append(",choice," - + ((ChoiceFormat)formats[i]).toPattern()); + 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 { //result.append(", unknown"); } @@ -678,7 +685,7 @@ * * @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) { @@ -972,7 +979,8 @@ 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) { @@ -1226,7 +1234,7 @@ 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); @@ -1338,25 +1346,83 @@ } } - 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 @@ -1374,120 +1440,129 @@ } 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); - break; - case 3: case 4:// percent - newFormat = NumberFormat.getPercentInstance(locale); - break; - case 5: case 6:// integer - newFormat = NumberFormat.getIntegerInstance(locale); - break; - default: // pattern - newFormat = new DecimalFormat(segments[3].toString(), DecimalFormatSymbols.getInstance(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; - } - 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); + + 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 3: case 4: // medium - newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, 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; - case 5: case 6: // long - newFormat = DateFormat.getDateInstance(DateFormat.LONG, locale); - break; - case 7: case 8: // full - newFormat = DateFormat.getDateInstance(DateFormat.FULL, locale); - break; + default: - newFormat = new SimpleDateFormat(segments[3].toString(), locale); - break; + maxOffset = oldMaxOffset; + throw new IllegalArgumentException("unknown format type: " + + segments[SEG_TYPE]); } - 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"); - } - 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('\''); + } } /**
--- a/jdk/src/share/classes/java/text/SimpleDateFormat.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/text/SimpleDateFormat.java Wed Jan 19 19:00:30 2011 -0800 @@ -1663,6 +1663,81 @@ } /** + * 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. * @param text the time text to be parsed. @@ -1907,248 +1982,95 @@ 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) { /* "GMT" without offset */ - calb.set(Calendar.ZONE_OFFSET, 0); - return pos.index; - } + 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(); - // 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; - } - - // 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; - } - 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; + 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; } - - // 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; + } else { + // Parse the rest as "hhmm" (RFC 822) + int i = subParseNumericZone(text, ++pos.index, + sign, 0, false, calb); + if (i > 0) { + return i; } - 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 ((text.length() - pos.index) <= 0) { + 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; - } + 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; } - // 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; + // 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;
--- a/jdk/src/share/classes/java/util/Locale.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/java/util/Locale.java Wed Jan 19 19:00:30 2011 -0800 @@ -1449,10 +1449,15 @@ * 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; }
--- a/jdk/src/share/classes/javax/print/attribute/standard/DialogTypeSelection.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/javax/print/attribute/standard/DialogTypeSelection.java Wed Jan 19 19:00:30 2011 -0800 @@ -52,6 +52,8 @@ public final class DialogTypeSelection extends EnumSyntax implements PrintRequestAttribute { + private static final long serialVersionUID = 7518682952133256029L; + /** * */
--- a/jdk/src/share/classes/javax/sound/midi/MidiSystem.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/javax/sound/midi/MidiSystem.java Wed Jan 19 19:00:30 2011 -0800 @@ -310,7 +310,7 @@ } else { transmitter = device.getTransmitter(); } - if (!(transmitter instanceof MidiDeviceReceiver)) { + if (!(transmitter instanceof MidiDeviceTransmitter)) { transmitter = new MidiDeviceTransmitterEnvelope(device, transmitter); } return transmitter;
--- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java Wed Jan 19 19:00:30 2011 -0800 @@ -359,7 +359,22 @@ 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 @@ 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(); }
--- a/jdk/src/share/classes/javax/swing/JSlider.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/javax/swing/JSlider.java Wed Jan 19 19:00:30 2011 -0800 @@ -40,7 +40,8 @@ /** * 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. * <p> * The slider can show both * major tick marks, and minor tick marks between the major ones. The number of
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSpinnerUI.java Wed Jan 19 19:00:30 2011 -0800 @@ -908,6 +908,14 @@ 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);
--- a/jdk/src/share/classes/sun/awt/FontConfiguration.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/awt/FontConfiguration.java Wed Jan 19 19:00:30 2011 -0800 @@ -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.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 @@ * 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 @@ if (verbose) { dump(); } - sanityCheck(); } //private static boolean loadingProperties; @@ -1343,6 +1344,11 @@ 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 @@ //componentFontNameID starts from "1" for (int ii = 1; ii < table_filenames.length; ii++) { if (table_filenames[ii] == -1) { - System.out.println("\n Warning: " - + "<filename." - + getString(table_componentFontNameIDs[ii]) - + "> 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: <filename." + + getString(table_componentFontNameIDs[ii]) + + "> 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 @@ 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 @@ script.contains("symbol")) { continue; } - System.out.println("\nError: " + System.err.println("\nError: " + "<awtfontpath." + script + "> entry is missing!!!"); @@ -1411,11 +1425,19 @@ } } 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 @@ -1652,20 +1674,16 @@ 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<String, Short> 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<String, Short> entry = (Entry <String, Short>)iterator.next(); - list[entry.getValue().shortValue()] = getStringID(entry.getKey()); + Arrays.fill(list, (short) -1); + for (Entry<String, Short> entry : map.entrySet()) { + list[entry.getValue()] = getStringID(entry.getKey()); } return list; } @@ -1763,25 +1781,19 @@ int len = table_scriptIDs.length + scriptFonts.size() * 20; table_scriptFonts = new short[len]; - Iterator iterator = scriptAllfonts.entrySet().iterator(); - while (iterator.hasNext()) { - Entry<Short, Short> entry = (Entry <Short, Short>)iterator.next(); - table_scriptFonts[entry.getKey().intValue()] = (short)entry.getValue().shortValue(); + for (Entry<Short, Short> entry : scriptAllfonts.entrySet()) { + table_scriptFonts[entry.getKey().intValue()] = entry.getValue(); } int off = table_scriptIDs.length; - iterator = scriptFonts.entrySet().iterator(); - while (iterator.hasNext()) { - Entry<Short, Short[]> entry = (Entry <Short, Short[]>)iterator.next(); + for (Entry<Short, Short[]> 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 @@ //(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<Short, short[]> entry = (Entry <Short, short[]>)iterator.next(); + for (Entry<Short, short[]> entry : sequences.entrySet()) { //table_sequences[entry.getKey().intValue()] = (short)-off; int k = entry.getKey().intValue(); short[] v = entry.getValue(); @@ -1827,31 +1837,24 @@ //(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<Short, Short> entry = (Entry <Short, Short>)iterator.next(); - table_filenames[entry.getKey().shortValue()] = entry.getValue().shortValue(); + Arrays.fill(table_filenames, (short) -1); + + for (Entry<Short, Short> 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<Short, Short> entry = (Entry <Short, Short>)iterator.next(); - table_awtfontpaths[entry.getKey().shortValue()] = entry.getValue().shortValue(); + for (Entry<Short, Short> 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<Short, int[]> entry = (Entry <Short, int[]>)iterator.next(); + for (Entry<Short, int[]> entry : exclusions.entrySet()) { int[] exI = entry.getValue(); char[] exC = new char[exI.length * 2]; int j = 0; @@ -1859,17 +1862,15 @@ 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<Short, Short> entry = (Entry <Short, Short>)iterator.next(); - table_proportionals[j++] = entry.getKey().shortValue(); - table_proportionals[j++] = entry.getValue().shortValue(); + for (Entry<Short, Short> 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 @@ len = table_scriptIDs.length + scriptFontsMotif.size() * 20; table_scriptFontsMotif = new short[len]; - iterator = scriptAllfontsMotif.entrySet().iterator(); - while (iterator.hasNext()) { - Entry<Short, Short> entry = (Entry <Short, Short>)iterator.next(); + for (Entry<Short, Short> 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<Short, Short[]> entry = (Entry <Short, Short[]>)iterator.next(); + for (Entry<Short, Short[]> 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 @@ //(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<Short, Short> entry = (Entry <Short, Short>)iterator.next(); - table_alphabeticSuffix[j++] = entry.getKey().shortValue(); - table_alphabeticSuffix[j++] = entry.getValue().shortValue(); + for (Entry<Short, Short> entry : alphabeticSuffix.entrySet()) { + table_alphabeticSuffix[j++] = entry.getKey(); + table_alphabeticSuffix[j++] = entry.getValue(); } //(15)short[] fallbackScriptIDs; just put the ID in head
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Wed Jan 19 19:00:30 2011 -0800 @@ -102,26 +102,6 @@ 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 @@ } }; - 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() {
--- a/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java Wed Jan 19 19:00:30 2011 -0800 @@ -635,6 +635,88 @@ 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();
--- a/jdk/src/share/classes/sun/font/FileFontStrike.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/font/FileFontStrike.java Wed Jan 19 19:00:30 2011 -0800 @@ -58,10 +58,10 @@ 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; + /* 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 @@ 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. @@ -522,32 +522,33 @@ } /* 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) {
--- a/jdk/src/share/classes/sun/font/Font2D.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/font/Font2D.java Wed Jan 19 19:00:30 2011 -0800 @@ -343,7 +343,21 @@ } 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);
--- a/jdk/src/share/classes/sun/java2d/SurfaceData.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/java2d/SurfaceData.java Wed Jan 19 19:00:30 2011 -0800 @@ -367,16 +367,17 @@ 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 @@ 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 @@ 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 @@ } } + 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 @@ 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 @@ 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 @@ 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 @@ 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,13 +634,17 @@ 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; - if (sg2d.paintState > sg2d.PAINT_OPAQUECOLOR || + PixelToParallelogramConverter converter = + (sg2d.alphafill.canDoParallelograms() + ? AAColorViaPgram + : AAColorViaShape); + sg2d.drawpipe = converter; + sg2d.fillpipe = converter; + sg2d.shapepipe = converter; + if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR || sg2d.compositeState > sg2d.COMP_ISCOPY) { sg2d.textpipe = colorText; @@ -634,12 +656,12 @@ 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 @@ } } + 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 @@ * 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 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);
--- a/jdk/src/share/classes/sun/java2d/loops/CompositeType.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/java2d/loops/CompositeType.java Wed Jan 19 19:00:30 2011 -0800 @@ -27,6 +27,7 @@ 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 @@ * the indicated algorithm if all of the more specific searches fail. */ public final class CompositeType { + + private static int unusedUID = 1; + private static final HashMap<String,Integer> compositeUIDMap = + new HashMap<String,Integer>(100); + /* * CONSTANTS USED BY ALL PRIMITIVES TO DESCRIBE THE COMPOSITING * ALGORITHMS THEY CAN PERFORM @@ -153,6 +159,22 @@ 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 @@ } } - private static int unusedUID = 1; private int uniqueID; private String desc; private CompositeType next; @@ -218,14 +239,20 @@ 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() {
--- a/jdk/src/share/classes/sun/java2d/loops/MaskFill.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/java2d/loops/MaskFill.java Wed Jan 19 19:00:30 2011 -0800 @@ -50,6 +50,10 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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(); + } } }
--- a/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/java2d/pipe/AAShapePipe.java Wed Jan 19 19:00:30 2011 -0800 @@ -28,6 +28,7 @@ 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 @@ * 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 @@ 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 @@ 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 @@ 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],
--- a/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/java2d/pipe/AlphaColorPipe.java Wed Jan 19 19:00:30 2011 -0800 @@ -34,7 +34,7 @@ * 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 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); + } }
--- a/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/java2d/pipe/RenderingEngine.java Wed Jan 19 19:00:30 2011 -0800 @@ -281,6 +281,72 @@ 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: + * <ul> + * <li> {@code x}, {@code y} + * <li> {@code x+dx1}, {@code y+dy1} + * <li> {@code x+dx1+dx2}, {@code y+dy1+dy2} + * <li> {@code x+dx2}, {@code y+dy2} + * </ul> + * 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. + * <p> + * 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: + * <pre> + * for (y = bbox[1]; y < bbox[3]; y += tileheight) { + * for (x = bbox[0]; x < bbox[2]; x += tilewidth) { + * } + * } + * </pre> + * 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. * @since 1.7 @@ -393,5 +459,24 @@ 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); + } } }
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java Wed Jan 19 19:00:30 2011 -0800 @@ -557,6 +557,69 @@ 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.
--- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c Wed Jan 19 19:00:30 2011 -0800 @@ -178,7 +178,7 @@ 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 @@ 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);
--- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h Wed Jan 19 19:00:30 2011 -0800 @@ -88,27 +88,18 @@ /* 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; - - rgbquad_t drb = srcrb - dstrb; - rgbquad_t dg = srcg - dstg; + const rgbquad_t a = alpha; + const rgbquad_t a1 = 0xFF - alpha; - 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.
--- a/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/native/sun/java2d/loops/DrawParallelogram.c Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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 @@ * 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 @@ 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 @@ // 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.
--- a/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/native/sun/java2d/loops/FillParallelogram.c Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ /* * 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);
--- a/jdk/src/share/native/sun/java2d/loops/MaskFill.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/native/sun/java2d/loops/MaskFill.c Wed Jan 19 19:00:30 2011 -0800 @@ -23,7 +23,11 @@ * questions. */ +#include <math.h> +#include <stdlib.h> +#include <string.h> #include "GraphicsPrimitiveMgr.h" +#include "ParallelogramUtils.h" #include "sun_java2d_loops_MaskFill.h" @@ -93,6 +97,967 @@ } } 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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/native/sun/java2d/loops/ParallelogramUtils.h Wed Jan 19 19:00:30 2011 -0800 @@ -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 */
--- a/jdk/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/share/native/sun/java2d/pipe/BufferedMaskBlit.c Wed Jan 19 19:00:30 2011 -0800 @@ -119,7 +119,8 @@ 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 @@ bpos += width * height * sizeof(jint); (*env)->ReleasePrimitiveArrayCritical(env, maskArray, - pMask, JNI_ABORT); + pMaskAlloc, JNI_ABORT); } SurfaceData_InvokeRelease(env, srcOps, &srcInfo); }
--- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c Wed Jan 19 19:00:30 2011 -0800 @@ -137,41 +137,43 @@ 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); }
--- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c Wed Jan 19 19:00:30 2011 -0800 @@ -32,6 +32,9 @@ #include <alsa/asoundlib.h> #include "PlatformMidi.h" #include "PLATFORM_API_LinuxOS_ALSA_MidiUtils.h" +#if defined(i586) +#include <sys/utsname.h> +#endif /* * Helper methods @@ -73,9 +76,38 @@ 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 -INT32 MIDI_IN_GetNumDevices() { TRACE0("MIDI_IN_GetNumDevices()\n"); + return getMidiDeviceCount(SND_RAWMIDI_STREAM_INPUT); }
--- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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;
--- a/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c Mon Jan 17 13:29:12 2011 +0530 +++ b/jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCM.c Wed Jan 19 19:00:30 2011 -0800 @@ -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 @@ 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 @@ } } 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 @@ 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 @@ } else { for (channels = minChannels; channels <= maxChannels; channels++) {