# HG changeset patch # User Omair Majid # Date 1372258033 14400 # Node ID c5297dd496dace6b4561ab0c729c3e07bac5057f # Parent f352f5c791049ce4ebc48af0e857840e7674e164 Fix patches to work with patch tools that can not handle renames 2013-06-26 Omair Majid * Makefile.am: (SECURITY_PATCHES): Add patches/openjdk/6990754-handle_renames.patch and patches/openjdk/6851834-handle_renames.patch * patches/openjdk/6990754-use_native_memory_for_symboltable.patch: Don't rename files using extended-diff-style. * patches/openjdk/6990754-handle_renames.patch: New file. Contains the rename portion of 6990754 since some patch programs can not handle renames. * patches/openjdk/6851834-restructure.patch: Don't rename files using extended-diff-style. * patches/openjdk/6851834-handle_renames.patch: New file. Contains rename porition of 6851834 since some patch programs can not handle renames. diff -r f352f5c79104 -r c5297dd496da ChangeLog --- a/ChangeLog Tue Jun 25 15:07:59 2013 +0100 +++ b/ChangeLog Wed Jun 26 10:47:13 2013 -0400 @@ -1,3 +1,18 @@ +2013-06-26 Omair Majid + + * Makefile.am: + (SECURITY_PATCHES): Add patches/openjdk/6990754-handle_renames.patch and + patches/openjdk/6851834-handle_renames.patch + * patches/openjdk/6990754-use_native_memory_for_symboltable.patch: Don't + rename files using extended-diff-style. + * patches/openjdk/6990754-handle_renames.patch: New file. Contains the + rename portion of 6990754 since some patch programs can not handle + renames. + * patches/openjdk/6851834-restructure.patch: Don't rename files using + extended-diff-style. + * patches/openjdk/6851834-handle_renames.patch: New file. Contains rename + porition of 6851834 since some patch programs can not handle renames. + 2013-06-24 Andrew John Hughes * Makefile.am: diff -r f352f5c79104 -r c5297dd496da Makefile.am --- a/Makefile.am Tue Jun 25 15:07:59 2013 +0100 +++ b/Makefile.am Wed Jun 26 10:47:13 2013 -0400 @@ -383,6 +383,7 @@ patches/openjdk/7036747-elfstringtable.patch \ patches/openjdk/7017732-move_static_fields_to_class.patch \ patches/openjdk/6990754-use_native_memory_for_symboltable.patch \ + patches/openjdk/6990754-handle_renames.patch \ patches/openjdk/7008809-report_class_in_arraystoreexception.patch \ patches/openjdk/7086585-flexible_field_injection.patch \ patches/security/20130618/hs_merge-01.patch \ @@ -398,6 +399,7 @@ patches/openjdk/6786688-wcag_table.patch \ patches/openjdk/6961178-doclet_xml.patch \ patches/openjdk/6851834-restructure.patch \ + patches/openjdk/6851834-handle_renames.patch \ patches/openjdk/7006270-regressions.patch \ patches/security/20130618/8012375-javadoc_framing.patch \ patches/security/20130618/8015997-more_javadoc_framing.patch \ diff -r f352f5c79104 -r c5297dd496da patches/openjdk/6851834-handle_renames.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/openjdk/6851834-handle_renames.patch Wed Jun 26 10:47:13 2013 -0400 @@ -0,0 +1,605 @@ +This handles the rename bits of the original 6851834 +diff -ruN openjdk.orig/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java +--- openjdk.orig/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java 1969-12-31 19:00:00.000000000 -0500 ++++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java 2013-06-25 14:55:45.802321034 -0400 +@@ -0,0 +1,298 @@ ++/* ++ * Copyright (c) 2001, 2006, 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. ++ */ ++ ++package com.sun.tools.doclets.formats.html; ++ ++import java.io.*; ++import javax.tools.FileObject; ++import com.sun.javadoc.*; ++import com.sun.tools.doclets.internal.toolkit.*; ++import com.sun.tools.doclets.internal.toolkit.util.*; ++import com.sun.tools.doclets.formats.html.markup.*; ++ ++/** ++ * Converts Java Source Code to HTML. ++ * ++ * This code is not part of an API. ++ * It is implementation that is subject to change. ++ * Do not use it as an API ++ * ++ * @author Jamie Ho ++ * @author Bhavesh Patel (Modified) ++ * @since 1.4 ++ */ ++public class SourceToHTMLConverter { ++ ++ /** ++ * The number of trailing blank lines at the end of the page. ++ * This is inserted so that anchors at the bottom of small pages ++ * can be reached. ++ */ ++ private static final int NUM_BLANK_LINES = 60; ++ ++ /** ++ * New line to be added to the documentation. ++ */ ++ private static final Content NEW_LINE = new RawHtml(DocletConstants.NL); ++ ++ /** ++ * Relative path from the documentation root to the file that is being ++ * generated. ++ */ ++ private static String relativePath = ""; ++ ++ /** ++ * Source is converted to HTML using static methods below. ++ */ ++ private SourceToHTMLConverter() {} ++ ++ /** ++ * Convert the Classes in the given RootDoc to an HTML. ++ * ++ * @param configuration the configuration. ++ * @param rd the RootDoc to convert. ++ * @param outputdir the name of the directory to output to. ++ */ ++ public static void convertRoot(ConfigurationImpl configuration, RootDoc rd, ++ String outputdir) { ++ if (rd == null || outputdir == null) { ++ return; ++ } ++ PackageDoc[] pds = rd.specifiedPackages(); ++ for (int i = 0; i < pds.length; i++) { ++ convertPackage(configuration, pds[i], outputdir); ++ } ++ ClassDoc[] cds = rd.specifiedClasses(); ++ for (int i = 0; i < cds.length; i++) { ++ convertClass(configuration, cds[i], ++ getPackageOutputDir(outputdir, cds[i].containingPackage())); ++ } ++ } ++ ++ /** ++ * Convert the Classes in the given Package to an HTML. ++ * ++ * @param configuration the configuration. ++ * @param pd the Package to convert. ++ * @param outputdir the name of the directory to output to. ++ */ ++ public static void convertPackage(ConfigurationImpl configuration, PackageDoc pd, ++ String outputdir) { ++ if (pd == null || outputdir == null) { ++ return; ++ } ++ String classOutputdir = getPackageOutputDir(outputdir, pd); ++ ClassDoc[] cds = pd.allClasses(); ++ for (int i = 0; i < cds.length; i++) { ++ convertClass(configuration, cds[i], classOutputdir); ++ } ++ } ++ ++ /** ++ * Return the directory write output to for the given package. ++ * ++ * @param outputDir the directory to output to. ++ * @param pd the Package to generate output for. ++ * @return the package output directory as a String. ++ */ ++ private static String getPackageOutputDir(String outputDir, PackageDoc pd) { ++ return outputDir + File.separator + ++ DirectoryManager.getDirectoryPath(pd) + File.separator; ++ } ++ ++ /** ++ * Convert the given Class to an HTML. ++ * ++ * @param configuration the configuration. ++ * @param cd the class to convert. ++ * @param outputdir the name of the directory to output to. ++ */ ++ public static void convertClass(ConfigurationImpl configuration, ClassDoc cd, ++ String outputdir) { ++ if (cd == null || outputdir == null) { ++ return; ++ } ++ try { ++ SourcePosition sp = cd.position(); ++ if (sp == null) ++ return; ++ Reader r; ++ // temp hack until we can update SourcePosition API. ++ if (sp instanceof com.sun.tools.javadoc.SourcePositionImpl) { ++ FileObject fo = ((com.sun.tools.javadoc.SourcePositionImpl) sp).fileObject(); ++ if (fo == null) ++ return; ++ r = fo.openReader(true); ++ } else { ++ File file = sp.file(); ++ if (file == null) ++ return; ++ r = new FileReader(file); ++ } ++ LineNumberReader reader = new LineNumberReader(r); ++ int lineno = 1; ++ String line; ++ relativePath = DirectoryManager.getRelativePath(DocletConstants.SOURCE_OUTPUT_DIR_NAME) + ++ DirectoryManager.getRelativePath(cd.containingPackage()); ++ Content body = getHeader(); ++ Content pre = new HtmlTree(HtmlTag.PRE); ++ try { ++ while ((line = reader.readLine()) != null) { ++ addLineNo(pre, lineno); ++ addLine(pre, line, configuration.sourcetab, lineno); ++ lineno++; ++ } ++ } finally { ++ reader.close(); ++ } ++ addBlankLines(pre); ++ Content div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre); ++ body.addContent(div); ++ writeToFile(body, outputdir, cd.name(), configuration); ++ } catch (Exception e){ ++ e.printStackTrace(); ++ } ++ } ++ ++ /** ++ * Write the output to the file. ++ * ++ * @param body the documentation content to be written to the file. ++ * @param outputDir the directory to output to. ++ * @param className the name of the class that I am converting to HTML. ++ * @param configuration the Doclet configuration to pass notices to. ++ */ ++ private static void writeToFile(Content body, String outputDir, ++ String className, ConfigurationImpl configuration) throws IOException { ++ Content htmlDocType = DocType.Transitional(); ++ Content head = new HtmlTree(HtmlTag.HEAD); ++ head.addContent(HtmlTree.TITLE(new StringContent( ++ configuration.getText("doclet.Window_Source_title")))); ++ head.addContent(getStyleSheetProperties(configuration)); ++ Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), ++ head, body); ++ Content htmlDocument = new HtmlDocument(htmlDocType, htmlTree); ++ File dir = new File(outputDir); ++ dir.mkdirs(); ++ File newFile = new File(dir, className + ".html"); ++ configuration.message.notice("doclet.Generating_0", newFile.getPath()); ++ FileOutputStream fout = new FileOutputStream(newFile); ++ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fout)); ++ bw.write(htmlDocument.toString()); ++ bw.close(); ++ fout.close(); ++ } ++ ++ /** ++ * Returns a link to the stylesheet file. ++ * ++ * @param configuration the doclet configuration for the current run of javadoc ++ * @return an HtmlTree for the lINK tag which provides the stylesheet location ++ */ ++ public static HtmlTree getStyleSheetProperties(ConfigurationImpl configuration) { ++ String filename = configuration.stylesheetfile; ++ if (filename.length() > 0) { ++ File stylefile = new File(filename); ++ String parent = stylefile.getParent(); ++ filename = (parent == null)? ++ filename: ++ filename.substring(parent.length() + 1); ++ } else { ++ filename = "stylesheet.css"; ++ } ++ filename = relativePath + filename; ++ HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", filename, "Style"); ++ return link; ++ } ++ ++ /** ++ * Get the header. ++ * ++ * @return the header content for the HTML file ++ */ ++ private static Content getHeader() { ++ return new HtmlTree(HtmlTag.BODY); ++ } ++ ++ /** ++ * Add the line numbers for the source code. ++ * ++ * @param pre the content tree to which the line number will be added ++ * @param lineno The line number ++ */ ++ private static void addLineNo(Content pre, int lineno) { ++ HtmlTree span = new HtmlTree(HtmlTag.SPAN); ++ span.addStyle(HtmlStyle.sourceLineNo); ++ if (lineno < 10) { ++ span.addContent("00" + Integer.toString(lineno)); ++ } else if (lineno < 100) { ++ span.addContent("0" + Integer.toString(lineno)); ++ } else { ++ span.addContent(Integer.toString(lineno)); ++ } ++ pre.addContent(span); ++ } ++ ++ /** ++ * Add a line from source to the HTML file that is generated. ++ * ++ * @param pre the content tree to which the line will be added. ++ * @param line the string to format. ++ * @param tabLength the number of spaces for each tab. ++ * @param currentLineNo the current number. ++ */ ++ private static void addLine(Content pre, String line, int tabLength, ++ int currentLineNo) { ++ if (line != null) { ++ StringBuffer lineBuffer = new StringBuffer(Util.escapeHtmlChars(line)); ++ Util.replaceTabs(tabLength, lineBuffer); ++ pre.addContent(new RawHtml(lineBuffer.toString())); ++ Content anchor = HtmlTree.A_NAME("line." + Integer.toString(currentLineNo)); ++ pre.addContent(anchor); ++ pre.addContent(NEW_LINE); ++ } ++ } ++ ++ /** ++ * Add trailing blank lines at the end of the page. ++ * ++ * @param pre the content tree to which the blank lines will be added. ++ */ ++ private static void addBlankLines(Content pre) { ++ for (int i = 0; i < NUM_BLANK_LINES; i++) { ++ pre.addContent(NEW_LINE); ++ } ++ } ++ ++ /** ++ * Given a Doc, return an anchor name for it. ++ * ++ * @param d the Doc to check. ++ * @return the name of the anchor. ++ */ ++ public static String getAnchorName(Doc d) { ++ return "line." + d.position().line(); ++ } ++} +diff -ruN openjdk.orig/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java +--- openjdk.orig/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java 2013-06-25 14:55:45.802321034 -0400 ++++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java 1969-12-31 19:00:00.000000000 -0500 +@@ -1,298 +0,0 @@ +-/* +- * Copyright (c) 2001, 2006, 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. +- */ +- +-package com.sun.tools.doclets.formats.html; +- +-import java.io.*; +-import javax.tools.FileObject; +-import com.sun.javadoc.*; +-import com.sun.tools.doclets.internal.toolkit.*; +-import com.sun.tools.doclets.internal.toolkit.util.*; +-import com.sun.tools.doclets.formats.html.markup.*; +- +-/** +- * Converts Java Source Code to HTML. +- * +- * This code is not part of an API. +- * It is implementation that is subject to change. +- * Do not use it as an API +- * +- * @author Jamie Ho +- * @author Bhavesh Patel (Modified) +- * @since 1.4 +- */ +-public class SourceToHTMLConverter { +- +- /** +- * The number of trailing blank lines at the end of the page. +- * This is inserted so that anchors at the bottom of small pages +- * can be reached. +- */ +- private static final int NUM_BLANK_LINES = 60; +- +- /** +- * New line to be added to the documentation. +- */ +- private static final Content NEW_LINE = new RawHtml(DocletConstants.NL); +- +- /** +- * Relative path from the documentation root to the file that is being +- * generated. +- */ +- private static String relativePath = ""; +- +- /** +- * Source is converted to HTML using static methods below. +- */ +- private SourceToHTMLConverter() {} +- +- /** +- * Convert the Classes in the given RootDoc to an HTML. +- * +- * @param configuration the configuration. +- * @param rd the RootDoc to convert. +- * @param outputdir the name of the directory to output to. +- */ +- public static void convertRoot(ConfigurationImpl configuration, RootDoc rd, +- String outputdir) { +- if (rd == null || outputdir == null) { +- return; +- } +- PackageDoc[] pds = rd.specifiedPackages(); +- for (int i = 0; i < pds.length; i++) { +- convertPackage(configuration, pds[i], outputdir); +- } +- ClassDoc[] cds = rd.specifiedClasses(); +- for (int i = 0; i < cds.length; i++) { +- convertClass(configuration, cds[i], +- getPackageOutputDir(outputdir, cds[i].containingPackage())); +- } +- } +- +- /** +- * Convert the Classes in the given Package to an HTML. +- * +- * @param configuration the configuration. +- * @param pd the Package to convert. +- * @param outputdir the name of the directory to output to. +- */ +- public static void convertPackage(ConfigurationImpl configuration, PackageDoc pd, +- String outputdir) { +- if (pd == null || outputdir == null) { +- return; +- } +- String classOutputdir = getPackageOutputDir(outputdir, pd); +- ClassDoc[] cds = pd.allClasses(); +- for (int i = 0; i < cds.length; i++) { +- convertClass(configuration, cds[i], classOutputdir); +- } +- } +- +- /** +- * Return the directory write output to for the given package. +- * +- * @param outputDir the directory to output to. +- * @param pd the Package to generate output for. +- * @return the package output directory as a String. +- */ +- private static String getPackageOutputDir(String outputDir, PackageDoc pd) { +- return outputDir + File.separator + +- DirectoryManager.getDirectoryPath(pd) + File.separator; +- } +- +- /** +- * Convert the given Class to an HTML. +- * +- * @param configuration the configuration. +- * @param cd the class to convert. +- * @param outputdir the name of the directory to output to. +- */ +- public static void convertClass(ConfigurationImpl configuration, ClassDoc cd, +- String outputdir) { +- if (cd == null || outputdir == null) { +- return; +- } +- try { +- SourcePosition sp = cd.position(); +- if (sp == null) +- return; +- Reader r; +- // temp hack until we can update SourcePosition API. +- if (sp instanceof com.sun.tools.javadoc.SourcePositionImpl) { +- FileObject fo = ((com.sun.tools.javadoc.SourcePositionImpl) sp).fileObject(); +- if (fo == null) +- return; +- r = fo.openReader(true); +- } else { +- File file = sp.file(); +- if (file == null) +- return; +- r = new FileReader(file); +- } +- LineNumberReader reader = new LineNumberReader(r); +- int lineno = 1; +- String line; +- relativePath = DirectoryManager.getRelativePath(DocletConstants.SOURCE_OUTPUT_DIR_NAME) + +- DirectoryManager.getRelativePath(cd.containingPackage()); +- Content body = getHeader(); +- Content pre = new HtmlTree(HtmlTag.PRE); +- try { +- while ((line = reader.readLine()) != null) { +- addLineNo(pre, lineno); +- addLine(pre, line, configuration.sourcetab, lineno); +- lineno++; +- } +- } finally { +- reader.close(); +- } +- addBlankLines(pre); +- Content div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre); +- body.addContent(div); +- writeToFile(body, outputdir, cd.name(), configuration); +- } catch (Exception e){ +- e.printStackTrace(); +- } +- } +- +- /** +- * Write the output to the file. +- * +- * @param body the documentation content to be written to the file. +- * @param outputDir the directory to output to. +- * @param className the name of the class that I am converting to HTML. +- * @param configuration the Doclet configuration to pass notices to. +- */ +- private static void writeToFile(Content body, String outputDir, +- String className, ConfigurationImpl configuration) throws IOException { +- Content htmlDocType = DocType.Transitional(); +- Content head = new HtmlTree(HtmlTag.HEAD); +- head.addContent(HtmlTree.TITLE(new StringContent( +- configuration.getText("doclet.Window_Source_title")))); +- head.addContent(getStyleSheetProperties(configuration)); +- Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), +- head, body); +- Content htmlDocument = new HtmlDocument(htmlDocType, htmlTree); +- File dir = new File(outputDir); +- dir.mkdirs(); +- File newFile = new File(dir, className + ".html"); +- configuration.message.notice("doclet.Generating_0", newFile.getPath()); +- FileOutputStream fout = new FileOutputStream(newFile); +- BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fout)); +- bw.write(htmlDocument.toString()); +- bw.close(); +- fout.close(); +- } +- +- /** +- * Returns a link to the stylesheet file. +- * +- * @param configuration the doclet configuration for the current run of javadoc +- * @return an HtmlTree for the lINK tag which provides the stylesheet location +- */ +- public static HtmlTree getStyleSheetProperties(ConfigurationImpl configuration) { +- String filename = configuration.stylesheetfile; +- if (filename.length() > 0) { +- File stylefile = new File(filename); +- String parent = stylefile.getParent(); +- filename = (parent == null)? +- filename: +- filename.substring(parent.length() + 1); +- } else { +- filename = "stylesheet.css"; +- } +- filename = relativePath + filename; +- HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", filename, "Style"); +- return link; +- } +- +- /** +- * Get the header. +- * +- * @return the header content for the HTML file +- */ +- private static Content getHeader() { +- return new HtmlTree(HtmlTag.BODY); +- } +- +- /** +- * Add the line numbers for the source code. +- * +- * @param pre the content tree to which the line number will be added +- * @param lineno The line number +- */ +- private static void addLineNo(Content pre, int lineno) { +- HtmlTree span = new HtmlTree(HtmlTag.SPAN); +- span.addStyle(HtmlStyle.sourceLineNo); +- if (lineno < 10) { +- span.addContent("00" + Integer.toString(lineno)); +- } else if (lineno < 100) { +- span.addContent("0" + Integer.toString(lineno)); +- } else { +- span.addContent(Integer.toString(lineno)); +- } +- pre.addContent(span); +- } +- +- /** +- * Add a line from source to the HTML file that is generated. +- * +- * @param pre the content tree to which the line will be added. +- * @param line the string to format. +- * @param tabLength the number of spaces for each tab. +- * @param currentLineNo the current number. +- */ +- private static void addLine(Content pre, String line, int tabLength, +- int currentLineNo) { +- if (line != null) { +- StringBuffer lineBuffer = new StringBuffer(Util.escapeHtmlChars(line)); +- Util.replaceTabs(tabLength, lineBuffer); +- pre.addContent(new RawHtml(lineBuffer.toString())); +- Content anchor = HtmlTree.A_NAME("line." + Integer.toString(currentLineNo)); +- pre.addContent(anchor); +- pre.addContent(NEW_LINE); +- } +- } +- +- /** +- * Add trailing blank lines at the end of the page. +- * +- * @param pre the content tree to which the blank lines will be added. +- */ +- private static void addBlankLines(Content pre) { +- for (int i = 0; i < NUM_BLANK_LINES; i++) { +- pre.addContent(NEW_LINE); +- } +- } +- +- /** +- * Given a Doc, return an anchor name for it. +- * +- * @param d the Doc to check. +- * @return the name of the anchor. +- */ +- public static String getAnchorName(Doc d) { +- return "line." + d.position().line(); +- } +-} diff -r f352f5c79104 -r c5297dd496da patches/openjdk/6851834-restructure.patch --- a/patches/openjdk/6851834-restructure.patch Tue Jun 25 15:07:59 2013 +0100 +++ b/patches/openjdk/6851834-restructure.patch Wed Jun 26 10:47:13 2013 -0400 @@ -3,6 +3,7 @@ # Date 1371730814 18000 # Node ID 5761891cfee48bc9382dd68e5e1bf164cff9bfbf # Parent 741c190d6989de395cb95895dc0320415af6b131 +# PLEASE SEE the other 6851834 patch which handles renames more generally 6851834: Javadoc doclet needs a structured approach to generate the output HTML. Reviewed-by: jjg @@ -11287,8 +11288,9 @@ } } diff --git a/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java b/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java -rename from src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java -rename to src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java +# most patch programs can not handle renames +# rename from src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java +# rename to src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java --- openjdk/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java +++ openjdk/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java @@ -23,14 +23,14 @@ diff -r f352f5c79104 -r c5297dd496da patches/openjdk/6990754-handle_renames.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/openjdk/6990754-handle_renames.patch Wed Jun 26 10:47:13 2013 -0400 @@ -0,0 +1,925 @@ +This handles the rename bits of the original 6990754 +diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbol.cpp openjdk/hotspot/src/share/vm/oops/symbol.cpp +--- openjdk.orig/hotspot/src/share/vm/oops/symbol.cpp 1969-12-31 19:00:00.000000000 -0500 ++++ openjdk/hotspot/src/share/vm/oops/symbol.cpp 2013-06-25 14:49:37.268431428 -0400 +@@ -0,0 +1,231 @@ ++/* ++ * Copyright (c) 1997, 2009, 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. ++ * ++ */ ++ ++ ++#include "precompiled.hpp" ++#include "oops/oop.inline.hpp" ++#include "oops/symbol.hpp" ++#include "runtime/os.hpp" ++#include "memory/allocation.inline.hpp" ++ ++Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) { ++ _identity_hash = os::random(); ++ for (int i = 0; i < _length; i++) { ++ byte_at_put(i, name[i]); ++ } ++} ++ ++void* Symbol::operator new(size_t size, int len) { ++ return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol"); ++} ++ ++// ------------------------------------------------------------------ ++// Symbol::equals ++// ++// Compares the symbol with a string of the given length. ++bool Symbol::equals(const char* str, int len) const { ++ int l = utf8_length(); ++ if (l != len) return false; ++ while (l-- > 0) { ++ if (str[l] != (char) byte_at(l)) ++ return false; ++ } ++ assert(l == -1, "we should be at the beginning"); ++ return true; ++} ++ ++ ++// ------------------------------------------------------------------ ++// Symbol::starts_with ++// ++// Tests if the symbol starts with the specified prefix of the given ++// length. ++bool Symbol::starts_with(const char* prefix, int len) const { ++ if (len > utf8_length()) return false; ++ while (len-- > 0) { ++ if (prefix[len] != (char) byte_at(len)) ++ return false; ++ } ++ assert(len == -1, "we should be at the beginning"); ++ return true; ++} ++ ++ ++// ------------------------------------------------------------------ ++// Symbol::index_of ++// ++// Finds if the given string is a substring of this symbol's utf8 bytes. ++// Return -1 on failure. Otherwise return the first index where str occurs. ++int Symbol::index_of_at(int i, const char* str, int len) const { ++ assert(i >= 0 && i <= utf8_length(), "oob"); ++ if (len <= 0) return 0; ++ char first_char = str[0]; ++ address bytes = (address) ((Symbol*)this)->base(); ++ address limit = bytes + utf8_length() - len; // inclusive limit ++ address scan = bytes + i; ++ if (scan > limit) ++ return -1; ++ for (;;) { ++ scan = (address) memchr(scan, first_char, (limit + 1 - scan)); ++ if (scan == NULL) ++ return -1; // not found ++ assert(scan >= bytes+i && scan <= limit, "scan oob"); ++ if (memcmp(scan, str, len) == 0) ++ return (int)(scan - bytes); ++ } ++} ++ ++ ++char* Symbol::as_C_string(char* buf, int size) const { ++ if (size > 0) { ++ int len = MIN2(size - 1, utf8_length()); ++ for (int i = 0; i < len; i++) { ++ buf[i] = byte_at(i); ++ } ++ buf[len] = '\0'; ++ } ++ return buf; ++} ++ ++char* Symbol::as_C_string() const { ++ int len = utf8_length(); ++ char* str = NEW_RESOURCE_ARRAY(char, len + 1); ++ return as_C_string(str, len + 1); ++} ++ ++char* Symbol::as_C_string_flexible_buffer(Thread* t, ++ char* buf, int size) const { ++ char* str; ++ int len = utf8_length(); ++ int buf_len = len + 1; ++ if (size < buf_len) { ++ str = NEW_RESOURCE_ARRAY(char, buf_len); ++ } else { ++ str = buf; ++ } ++ return as_C_string(str, buf_len); ++} ++ ++void Symbol::print_symbol_on(outputStream* st) const { ++ st = st ? st : tty; ++ int length = UTF8::unicode_length((const char*)bytes(), utf8_length()); ++ const char *ptr = (const char *)bytes(); ++ jchar value; ++ for (int index = 0; index < length; index++) { ++ ptr = UTF8::next(ptr, &value); ++ if (value >= 32 && value < 127 || value == '\'' || value == '\\') { ++ st->put(value); ++ } else { ++ st->print("\\u%04x", value); ++ } ++ } ++} ++ ++jchar* Symbol::as_unicode(int& length) const { ++ Symbol* this_ptr = (Symbol*)this; ++ length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length()); ++ jchar* result = NEW_RESOURCE_ARRAY(jchar, length); ++ if (length > 0) { ++ UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length); ++ } ++ return result; ++} ++ ++const char* Symbol::as_klass_external_name(char* buf, int size) const { ++ if (size > 0) { ++ char* str = as_C_string(buf, size); ++ int length = (int)strlen(str); ++ // Turn all '/'s into '.'s (also for array klasses) ++ for (int index = 0; index < length; index++) { ++ if (str[index] == '/') { ++ str[index] = '.'; ++ } ++ } ++ return str; ++ } else { ++ return buf; ++ } ++} ++ ++const char* Symbol::as_klass_external_name() const { ++ char* str = as_C_string(); ++ int length = (int)strlen(str); ++ // Turn all '/'s into '.'s (also for array klasses) ++ for (int index = 0; index < length; index++) { ++ if (str[index] == '/') { ++ str[index] = '.'; ++ } ++ } ++ return str; ++} ++ ++ ++void Symbol::print_on(outputStream* st) const { ++ if (this == NULL) { ++ st->print_cr("NULL"); ++ } else { ++ st->print("Symbol: '"); ++ print_symbol_on(st); ++ st->print("'"); ++ st->print(" count %d", refcount()); ++ } ++} ++ ++// The print_value functions are present in all builds, to support the ++// disassembler and error reporting. ++void Symbol::print_value_on(outputStream* st) const { ++ if (this == NULL) { ++ st->print("NULL"); ++ } else { ++ st->print("'"); ++ for (int i = 0; i < utf8_length(); i++) { ++ st->print("%c", byte_at(i)); ++ } ++ st->print("'"); ++ } ++} ++ ++void Symbol::increment_refcount() { ++ // Only increment the refcount if positive. If negative either ++ // overflow has occurred or it is a permanent symbol in a read only ++ // shared archive. ++ if (_refcount >= 0) { ++ Atomic::inc(&_refcount); ++ NOT_PRODUCT(Atomic::inc(&_total_count);) ++ } ++} ++ ++void Symbol::decrement_refcount() { ++ if (_refcount >= 0) { ++ Atomic::dec(&_refcount); ++#ifdef ASSERT ++ if (_refcount < 0) { ++ print(); ++ assert(false, "reference count underflow for symbol"); ++ } ++#endif ++ } ++} ++ ++NOT_PRODUCT(int Symbol::_total_count = 0;) +diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbol.hpp openjdk/hotspot/src/share/vm/oops/symbol.hpp +--- openjdk.orig/hotspot/src/share/vm/oops/symbol.hpp 1969-12-31 19:00:00.000000000 -0500 ++++ openjdk/hotspot/src/share/vm/oops/symbol.hpp 2013-06-25 14:49:37.269431439 -0400 +@@ -0,0 +1,223 @@ ++/* ++ * Copyright (c) 1997, 2009, 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. ++ * ++ */ ++ ++#ifndef SHARE_VM_OOPS_SYMBOL_HPP ++#define SHARE_VM_OOPS_SYMBOL_HPP ++ ++#include "utilities/utf8.hpp" ++#include "memory/allocation.hpp" ++ ++// A Symbol is a canonicalized string. ++// All Symbols reside in global SymbolTable and are reference counted. ++ ++// Reference counting ++// ++// All Symbols are allocated and added to the SymbolTable. ++// When a class is unloaded, the reference counts of the Symbol pointers in ++// the ConstantPool and in instanceKlass (see release_C_heap_structures) are ++// decremented. When the reference count for a Symbol goes to 0, the garbage ++// collector can free the Symbol and remove it from the SymbolTable. ++// ++// 0) Symbols need to be reference counted when a pointer to the Symbol is ++// saved in persistent storage. This does not include the pointer ++// in the SymbolTable bucket (the _literal field in HashtableEntry) ++// that points to the Symbol. All other stores of a Symbol* ++// to a field of a persistent variable (e.g., the _name filed in ++// FieldAccessInfo or _ptr in a CPSlot) is reference counted. ++// ++// 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for ++// "name" and returns a pointer to F or finds a pre-existing Symbol F for ++// "name" and returns a pointer to it. In both cases the reference count for F ++// is incremented under the assumption that a pointer to F will be created from ++// the return value. Thus the increment of the reference count is on the lookup ++// and not on the assignment to the new Symbol*. That is ++// Symbol* G = lookup() ++// ^ increment on lookup() ++// and not ++// Symbol* G = lookup() ++// ^ increment on assignmnet ++// The reference count must be decremented manually when the copy of the ++// pointer G is destroyed. ++// ++// 2) For a local Symbol* A that is a copy of an existing Symbol* B, the ++// reference counting is elided when the scope of B is greater than the scope ++// of A. For example, in the code fragment ++// below "klass" is passed as a parameter to the method. Symbol* "kn" ++// is a copy of the name in "klass". ++// ++// Symbol* kn = klass->name(); ++// unsigned int d_hash = dictionary()->compute_hash(kn, class_loader); ++// ++// The scope of "klass" is greater than the scope of "kn" so the reference ++// counting for "kn" is elided. ++// ++// Symbol* copied from ConstantPool entries are good candidates for reference ++// counting elision. The ConstantPool entries for a class C exist until C is ++// unloaded. If a Symbol* is copied out of the ConstantPool into Symbol* X, ++// the Symbol* in the ConstantPool will in general out live X so the reference ++// counting on X can be elided. ++// ++// For cases where the scope of A is not greater than the scope of B, ++// the reference counting is explicitly done. See ciSymbol, ++// ResolutionErrorEntry and ClassVerifier for examples. ++// ++// 3) When a Symbol K is created for temporary use, generally for substrings of ++// an existing symbol or to create a new symbol, assign it to a ++// TempNewSymbol. The SymbolTable methods new_symbol(), lookup() ++// and probe() all potentially return a pointer to a new Symbol. ++// The allocation (or lookup) of K increments the reference count for K ++// and the destructor decrements the reference count. ++// ++// Another example of TempNewSymbol usage is parsed_name used in ++// ClassFileParser::parseClassFile() where parsed_name is used in the cleanup ++// after a failed attempt to load a class. Here parsed_name is a ++// TempNewSymbol (passed in as a parameter) so the reference count on its symbol ++// will be decremented when it goes out of scope. ++ ++class Symbol : public CHeapObj { ++ friend class VMStructs; ++ friend class SymbolTable; ++ friend class MoveSymbols; ++ private: ++ volatile int _refcount; ++ int _identity_hash; ++ unsigned short _length; // number of UTF8 characters in the symbol ++ jbyte _body[1]; ++ ++ enum { ++ // max_symbol_length is constrained by type of _length ++ max_symbol_length = (1 << 16) -1 ++ }; ++ ++ static int object_size(int length) { ++ size_t size = heap_word_size(sizeof(Symbol) + length); ++ return align_object_size(size); ++ } ++ ++ void byte_at_put(int index, int value) { ++ assert(index >=0 && index < _length, "symbol index overflow"); ++ _body[index] = value; ++ } ++ ++ Symbol(const u1* name, int length); ++ void* operator new(size_t size, int len); ++ ++ public: ++ // Low-level access (used with care, since not GC-safe) ++ const jbyte* base() const { return &_body[0]; } ++ ++ int object_size() { return object_size(utf8_length()); } ++ ++ // Returns the largest size symbol we can safely hold. ++ static int max_length() { ++ return max_symbol_length; ++ } ++ ++ int identity_hash() { ++ return _identity_hash; ++ } ++ ++ // Reference counting. See comments above this class for when to use. ++ int refcount() const { return _refcount; } ++ void increment_refcount(); ++ void decrement_refcount(); ++ ++ int byte_at(int index) const { ++ assert(index >=0 && index < _length, "symbol index overflow"); ++ return base()[index]; ++ } ++ ++ const jbyte* bytes() const { return base(); } ++ ++ int utf8_length() const { return _length; } ++ ++ // Compares the symbol with a string. ++ bool equals(const char* str, int len) const; ++ bool equals(const char* str) const { return equals(str, (int) strlen(str)); } ++ ++ // Tests if the symbol starts with the given prefix. ++ bool starts_with(const char* prefix, int len) const; ++ bool starts_with(const char* prefix) const { ++ return starts_with(prefix, (int) strlen(prefix)); ++ } ++ ++ // Tests if the symbol starts with the given prefix. ++ int index_of_at(int i, const char* str, int len) const; ++ int index_of_at(int i, const char* str) const { ++ return index_of_at(i, str, (int) strlen(str)); ++ } ++ ++ // Three-way compare for sorting; returns -1/0/1 if receiver is than arg ++ // note that the ordering is not alfabetical ++ inline int fast_compare(Symbol* other) const; ++ ++ // Returns receiver converted to null-terminated UTF-8 string; string is ++ // allocated in resource area, or in the char buffer provided by caller. ++ char* as_C_string() const; ++ char* as_C_string(char* buf, int size) const; ++ // Use buf if needed buffer length is <= size. ++ char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const; ++ ++ ++ // Returns a null terminated utf8 string in a resource array ++ char* as_utf8() const { return as_C_string(); } ++ char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const { ++ return as_C_string_flexible_buffer(t, buf, size); ++ } ++ ++ jchar* as_unicode(int& length) const; ++ ++ // Treating this symbol as a class name, returns the Java name for the class. ++ // String is allocated in resource area if buffer is not provided. ++ // See Klass::external_name() ++ const char* as_klass_external_name() const; ++ const char* as_klass_external_name(char* buf, int size) const; ++ ++ // Printing ++ void print_symbol_on(outputStream* st = NULL) const; ++ void print_on(outputStream* st) const; // First level print ++ void print_value_on(outputStream* st) const; // Second level print. ++ ++ // printing on default output stream ++ void print() { print_on(tty); } ++ void print_value() { print_value_on(tty); } ++ ++#ifndef PRODUCT ++ // Empty constructor to create a dummy symbol object on stack ++ // only for getting its vtable pointer. ++ Symbol() { } ++ ++ static int _total_count; ++#endif ++}; ++ ++// Note: this comparison is used for vtable sorting only; it doesn't matter ++// what order it defines, as long as it is a total, time-invariant order ++// Since Symbol*s are in C_HEAP, their relative order in memory never changes, ++// so use address comparison for speed ++int Symbol::fast_compare(Symbol* other) const { ++ return (((uintptr_t)this < (uintptr_t)other) ? -1 ++ : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1); ++} ++#endif // SHARE_VM_OOPS_SYMBOL_HPP +diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbolOop.cpp openjdk/hotspot/src/share/vm/oops/symbolOop.cpp +--- openjdk.orig/hotspot/src/share/vm/oops/symbolOop.cpp 2013-06-25 14:49:37.268431428 -0400 ++++ openjdk/hotspot/src/share/vm/oops/symbolOop.cpp 1969-12-31 19:00:00.000000000 -0500 +@@ -1,231 +0,0 @@ +-/* +- * Copyright (c) 1997, 2009, 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. +- * +- */ +- +- +-#include "precompiled.hpp" +-#include "oops/oop.inline.hpp" +-#include "oops/symbol.hpp" +-#include "runtime/os.hpp" +-#include "memory/allocation.inline.hpp" +- +-Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) { +- _identity_hash = os::random(); +- for (int i = 0; i < _length; i++) { +- byte_at_put(i, name[i]); +- } +-} +- +-void* Symbol::operator new(size_t size, int len) { +- return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol"); +-} +- +-// ------------------------------------------------------------------ +-// Symbol::equals +-// +-// Compares the symbol with a string of the given length. +-bool Symbol::equals(const char* str, int len) const { +- int l = utf8_length(); +- if (l != len) return false; +- while (l-- > 0) { +- if (str[l] != (char) byte_at(l)) +- return false; +- } +- assert(l == -1, "we should be at the beginning"); +- return true; +-} +- +- +-// ------------------------------------------------------------------ +-// Symbol::starts_with +-// +-// Tests if the symbol starts with the specified prefix of the given +-// length. +-bool Symbol::starts_with(const char* prefix, int len) const { +- if (len > utf8_length()) return false; +- while (len-- > 0) { +- if (prefix[len] != (char) byte_at(len)) +- return false; +- } +- assert(len == -1, "we should be at the beginning"); +- return true; +-} +- +- +-// ------------------------------------------------------------------ +-// Symbol::index_of +-// +-// Finds if the given string is a substring of this symbol's utf8 bytes. +-// Return -1 on failure. Otherwise return the first index where str occurs. +-int Symbol::index_of_at(int i, const char* str, int len) const { +- assert(i >= 0 && i <= utf8_length(), "oob"); +- if (len <= 0) return 0; +- char first_char = str[0]; +- address bytes = (address) ((Symbol*)this)->base(); +- address limit = bytes + utf8_length() - len; // inclusive limit +- address scan = bytes + i; +- if (scan > limit) +- return -1; +- for (;;) { +- scan = (address) memchr(scan, first_char, (limit + 1 - scan)); +- if (scan == NULL) +- return -1; // not found +- assert(scan >= bytes+i && scan <= limit, "scan oob"); +- if (memcmp(scan, str, len) == 0) +- return (int)(scan - bytes); +- } +-} +- +- +-char* Symbol::as_C_string(char* buf, int size) const { +- if (size > 0) { +- int len = MIN2(size - 1, utf8_length()); +- for (int i = 0; i < len; i++) { +- buf[i] = byte_at(i); +- } +- buf[len] = '\0'; +- } +- return buf; +-} +- +-char* Symbol::as_C_string() const { +- int len = utf8_length(); +- char* str = NEW_RESOURCE_ARRAY(char, len + 1); +- return as_C_string(str, len + 1); +-} +- +-char* Symbol::as_C_string_flexible_buffer(Thread* t, +- char* buf, int size) const { +- char* str; +- int len = utf8_length(); +- int buf_len = len + 1; +- if (size < buf_len) { +- str = NEW_RESOURCE_ARRAY(char, buf_len); +- } else { +- str = buf; +- } +- return as_C_string(str, buf_len); +-} +- +-void Symbol::print_symbol_on(outputStream* st) const { +- st = st ? st : tty; +- int length = UTF8::unicode_length((const char*)bytes(), utf8_length()); +- const char *ptr = (const char *)bytes(); +- jchar value; +- for (int index = 0; index < length; index++) { +- ptr = UTF8::next(ptr, &value); +- if (value >= 32 && value < 127 || value == '\'' || value == '\\') { +- st->put(value); +- } else { +- st->print("\\u%04x", value); +- } +- } +-} +- +-jchar* Symbol::as_unicode(int& length) const { +- Symbol* this_ptr = (Symbol*)this; +- length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length()); +- jchar* result = NEW_RESOURCE_ARRAY(jchar, length); +- if (length > 0) { +- UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length); +- } +- return result; +-} +- +-const char* Symbol::as_klass_external_name(char* buf, int size) const { +- if (size > 0) { +- char* str = as_C_string(buf, size); +- int length = (int)strlen(str); +- // Turn all '/'s into '.'s (also for array klasses) +- for (int index = 0; index < length; index++) { +- if (str[index] == '/') { +- str[index] = '.'; +- } +- } +- return str; +- } else { +- return buf; +- } +-} +- +-const char* Symbol::as_klass_external_name() const { +- char* str = as_C_string(); +- int length = (int)strlen(str); +- // Turn all '/'s into '.'s (also for array klasses) +- for (int index = 0; index < length; index++) { +- if (str[index] == '/') { +- str[index] = '.'; +- } +- } +- return str; +-} +- +- +-void Symbol::print_on(outputStream* st) const { +- if (this == NULL) { +- st->print_cr("NULL"); +- } else { +- st->print("Symbol: '"); +- print_symbol_on(st); +- st->print("'"); +- st->print(" count %d", refcount()); +- } +-} +- +-// The print_value functions are present in all builds, to support the +-// disassembler and error reporting. +-void Symbol::print_value_on(outputStream* st) const { +- if (this == NULL) { +- st->print("NULL"); +- } else { +- st->print("'"); +- for (int i = 0; i < utf8_length(); i++) { +- st->print("%c", byte_at(i)); +- } +- st->print("'"); +- } +-} +- +-void Symbol::increment_refcount() { +- // Only increment the refcount if positive. If negative either +- // overflow has occurred or it is a permanent symbol in a read only +- // shared archive. +- if (_refcount >= 0) { +- Atomic::inc(&_refcount); +- NOT_PRODUCT(Atomic::inc(&_total_count);) +- } +-} +- +-void Symbol::decrement_refcount() { +- if (_refcount >= 0) { +- Atomic::dec(&_refcount); +-#ifdef ASSERT +- if (_refcount < 0) { +- print(); +- assert(false, "reference count underflow for symbol"); +- } +-#endif +- } +-} +- +-NOT_PRODUCT(int Symbol::_total_count = 0;) +diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbolOop.hpp openjdk/hotspot/src/share/vm/oops/symbolOop.hpp +--- openjdk.orig/hotspot/src/share/vm/oops/symbolOop.hpp 2013-06-25 14:49:37.269431439 -0400 ++++ openjdk/hotspot/src/share/vm/oops/symbolOop.hpp 1969-12-31 19:00:00.000000000 -0500 +@@ -1,223 +0,0 @@ +-/* +- * Copyright (c) 1997, 2009, 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. +- * +- */ +- +-#ifndef SHARE_VM_OOPS_SYMBOL_HPP +-#define SHARE_VM_OOPS_SYMBOL_HPP +- +-#include "utilities/utf8.hpp" +-#include "memory/allocation.hpp" +- +-// A Symbol is a canonicalized string. +-// All Symbols reside in global SymbolTable and are reference counted. +- +-// Reference counting +-// +-// All Symbols are allocated and added to the SymbolTable. +-// When a class is unloaded, the reference counts of the Symbol pointers in +-// the ConstantPool and in instanceKlass (see release_C_heap_structures) are +-// decremented. When the reference count for a Symbol goes to 0, the garbage +-// collector can free the Symbol and remove it from the SymbolTable. +-// +-// 0) Symbols need to be reference counted when a pointer to the Symbol is +-// saved in persistent storage. This does not include the pointer +-// in the SymbolTable bucket (the _literal field in HashtableEntry) +-// that points to the Symbol. All other stores of a Symbol* +-// to a field of a persistent variable (e.g., the _name filed in +-// FieldAccessInfo or _ptr in a CPSlot) is reference counted. +-// +-// 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for +-// "name" and returns a pointer to F or finds a pre-existing Symbol F for +-// "name" and returns a pointer to it. In both cases the reference count for F +-// is incremented under the assumption that a pointer to F will be created from +-// the return value. Thus the increment of the reference count is on the lookup +-// and not on the assignment to the new Symbol*. That is +-// Symbol* G = lookup() +-// ^ increment on lookup() +-// and not +-// Symbol* G = lookup() +-// ^ increment on assignmnet +-// The reference count must be decremented manually when the copy of the +-// pointer G is destroyed. +-// +-// 2) For a local Symbol* A that is a copy of an existing Symbol* B, the +-// reference counting is elided when the scope of B is greater than the scope +-// of A. For example, in the code fragment +-// below "klass" is passed as a parameter to the method. Symbol* "kn" +-// is a copy of the name in "klass". +-// +-// Symbol* kn = klass->name(); +-// unsigned int d_hash = dictionary()->compute_hash(kn, class_loader); +-// +-// The scope of "klass" is greater than the scope of "kn" so the reference +-// counting for "kn" is elided. +-// +-// Symbol* copied from ConstantPool entries are good candidates for reference +-// counting elision. The ConstantPool entries for a class C exist until C is +-// unloaded. If a Symbol* is copied out of the ConstantPool into Symbol* X, +-// the Symbol* in the ConstantPool will in general out live X so the reference +-// counting on X can be elided. +-// +-// For cases where the scope of A is not greater than the scope of B, +-// the reference counting is explicitly done. See ciSymbol, +-// ResolutionErrorEntry and ClassVerifier for examples. +-// +-// 3) When a Symbol K is created for temporary use, generally for substrings of +-// an existing symbol or to create a new symbol, assign it to a +-// TempNewSymbol. The SymbolTable methods new_symbol(), lookup() +-// and probe() all potentially return a pointer to a new Symbol. +-// The allocation (or lookup) of K increments the reference count for K +-// and the destructor decrements the reference count. +-// +-// Another example of TempNewSymbol usage is parsed_name used in +-// ClassFileParser::parseClassFile() where parsed_name is used in the cleanup +-// after a failed attempt to load a class. Here parsed_name is a +-// TempNewSymbol (passed in as a parameter) so the reference count on its symbol +-// will be decremented when it goes out of scope. +- +-class Symbol : public CHeapObj { +- friend class VMStructs; +- friend class SymbolTable; +- friend class MoveSymbols; +- private: +- volatile int _refcount; +- int _identity_hash; +- unsigned short _length; // number of UTF8 characters in the symbol +- jbyte _body[1]; +- +- enum { +- // max_symbol_length is constrained by type of _length +- max_symbol_length = (1 << 16) -1 +- }; +- +- static int object_size(int length) { +- size_t size = heap_word_size(sizeof(Symbol) + length); +- return align_object_size(size); +- } +- +- void byte_at_put(int index, int value) { +- assert(index >=0 && index < _length, "symbol index overflow"); +- _body[index] = value; +- } +- +- Symbol(const u1* name, int length); +- void* operator new(size_t size, int len); +- +- public: +- // Low-level access (used with care, since not GC-safe) +- const jbyte* base() const { return &_body[0]; } +- +- int object_size() { return object_size(utf8_length()); } +- +- // Returns the largest size symbol we can safely hold. +- static int max_length() { +- return max_symbol_length; +- } +- +- int identity_hash() { +- return _identity_hash; +- } +- +- // Reference counting. See comments above this class for when to use. +- int refcount() const { return _refcount; } +- void increment_refcount(); +- void decrement_refcount(); +- +- int byte_at(int index) const { +- assert(index >=0 && index < _length, "symbol index overflow"); +- return base()[index]; +- } +- +- const jbyte* bytes() const { return base(); } +- +- int utf8_length() const { return _length; } +- +- // Compares the symbol with a string. +- bool equals(const char* str, int len) const; +- bool equals(const char* str) const { return equals(str, (int) strlen(str)); } +- +- // Tests if the symbol starts with the given prefix. +- bool starts_with(const char* prefix, int len) const; +- bool starts_with(const char* prefix) const { +- return starts_with(prefix, (int) strlen(prefix)); +- } +- +- // Tests if the symbol starts with the given prefix. +- int index_of_at(int i, const char* str, int len) const; +- int index_of_at(int i, const char* str) const { +- return index_of_at(i, str, (int) strlen(str)); +- } +- +- // Three-way compare for sorting; returns -1/0/1 if receiver is than arg +- // note that the ordering is not alfabetical +- inline int fast_compare(Symbol* other) const; +- +- // Returns receiver converted to null-terminated UTF-8 string; string is +- // allocated in resource area, or in the char buffer provided by caller. +- char* as_C_string() const; +- char* as_C_string(char* buf, int size) const; +- // Use buf if needed buffer length is <= size. +- char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const; +- +- +- // Returns a null terminated utf8 string in a resource array +- char* as_utf8() const { return as_C_string(); } +- char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const { +- return as_C_string_flexible_buffer(t, buf, size); +- } +- +- jchar* as_unicode(int& length) const; +- +- // Treating this symbol as a class name, returns the Java name for the class. +- // String is allocated in resource area if buffer is not provided. +- // See Klass::external_name() +- const char* as_klass_external_name() const; +- const char* as_klass_external_name(char* buf, int size) const; +- +- // Printing +- void print_symbol_on(outputStream* st = NULL) const; +- void print_on(outputStream* st) const; // First level print +- void print_value_on(outputStream* st) const; // Second level print. +- +- // printing on default output stream +- void print() { print_on(tty); } +- void print_value() { print_value_on(tty); } +- +-#ifndef PRODUCT +- // Empty constructor to create a dummy symbol object on stack +- // only for getting its vtable pointer. +- Symbol() { } +- +- static int _total_count; +-#endif +-}; +- +-// Note: this comparison is used for vtable sorting only; it doesn't matter +-// what order it defines, as long as it is a total, time-invariant order +-// Since Symbol*s are in C_HEAP, their relative order in memory never changes, +-// so use address comparison for speed +-int Symbol::fast_compare(Symbol* other) const { +- return (((uintptr_t)this < (uintptr_t)other) ? -1 +- : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1); +-} +-#endif // SHARE_VM_OOPS_SYMBOL_HPP diff -r f352f5c79104 -r c5297dd496da patches/openjdk/6990754-use_native_memory_for_symboltable.patch --- a/patches/openjdk/6990754-use_native_memory_for_symboltable.patch Tue Jun 25 15:07:59 2013 +0100 +++ b/patches/openjdk/6990754-use_native_memory_for_symboltable.patch Wed Jun 26 10:47:13 2013 -0400 @@ -3,6 +3,7 @@ # Date 1371745779 18000 # Node ID afb96a923f7f2da64e711455257a024c100e8e2e # Parent af33d9cd440e2851eaffb819d67f86b42c6a8030 +# PLEASE SEE the other 6990754 patch which handles renames more generally 6990754: Use native memory and reference counting to implement SymbolTable Summary: move symbols from permgen into C heap and reference count them Reviewed-by: never, acorn, jmasa, stefank @@ -13107,8 +13108,9 @@ #endif // SHARE_VM_OOPS_OOPSHIERARCHY_HPP diff --git a/src/share/vm/oops/symbolOop.cpp b/src/share/vm/oops/symbol.cpp -rename from src/share/vm/oops/symbolOop.cpp -rename to src/share/vm/oops/symbol.cpp +# most patch programs can not handle file renames +# rename from src/share/vm/oops/symbolOop.cpp +# rename to src/share/vm/oops/symbol.cpp --- openjdk/hotspot/src/share/vm/oops/symbolOop.cpp +++ openjdk/hotspot/src/share/vm/oops/symbol.cpp @@ -1,5 +1,5 @@