diff --git a/.hgtags b/.hgtags index 89f5f016035..6d54fecdbfa 100644 --- a/.hgtags +++ b/.hgtags @@ -26,3 +26,4 @@ caf58ffa084568990cbb3441f9ae188e36b31770 jdk7-b42 6b84b04a80afe23262377c60913eebfc898f14c4 jdk7-b49 5da0e6b9f4f18ef483c977337214b12ee0e1fc8f jdk7-b50 a25c5ec5e40e07733d1ff9898a0abe36159288ff jdk7-b51 +7a90e89e36d103038f8667f6a7daae34ecfa1ad8 jdk7-b52 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 52f1f706812..5ac8ad95712 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -26,3 +26,4 @@ d7744e86dedc21a8ecf6bdb73eb191b8eaf5b0da jdk7-b47 aee93a8992d2389121eb610c00a86196f3e2b9b0 jdk7-b49 5111e13e44e542fe945b47ab154546daec36737d jdk7-b50 0f0189d55ce4a1f7840da7582ac7d970b3b7ab15 jdk7-b51 +4264c2fe66493e57c411045a1b61377796641e45 jdk7-b52 diff --git a/corba/.hgtags b/corba/.hgtags index 28a93dc8343..91ac5a1ccae 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -26,3 +26,4 @@ ccd6a16502e0650d91d85c4b86be05cbcd461a87 jdk7-b42 d70978bc64bc7a04be7797ab0dcd9b7b1b3a6bff jdk7-b49 0edbd0074b02b42b2b83cc47cb391d4869b7a8ec jdk7-b50 3eb8f1047a7402a9a79937d1c39560e931e91da2 jdk7-b51 +bec82237d694f9802b820fa11bbb4f7fa9bf8e77 jdk7-b52 diff --git a/corba/make/com/sun/corba/se/sources/Makefile b/corba/make/com/sun/corba/se/sources/Makefile index 164a4e65a93..9d945a29343 100644 --- a/corba/make/com/sun/corba/se/sources/Makefile +++ b/corba/make/com/sun/corba/se/sources/Makefile @@ -46,8 +46,6 @@ CORBA_JMK_DIRECTORY=$(TOPDIR)/make/com/sun/corba/minclude/ include $(CORBA_JMK_DIRECTORY)com_sun_corba_se_PortableActivationIDL.jmk include $(CORBA_JMK_DIRECTORY)com_sun_corba_se_impl_logging.jmk -FILES_java += com/sun/corba/se/org/omg/CORBA/ORB.java - # # Dirs # @@ -80,11 +78,11 @@ ORBUTIL.MC = $(SRC_DIR)/com/sun/corba/se/spi/logging/data/ORBUtil.mc POA.MC = $(SRC_DIR)/com/sun/corba/se/spi/logging/data/POA.mc UTIL.MC = $(SRC_DIR)/com/sun/corba/se/spi/logging/data/Util.mc -MC_GENERATE_CLASS = $(SRC_DIR)/com/sun/tools/corba/se/logutil/scripts/mc.scm -main main make-class -MC_GENERATE_LOG_RB = $(SRC_DIR)/com/sun/tools/corba/se/logutil/scripts/mc.scm -main main make-resource +MC_GENERATE_CLASS = make-class +MC_GENERATE_LOG_RB = make-resource -JSCHEME_GENERATE_CLASS = $(BOOT_JAVA_CMD) jscheme.REPL $(MC_GENERATE_CLASS) -JSCHEME_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) jscheme.REPL $(MC_GENERATE_LOG_RB) +JSCHEME_GENERATE_CLASS = $(BOOT_JAVA_CMD) com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_CLASS) +JSCHEME_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_LOG_RB) # diff --git a/corba/make/sun/rmi/corbalogsources/Makefile b/corba/make/sun/rmi/corbalogsources/Makefile index a7b995c1c51..0859c5ab2a9 100644 --- a/corba/make/sun/rmi/corbalogsources/Makefile +++ b/corba/make/sun/rmi/corbalogsources/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -75,15 +75,14 @@ ORBUTIL.MC = $(SRC_DIR)/com/sun/corba/se/spi/logging/data/ORBUtil.mc POA.MC = $(SRC_DIR)/com/sun/corba/se/spi/logging/data/POA.mc UTIL.MC = $(SRC_DIR)/com/sun/corba/se/spi/logging/data/Util.mc -MC_GENERATE_CLASS = $(SRC_DIR)/com/sun/tools/corba/se/logutil/scripts/mc.scm -main main make-class -MC_GENERATE_LOG_RB = $(SRC_DIR)/com/sun/tools/corba/se/logutil/scripts/mc.scm -main main make-resource +MC_GENERATE_CLASS = make-class +MC_GENERATE_LOG_RB = make-resource -JSCHEME_LIB_DIRECTORY=$(SRC_DIR)/com/sun/tools/corba/se/logutil/lib -JSCHEME_CLASSPATH=$(JSCHEME_LIB_DIRECTORY)/jscheme.jar$(CLASSPATH_SEPARATOR)$(JSCHEME_LIB_DIRECTORY)/jschemelogutil.jar -JSCHEME_GENERATE_CLASS = $(BOOT_JAVA_CMD) \ - -cp "$(JSCHEME_CLASSPATH)" jscheme.REPL $(MC_GENERATE_CLASS) -JSCHEME_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) \ - -cp "$(JSCHEME_CLASSPATH)" jscheme.REPL $(MC_GENERATE_LOG_RB) +MC_CLASSPATH=$(BUILDTOOLJARDIR)/MC.jar +MCJ_GENERATE_CLASS = $(BOOT_JAVA_CMD) \ + -cp "$(MC_CLASSPATH)" com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_CLASS) +MCJ_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) \ + -cp "$(MC_CLASSPATH)" com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_LOG_RB) # @@ -104,28 +103,28 @@ $(LOG_GENDIRECTORY): $(MKDIR) -p $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/ActivationSystemException.java : $(ACTIVATION.MC) - $(JSCHEME_GENERATE_CLASS) $(ACTIVATION.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(ACTIVATION.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/IORSystemException.java : $(IOR.MC) - $(JSCHEME_GENERATE_CLASS) $(IOR.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(IOR.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/InterceptorsSystemException.java : $(INTERCEPTORS.MC) - $(JSCHEME_GENERATE_CLASS) $(INTERCEPTORS.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(INTERCEPTORS.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/NamingSystemException.java : $(NAMING.MC) - $(JSCHEME_GENERATE_CLASS) $(NAMING.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(NAMING.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/OMGSystemException.java : $(OMG.MC) - $(JSCHEME_GENERATE_CLASS) $(OMG.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(OMG.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/ORBUtilSystemException.java : $(ORBUTIL.MC) - $(JSCHEME_GENERATE_CLASS) $(ORBUTIL.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(ORBUTIL.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/POASystemException.java : $(POA.MC) - $(JSCHEME_GENERATE_CLASS) $(POA.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(POA.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/UtilSystemException.java : $(UTIL.MC) - $(JSCHEME_GENERATE_CLASS) $(UTIL.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_CLASS) $(UTIL.MC) $(LOG_GENDIRECTORY) logresource.generate: $(LOG_GENDIRECTORY)/LogStrings.properties @@ -142,28 +141,28 @@ $(LOG_GENDIRECTORY)/LogStrings.properties: \ $(CAT) $(LOG_GENDIRECTORY)/*.resource > $(LOG_GENDIRECTORY)/LogStrings.properties $(LOG_GENDIRECTORY)/ActivationSystemException.resource : $(ACTIVATION.MC) - $(JSCHEME_GENERATE_LOG_RB) $(ACTIVATION.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(ACTIVATION.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/IORSystemException.resource : $(IOR.MC) - $(JSCHEME_GENERATE_LOG_RB) $(IOR.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(IOR.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/InterceptorsSystemException.resource : $(INTERCEPTORS.MC) - $(JSCHEME_GENERATE_LOG_RB) $(INTERCEPTORS.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(INTERCEPTORS.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/NamingSystemException.resource : $(NAMING.MC) - $(JSCHEME_GENERATE_LOG_RB) $(NAMING.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(NAMING.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/OMGSystemException.resource : $(OMG.MC) - $(JSCHEME_GENERATE_LOG_RB) $(OMG.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(OMG.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/ORBUtilSystemException.resource : $(ORBUTIL.MC) - $(JSCHEME_GENERATE_LOG_RB) $(ORBUTIL.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(ORBUTIL.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/POASystemException.resource : $(POA.MC) - $(JSCHEME_GENERATE_LOG_RB) $(POA.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(POA.MC) $(LOG_GENDIRECTORY) $(LOG_GENDIRECTORY)/UtilSystemException.resource : $(UTIL.MC) - $(JSCHEME_GENERATE_LOG_RB) $(UTIL.MC) $(LOG_GENDIRECTORY) + $(MCJ_GENERATE_LOG_RB) $(UTIL.MC) $(LOG_GENDIRECTORY) # diff --git a/corba/make/tools/Makefile b/corba/make/tools/Makefile index 489c7b2f269..f0d95363b84 100644 --- a/corba/make/tools/Makefile +++ b/corba/make/tools/Makefile @@ -1,5 +1,5 @@ # -# Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ include $(BUILDDIR)/common/Defs.gmk SUBDIRS = \ strip_properties \ idlj \ + logutil \ all build clean clobber:: $(SUBDIRS-loop) diff --git a/corba/make/tools/logutil/Makefile b/corba/make/tools/logutil/Makefile new file mode 100644 index 00000000000..2e19867f8d4 --- /dev/null +++ b/corba/make/tools/logutil/Makefile @@ -0,0 +1,43 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for building the idlj tool +# + +BUILDDIR = ../.. +PACKAGE = com.sun.tools.corba.se.logutil +PRODUCT = tools +PROGRAM = MC +include $(BUILDDIR)/common/Defs.gmk + +BUILDTOOL_SOURCE_ROOT = $(SHARE_SRC)/classes +BUILDTOOL_MAIN = $(PKGDIR)/MC.java + +# +# Build tool jar rules. +# +include $(BUILDDIR)/common/BuildToolJar.gmk + diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java b/corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java index d8b31fc0f77..e618a7401fa 100644 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java +++ b/corba/src/share/classes/com/sun/tools/corba/se/logutil/IndentingPrintWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.io.Writer ; import java.io.OutputStream ; import java.io.BufferedWriter ; import java.io.OutputStreamWriter ; -import jsint.Pair ; import java.util.StringTokenizer ; public class IndentingPrintWriter extends PrintWriter { @@ -38,22 +37,20 @@ public class IndentingPrintWriter extends PrintWriter { private int indentWidth = 4 ; private String indentString = "" ; - public void printMsg( String msg, Pair data ) + public void printMsg( String msg, Object... data ) { // System.out.println( "printMsg called with msg=" + msg + " data=" + data ) ; StringTokenizer st = new StringTokenizer( msg, "@", true ) ; StringBuffer result = new StringBuffer() ; - Object head = data.first ; - Pair tail = (Pair)data.rest ; String token = null ; + int pos = 0; while (st.hasMoreTokens()) { token = st.nextToken() ; if (token.equals("@")) { - if (head != null) { - result.append( head ) ; - head = tail.first ; - tail = (Pair)tail.rest ; + if (pos < data.length) { + result.append( data[pos] ); + ++pos; } else { throw new Error( "List too short for message" ) ; } diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/Input.java b/corba/src/share/classes/com/sun/tools/corba/se/logutil/Input.java new file mode 100644 index 00000000000..5431f0c7a17 --- /dev/null +++ b/corba/src/share/classes/com/sun/tools/corba/se/logutil/Input.java @@ -0,0 +1,211 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.corba.se.logutil; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStreamReader; +import java.io.IOException; + +import java.util.LinkedList; +import java.util.Queue; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Input { + + /** + * The name of the package this class will inhabit. + */ + private String packageName; + + /** + * The name of the generated class. + */ + private String className; + + /** + * The name of the group of exceptions handled by the class. + */ + private String groupName; + + /** + * The group of exceptions. + */ + private Queue exceptions; + + /** + * Represents the current state of parsing the input. + */ + private enum State + { + OUTER, + IN_CLASS, + IN_EXCEPTION_LIST + }; + + /** + * Regular expression to match each code line. + */ + private static final Pattern EXCEPTION_INFO_REGEX = + Pattern.compile("(\\w+)\\s*(\\d+)\\s*(\\w+)"); + + /** + * Parses the specified file to create a new {@link Input} + * object. + * + * @param filename the file to parse. + * @throws FileNotFoundException if the file can't be found. + * @throws IOException if an I/O error occurs. + */ + public Input(final String filename) + throws FileNotFoundException, IOException { + BufferedReader r = + new BufferedReader(new InputStreamReader(new FileInputStream(filename))); + State state = State.OUTER; + InputException current = null; + exceptions = new LinkedList(); + String line; + while ((line = r.readLine()) != null) { + // Skip ; comments + if (line.startsWith(";")) + continue; + + int index = line.indexOf("("); + if (index == -1) + continue; + + switch (state) { + case OUTER: + state = State.IN_CLASS; + String[] classInfo = line.substring(index).split(" "); + packageName = classInfo[0].substring(2, classInfo[0].length() - 1); + className = classInfo[1].substring(1, classInfo[1].length() - 1); + groupName = classInfo[2]; + break; + case IN_CLASS: + state = State.IN_EXCEPTION_LIST; + break; + case IN_EXCEPTION_LIST: + boolean inQuote = false; + boolean inCode = false; + boolean end = false; + int start = index + 1; + Queue lines = new LinkedList(); + for (int a = start; a < line.length(); ++a) { + if (line.charAt(a) == '(' && !inCode && !inQuote) { + if (current == null) + current = + new InputException(line.substring(start, a).trim()); + start = a + 1; + inCode = true; + } + if (line.charAt(a) == '"') + inQuote = !inQuote; + if (line.charAt(a) == ')' && !inQuote) { + if (inCode) { + lines.offer(line.substring(start, a)); + inCode = false; + } else + end = true; + } + if (!end && a == line.length() - 1) + line += r.readLine(); + } + for (String l : lines) { + int stringStart = l.indexOf("\"") + 1; + int stringEnd = l.indexOf("\"", stringStart); + Matcher matcher = EXCEPTION_INFO_REGEX.matcher(l.substring(0, stringStart)); + if (matcher.find()) + current.add(new InputCode(matcher.group(1), + Integer.parseInt(matcher.group(2)), + matcher.group(3), + l.substring(stringStart, stringEnd))); + } + exceptions.offer(current); + current = null; + break; + } + } + } + + /** + * Returns the name of this group of exceptions. + * + * @return the name of this group of exceptions. + */ + public String getGroupName() + { + return groupName; + } + + /** + * Returns the name of the package this class will go in. + * + * @return the name of the package. + */ + public String getPackageName() + { + return packageName; + } + + /** + * Returns the name of the generated class. + * + * @return the name of the class. + */ + public String getClassName() + { + return className; + } + + /** + * Returns the exceptions contained in this class. + * + * @return the exceptions. + */ + public Queue getExceptions() { + return exceptions; + } + + /** + * Returns a textual representation of this input. + * + * @return a textual representation. + */ + public String toString() { + return getClass().getName() + + "[packageName=" + packageName + + ",className=" + className + + ",groupName=" + groupName + + ",exceptions=" + exceptions + + "]"; + } + +} diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputCode.java b/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputCode.java new file mode 100644 index 00000000000..810a449f486 --- /dev/null +++ b/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputCode.java @@ -0,0 +1,116 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.corba.se.logutil; + +public class InputCode { + + /** + * The name of this code. + */ + private final String name; + + /** + * The code. + */ + private final int code; + + /** + * The log level for this code. + */ + private final String logLevel; + + /** + * The error message for this code. + */ + private final String message; + + /** + * Creates a new error code with the specified name, code, + * log level and error message. + * + * @param name the name of the new code. + * @param code the code itself. + * @param logLevel the level of severity of this error. + * @param message the error message for this code. + */ + public InputCode(final String name, final int code, + final String logLevel, final String message) { + this.name = name; + this.code = code; + this.logLevel = logLevel; + this.message = message; + } + + /** + * Returns the name of this code. + * + * @return the name of the code. + */ + public String getName() { + return name; + } + + /** + * Returns the code. + * + * @return the code. + */ + public int getCode() { + return code; + } + + /** + * Returns the severity of this code. + * + * @return the log level severity of the code. + */ + public String getLogLevel() { + return logLevel; + } + + /** + * Returns the error message for this code. + * + * @return the error message for this code. + */ + public String getMessage() { + return message; + } + + /** + * Returns a textual representation of this code. + * + * @return a textual representation. + */ + public String toString() { + return getClass().getName() + + "[name=" + name + + ",code=" + code + + ",logLevel=" + logLevel + + ",message=" + message + + "]"; + } + +} diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputException.java b/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputException.java new file mode 100644 index 00000000000..5c1f4984e57 --- /dev/null +++ b/corba/src/share/classes/com/sun/tools/corba/se/logutil/InputException.java @@ -0,0 +1,94 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.corba.se.logutil; + +import java.util.LinkedList; +import java.util.Queue; + +public class InputException { + + /** + * The name of this exception. + */ + private final String name; + + /** + * The codes associated with this exception. + */ + private final Queue codes; + + /** + * Constructs a new {@link InputException} with the + * specified name. + * + * @param name the name of the new exception; + */ + public InputException(final String name) { + this.name = name; + codes = new LinkedList(); + } + + /** + * Adds a new code to this exception. + * + * @param c the code to add. + */ + public void add(InputCode c) + { + codes.offer(c); + } + + /** + * Returns the name of this exception. + * + * @return the exception's name. + */ + public String getName() { + return name; + } + + /** + * Returns the codes associated with this exception. + * + * @return the exception's codes. + */ + public Queue getCodes() { + return codes; + } + + /** + * Returns a textual representation of this exception. + * + * @return a textual representation. + */ + public String toString() { + return getClass().getName() + + "[name=" + name + + ",codes=" + codes + + "]"; + } + +} + diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/MC.java b/corba/src/share/classes/com/sun/tools/corba/se/logutil/MC.java new file mode 100644 index 00000000000..9246f70c3ab --- /dev/null +++ b/corba/src/share/classes/com/sun/tools/corba/se/logutil/MC.java @@ -0,0 +1,559 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.corba.se.logutil; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import java.util.Arrays; +import java.util.Date; +import java.util.Formatter; +import java.util.List; +import java.util.Queue; + +public class MC { + + private static final String VERSION = "1.0"; + + private static final List SUN_EXCEPTION_GROUPS = Arrays.asList(new String[] + { "SUNBASE", "ORBUTIL", "ACTIVATION", "NAMING", "INTERCEPTORS", "POA", "IOR", "UTIL" }); + + private static final List EXCEPTIONS = Arrays.asList(new String[] + { "UNKNOWN", "BAD_PARAM", "NO_MEMORY", "IMP_LIMIT", "COMM_FAILURE", "INV_OBJREF", "NO_PERMISSION", + "INTERNAL", "MARSHAL", "INITIALIZE", "NO_IMPLEMENT", "BAD_TYPECODE", "BAD_OPERATION", "NO_RESOURCES", + "NO_RESPONSE", "PERSIST_STORE", "BAD_INV_ORDER", "TRANSIENT", "FREE_MEM", "INV_IDENT", "INV_FLAG", + "INTF_REPOS", "BAD_CONTEXT", "OBJ_ADAPTER", "DATA_CONVERSION", "OBJECT_NOT_EXIST", "TRANSACTION_REQUIRED", + "TRANSACTION_ROLLEDBACK", "INVALID_TRANSACTION", "INV_POLICY", "CODESET_INCOMPATIBLE", "REBIND", + "TIMEOUT", "TRANSACTION_UNAVAILABLE", "BAD_QOS", "INVALID_ACTIVITY", "ACTIVITY_COMPLETED", + "ACTIVITY_REQUIRED" }); + + /** + * Read the minor codes from the input file and + * write out a resource file. + * + * @param inFile the file to read the codes from. + * @param outDir the directory to write the resource file to. + * @throws FileNotFoundException if the input file can not be found. + * @throws IOException if an I/O error occurs. + */ + private void makeResource(String inFile, String outDir) + throws FileNotFoundException, IOException { + writeResource(outDir, new Input(inFile)); + } + + /** + * Create a new Java source file using the specified Scheme input file, + * and writing the result to the given output directory. + * + * @param inFile the file to read the data from. + * @param outDir the directory to write the Java class to. + * @throws FileNotFoundException if the input file can not be found. + * @throws IOException if an I/O error occurs. + */ + private void makeClass(String inFile, String outDir) + throws FileNotFoundException, IOException { + writeClass(inFile, outDir, new Input(inFile)); + } + + /** + * Writes out a Java source file using the data from the given + * {@link Input} object. The result is written to {@code outDir}. + * The name of the input file is just used in the header of the + * resulting source file. + * + * @param inFile the name of the file the data was read from. + * @param outDir the directory to write the Java class to. + * @param input the parsed input data. + * @throws FileNotFoundException if the output file can't be written. + */ + private void writeClass(String inFile, String outDir, Input input) + throws FileNotFoundException { + String packageName = input.getPackageName(); + String className = input.getClassName(); + String groupName = input.getGroupName(); + Queue exceptions = input.getExceptions(); + FileOutputStream file = new FileOutputStream(outDir + File.separator + className + ".java"); + IndentingPrintWriter pw = new IndentingPrintWriter(file); + + writeClassHeader(inFile, groupName, pw); + pw.printMsg("package @ ;", packageName); + pw.println(); + pw.println("import java.util.logging.Logger ;"); + pw.println("import java.util.logging.Level ;"); + pw.println(); + pw.println("import org.omg.CORBA.OMGVMCID ;"); + pw.println( "import com.sun.corba.se.impl.util.SUNVMCID ;"); + pw.println( "import org.omg.CORBA.CompletionStatus ;"); + pw.println( "import org.omg.CORBA.SystemException ;"); + pw.println(); + pw.println( "import com.sun.corba.se.spi.orb.ORB ;"); + pw.println(); + pw.println( "import com.sun.corba.se.spi.logging.LogWrapperFactory;"); + pw.println(); + pw.println( "import com.sun.corba.se.spi.logging.LogWrapperBase;"); + pw.println(); + writeImports(exceptions, pw); + pw.println(); + pw.indent(); + pw.printMsg("public class @ extends LogWrapperBase {", className); + pw.println(); + pw.printMsg("public @( Logger logger )", className); + pw.indent(); + pw.println( "{"); + pw.undent(); + pw.println( "super( logger ) ;"); + pw.println( "}"); + pw.println(); + pw.flush(); + writeFactoryMethod(className, groupName, pw); + writeExceptions(groupName, exceptions, className, pw); + pw.undent(); + pw.println( ); + pw.println( "}"); + pw.flush(); + pw.close(); + } + + /** + * Writes out the header of a Java source file. + * + * @param inFile the input file the file was generated from. + * @param groupName the group of exceptions the Java source file is for. + * @param pw the print writer used to write the output. + */ + private void writeClassHeader(String inFile, String groupName, + IndentingPrintWriter pw) { + if (groupName.equals("OMG")) + pw.println("// Log wrapper class for standard exceptions"); + else + pw.printMsg("// Log wrapper class for Sun private system exceptions in group @", + groupName); + pw.println("//"); + pw.printMsg("// Generated by MC.java version @, DO NOT EDIT BY HAND!", VERSION); + pw.printMsg("// Generated from input file @ on @", inFile, new Date()); + pw.println(); + } + + /** + * Write out the import list for the exceptions. + * + * @param groups the exceptions that were parsed. + * @param pw the {@link IndentingPrintWriter} for writing to the file. + */ + private void writeImports(Queue exceptions, + IndentingPrintWriter pw) { + if (exceptions == null) + return; + for (InputException e : exceptions) + pw.println("import org.omg.CORBA." + e.getName() + " ;"); + } + + /** + * Write out the factory method for this group of exceptions. + * + * @param className the name of the generated class. + * @param groupName the name of this group of exceptions. + * @param pw the {@link IndentingPrintWriter} for writing to the file. + */ + private void writeFactoryMethod(String className, String groupName, + IndentingPrintWriter pw) { + pw.indent(); + pw.println( "private static LogWrapperFactory factory = new LogWrapperFactory() {"); + pw.println( "public LogWrapperBase create( Logger logger )" ); + pw.indent(); + pw.println( "{"); + pw.undent(); + pw.printMsg("return new @( logger ) ;", className); + pw.undent(); + pw.println( "}" ); + pw.println( "} ;" ); + pw.println(); + pw.printMsg("public static @ get( ORB orb, String logDomain )", className); + pw.indent(); + pw.println( "{"); + pw.indent(); + pw.printMsg( "@ wrapper = ", className); + pw.indent(); + pw.printMsg( "(@) orb.getLogWrapper( logDomain, ", className); + pw.undent(); + pw.undent(); + pw.printMsg( "\"@\", factory ) ;", groupName); + pw.undent(); + pw.println( "return wrapper ;" ); + pw.println( "} " ); + pw.println(); + pw.printMsg( "public static @ get( String logDomain )", className); + pw.indent(); + pw.println( "{"); + pw.indent(); + pw.printMsg( "@ wrapper = ", className); + pw.indent(); + pw.printMsg( "(@) ORB.staticGetLogWrapper( logDomain, ", className); + pw.undent(); + pw.undent(); + pw.printMsg( "\"@\", factory ) ;", groupName); + pw.undent(); + pw.println( "return wrapper ;" ); + pw.println( "} " ); + pw.println(); + } + + /** + * Writes out the exceptions themselves. + * + * @param groupName the name of this group of exceptions. + * @param exceptions the exceptions to write out. + * @param className the name of the generated class. + * @param pw the {@link IndentingPrintWriter} for writing to the file. + */ + private void writeExceptions(String groupName, Queue exceptions, + String className, IndentingPrintWriter pw) { + for (InputException e : exceptions) { + pw.println("///////////////////////////////////////////////////////////"); + pw.printMsg("// @", e.getName()); + pw.println("///////////////////////////////////////////////////////////"); + pw.println(); + for (InputCode c : e.getCodes()) + writeMethods(groupName, e.getName(), c.getName(), c.getCode(), + c.getLogLevel(), className, StringUtil.countArgs(c.getMessage()), pw); + pw.flush(); + } + } + + /** + * Writes out the methods for a particular error. + * + * @param groupName the name of this group of exceptions. + * @param exceptionName the name of this particular exception. + * @param errorName the name of this particular error. + * @param code the minor code for this particular error. + * @param ident the name of the error in mixed-case identifier form. + * @param level the level at which to place log messages. + * @param className the name of the class for this group of exceptions. + * @param numParams the number of parameters the detail message takes. + * @param pw the print writer for writing to the file. + */ + private void writeMethods(String groupName, String exceptionName, String errorName, + int code, String level, String className, int numParams, + IndentingPrintWriter pw) { + String ident = StringUtil.toMixedCase(errorName); + pw.printMsg("public static final int @ = @ ;", errorName, getBase(groupName, code)); + pw.println(); + pw.flush(); + writeMethodStatusCause(groupName, exceptionName, errorName, ident, level, + numParams, className, pw); + pw.println(); + pw.flush(); + writeMethodStatus(exceptionName, ident, numParams, pw); + pw.println(); + pw.flush(); + writeMethodCause(exceptionName, ident, numParams, pw); + pw.println(); + pw.flush(); + writeMethodNoArgs(exceptionName, ident, numParams, pw); + pw.println(); + pw.flush(); + } + + /** + * Writes out a method for an error that takes a + * {@link org.omg.CORBA.CompletionStatus} and a cause. + * + * @param groupName the name of this group of exceptions. + * @param exceptionName the name of this particular exception. + * @param errorName the name of this particular error. + * @param ident the name of the error in mixed-case identifier form. + * @param logLevel the level at which to place log messages. + * @param numParams the number of parameters the detail message takes. + * @param className the name of the class for this group of exceptions. + * @param pw the print writer for writing to the file. + */ + private void writeMethodStatusCause(String groupName, String exceptionName, + String errorName, String ident, + String logLevel, int numParams, + String className, IndentingPrintWriter pw) { + pw.indent(); + pw.printMsg( "public @ @( CompletionStatus cs, Throwable t@) {", exceptionName, + ident, makeDeclArgs(true, numParams)); + pw.printMsg( "@ exc = new @( @, cs ) ;", exceptionName, exceptionName, errorName); + pw.indent(); + pw.println( "if (t != null)" ); + pw.undent(); + pw.println( "exc.initCause( t ) ;" ); + pw.println(); + pw.indent(); + pw.printMsg( "if (logger.isLoggable( Level.@ )) {", logLevel); + if (numParams > 0) { + pw.printMsg( "Object[] parameters = new Object[@] ;", numParams); + for (int a = 0; a < numParams; ++a) + pw.printMsg("parameters[@] = arg@ ;", a, a); + } else + pw.println( "Object[] parameters = null ;"); + pw.indent(); + pw.printMsg( "doLog( Level.@, \"@.@\",", logLevel, groupName, ident); + pw.undent(); + pw.undent(); + pw.printMsg( "parameters, @.class, exc ) ;", className); + pw.println( "}"); + pw.println(); + + pw.undent(); + pw.println( "return exc ;"); + pw.println( "}"); + } + + /** + * Writes out a method for an error that takes a + * {@link org.omg.CORBA.CompletionStatus}. + * + * @param exceptionName the name of this particular exception. + * @param ident the name of the error in mixed-case identifier form. + * @param numParams the number of parameters the detail message takes. + * @param pw the print writer for writing to the file. + */ + private void writeMethodStatus(String exceptionName, String ident, + int numParams, IndentingPrintWriter pw) { + pw.indent(); + pw.printMsg("public @ @( CompletionStatus cs@) {", exceptionName, + ident, makeDeclArgs(true, numParams)); + pw.undent(); + pw.printMsg("return @( cs, null@ ) ;", ident, makeCallArgs(true, numParams)); + pw.println("}"); + } + + /** + * Writes out a method for an error that takes a cause. + * + * @param exceptionName the name of this particular exception. + * @param ident the name of the error in mixed-case identifier form. + * @param numParams the number of parameters the detail message takes. + * @param pw the print writer for writing to the file. + */ + private void writeMethodCause(String exceptionName, String ident, + int numParams, IndentingPrintWriter pw) { + pw.indent(); + pw.printMsg("public @ @( Throwable t@) {", exceptionName, ident, + makeDeclArgs(true, numParams)); + pw.undent(); + pw.printMsg("return @( CompletionStatus.COMPLETED_NO, t@ ) ;", ident, + makeCallArgs(true, numParams)); + pw.println("}"); + } + + /** + * Writes out a method for an error that takes no arguments. + * + * @param exceptionName the name of this particular exception. + * @param ident the name of the error in mixed-case identifier form. + * @param numParams the number of parameters the detail message takes. + * @param pw the print writer for writing to the file. + */ + private void writeMethodNoArgs(String exceptionName, String ident, + int numParams, IndentingPrintWriter pw) { + + pw.indent(); + pw.printMsg("public @ @( @) {", exceptionName, ident, + makeDeclArgs(false, numParams)); + pw.undent(); + pw.printMsg("return @( CompletionStatus.COMPLETED_NO, null@ ) ;", + ident, makeCallArgs(true, numParams)); + pw.println("}"); + } + + /** + * Returns a list of comma-separated arguments with type declarations. + * + * @param leadingComma true if the list should start with a comma. + * @param numArgs the number of arguments to generate. + * @return the generated string. + */ + private String makeDeclArgs(boolean leadingComma, int numArgs) { + return makeArgString("Object arg", leadingComma, numArgs); + } + + /** + * Returns a list of comma-separated arguments without type declarations. + * + * @param leadingComma true if the list should start with a comma. + * @param numArgs the number of arguments to generate. + * @return the generated string. + */ + private String makeCallArgs(boolean leadingComma, int numArgs) { + return makeArgString("arg", leadingComma, numArgs); + } + + /** + * Returns a list of comma-separated arguments. + * + * @param prefixString the string with which to prefix each argument. + * @param leadingComma true if the list should start with a comma. + * @param numArgs the number of arguments to generate. + * @return the generated string. + */ + private String makeArgString(String prefixString, boolean leadingComma, + int numArgs) { + if (numArgs == 0) + return " "; + if (numArgs == 1) { + if (leadingComma) + return ", " + prefixString + (numArgs - 1); + else + return " " + prefixString + (numArgs - 1); + } + return makeArgString(prefixString, leadingComma, numArgs - 1) + + ", " + prefixString + (numArgs - 1); + } + + /** + * Returns the {@link String} containing the calculation of the + * error code. + * + * @param groupName the group of exception to which the code belongs. + * @param code the minor code number representing the exception within the group. + * @return the unique error code. + */ + private String getBase(String groupName, int code) { + if (groupName.equals("OMG")) + return "OMGVMCID.value + " + code; + else + return "SUNVMCID.value + " + (code + getSunBaseNumber(groupName)); + } + + /** + * Returns the base number for Sun-specific exceptions. + * + * @return the base number. + */ + private int getSunBaseNumber(String groupName) { + return 200 * SUN_EXCEPTION_GROUPS.indexOf(groupName); + } + + /** + * Writes out a resource file using the data from the given + * {@link Input} object. The result is written to {@code outDir}. + * + * @param outDir the directory to write the Java class to. + * @param input the parsed input data. + * @throws FileNotFoundException if the output file can't be written. + */ + private void writeResource(String outDir, Input input) + throws FileNotFoundException { + FileOutputStream file = new FileOutputStream(outDir + File.separator + + input.getClassName() + ".resource"); + IndentingPrintWriter pw = new IndentingPrintWriter(file); + String groupName = input.getGroupName(); + for (InputException e : input.getExceptions()) { + String exName = e.getName(); + for (InputCode c : e.getCodes()) { + String ident = StringUtil.toMixedCase(c.getName()); + pw.printMsg("@.@=\"@: (@) @\"", groupName, ident, + getMessageID(groupName, exName, c.getCode()), exName, c.getMessage()); + } + pw.flush(); + } + pw.close(); + } + + /** + * Returns the message ID corresponding to the given group name, + * exception name and error code. + * + * @param groupName the name of the group of exceptions. + * @param exception the name of the particular exception. + * @param code an error code from the given exception. + * @return the message ID. + */ + private String getMessageID(String groupName, String exceptionName, int code) { + if (groupName.equals("OMG")) + return getStandardMessageID(exceptionName, code); + else + return getSunMessageID(groupName, exceptionName, code); + } + + /** + * Returns the standard (OMG) message ID corresponding to the given + * exception name and error code. + * + * @param exceptionName the name of the particular exception. + * @param code an error code from the given exception. + * @return the message ID. + */ + private String getStandardMessageID(String exceptionName, int code) { + return new Formatter().format("IOP%s0%04d", getExceptionID(exceptionName), + code).toString(); + } + + /** + * Returns the Sun message ID corresponding to the given group name, + * exception name and error code. + * + * @param groupName the name of the group of exceptions. + * @param exceptionName the name of the particular exception. + * @param code an error code from the given exception. + * @return the message ID. + */ + private String getSunMessageID(String groupName, String exceptionName, int code) { + return new Formatter().format("IOP%s1%04d", getExceptionID(exceptionName), + getSunBaseNumber(groupName) + code).toString(); + } + + /** + * Returns the exception ID corresponding to the given exception name. + * + * @param exceptionName the name of the particular exception. + * @return the message ID. + */ + private String getExceptionID(String exceptionName) { + return new Formatter().format("%03d", EXCEPTIONS.indexOf(exceptionName)).toString(); + } + + /** + * Entry point for running the generator from the command + * line. Users can specify either "make-class" or "make-resource" + * as the first argument to generate the specified type of file. + * + * @param args the command-line arguments. + * @throws FileNotFoundException if the input file can not be found. + * @throws IOException if an I/O error occurs. + */ + public static void main(String[] args) + throws FileNotFoundException, IOException + { + if (args.length < 3) + { + System.err.println("(make-class|make-resource) "); + System.exit(-1); + } + if (args[0].equals("make-class")) + new MC().makeClass(args[1], args[2]); + else if (args[0].equals("make-resource")) + new MC().makeResource(args[1], args[2]); + else + System.err.println("Invalid command: " + args[0]); + } + +} diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/lib/jscheme.jar b/corba/src/share/classes/com/sun/tools/corba/se/logutil/lib/jscheme.jar deleted file mode 100644 index 5a2a0f1f44d..00000000000 Binary files a/corba/src/share/classes/com/sun/tools/corba/se/logutil/lib/jscheme.jar and /dev/null differ diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/lib/jschemelogutil.jar b/corba/src/share/classes/com/sun/tools/corba/se/logutil/lib/jschemelogutil.jar deleted file mode 100644 index 4510aedd1d7..00000000000 Binary files a/corba/src/share/classes/com/sun/tools/corba/se/logutil/lib/jschemelogutil.jar and /dev/null differ diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/mc b/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/mc deleted file mode 100644 index 16df63d031f..00000000000 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/mc +++ /dev/null @@ -1,2 +0,0 @@ -#! /bin/sh -java -cp lib/jscheme.jar:lib/util.jar jscheme.REPL mc.scm -main main $@ diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/mc.scm b/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/mc.scm deleted file mode 100644 index 3e9b51409ec..00000000000 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/mc.scm +++ /dev/null @@ -1,662 +0,0 @@ -; Scheme program to produce CORBA standard exceptions class -; requires Jscheme Java extensions -; Makes use of some custom Java classes also - -(import "com.sun.tools.corba.se.logutil.IndentingPrintWriter" ) -(import "com.sun.tools.corba.se.logutil.StringUtil" ) -(import "java.io.FileOutputStream") - -(define version-string "1.3") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Utility functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; reload this file (convenience definition) -(define (reload) (load "mc.scm")) - -; Simple little function to report an error -(define (error msg) - (throw (Error. msg))) - -; some debug support -(define debug #f) - -(define (dprint msg) - (if debug - (.println System.out$ msg))) - -; Replace dprint with noprint to avoid seeing messages when debug is #t -(define (noprint msg) ()) - -; Helper function present so that a scheme method taking strings as args -; can be easily run from a command line. -; arg: vector containing argument strings. Element 0 is the function name -; to execute -(define (main arg) - (let* - ( - (arg-list (vector->list arg)) - (function-symbol (string->symbol (car arg-list))) - (args (cdr arg-list))) - (apply (eval function-symbol) args))) - -; Returns the position of key in lst, numbering from 0. key is matched using eqv? -(define (get-list-position key lst) - (letrec - ( - (helper (lambda (k l accum) - (cond - ((null? l) (error (string-append "Could not find " k))) - ((eqv? k (car l)) accum) - (else (helper k (cdr l) (+ accum 1))) )))) - (begin - (noprint (string-append "get-list-position called with key " key " lst " lst )) - (helper key lst 0)))) - -; Return a string representing number in decimal padded to length with leading 0s. -(define (pad-number-string number length) - (let* - ( - (number-string (number->string number)) - (pad-length (- length (string-length number-string))) - ) - (string-append (make-string pad-length #\0) number-string))) - -; Read an S-expression from a file that contains all of the data. -; -; The S-expression used for minor codes must have the structure -; (package-name class-name exception-group-name -; (exception -; (name value level explanation) -; ... -; ) -; ... -; ) -(define (read-file fname) - (read (open-input-file fname))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions for handling major system exceptions and exception groups -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Function to find the base ID given an exception group name. Result is a function that -; maps the minor code into the Java expression for that minor code's actual value. -(define (get-base group-name) - (if (eqv? group-name 'OMG) - (lambda (minor-code) - (string-append "OMGVMCID.value + " (number->string minor-code))) - (let ; bind base-number outside the lambda so it is only evaluated once - ( - (base-number (get-sun-base-number group-name))) - (lambda (minor-code) - (string-append "SUNVMCID.value + " (number->string (+ base-number minor-code))))))) - -; Function to get a base value for the group-name -(define (get-sun-base-number group-name) - (let* - ( - (lst (list 'SUNBASE 'ORBUTIL 'ACTIVATION 'NAMING 'INTERCEPTORS 'POA 'IOR 'UTIL)) - (subsystem-size 200)) - (* subsystem-size (get-list-position group-name lst)))) - -; Function to get a 3 digit number for a system exception -(define (get-exception-id exception-name) - (let - ( - (lst (list 'UNKNOWN 'BAD_PARAM 'NO_MEMORY 'IMP_LIMIT 'COMM_FAILURE 'INV_OBJREF 'NO_PERMISSION - 'INTERNAL 'MARSHAL 'INITIALIZE 'NO_IMPLEMENT 'BAD_TYPECODE 'BAD_OPERATION 'NO_RESOURCES - 'NO_RESPONSE 'PERSIST_STORE 'BAD_INV_ORDER 'TRANSIENT 'FREE_MEM 'INV_IDENT 'INV_FLAG - 'INTF_REPOS 'BAD_CONTEXT 'OBJ_ADAPTER 'DATA_CONVERSION 'OBJECT_NOT_EXIST 'TRANSACTION_REQUIRED - 'TRANSACTION_ROLLEDBACK 'INVALID_TRANSACTION 'INV_POLICY 'CODESET_INCOMPATIBLE 'REBIND - 'TIMEOUT 'TRANSACTION_UNAVAILABLE 'BAD_QOS 'INVALID_ACTIVITY 'ACTIVITY_COMPLETED - 'ACTIVITY_REQUIRED ))) - (pad-number-string (get-list-position exception-name lst) 3))) - -; Return the message id string for any system exception -; -(define (get-message-id exception-type group-name minor) - (if (eqv? group-name 'OMG) - (get-standard-message-id exception-type minor) - (get-sun-message-id exception-type group-name minor))) - -; Return the message id string for a particular standard exception -; -(define (get-standard-message-id exception-type minor) - (string-append - "IOP" - (get-exception-id exception-type) - "0" - (pad-number-string (number->string minor) 4))) - -; Return the sun message id for this exception-type, group-name, and minor code. -(define (get-sun-message-id exception-type group-name minor) - (string-append - "IOP" - (get-exception-id exception-type) - "1" - (pad-number-string (+ (get-sun-base-number group-name) minor) 4))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; visitor framework for the input file format -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(define (visit-top obj func1) - (let* - ( - (package (car obj)) - (class (cadr obj)) - (group (caddr obj)) - (func2 (func1 package class group)) - (exceptions (cadddr obj))) - (visit-exceptions exceptions func2))) - -; visit the elements of an arbitrary list -; lst: the list to visit -; func: the function to apply to each element of lst -; next-level the function on lst element and func that visits the next level -(define (visit-list lst func next-level) - (if (null? (cdr lst)) - (next-level #t (car lst) func) - (begin - (next-level #f (car lst) func) - (visit-list (cdr lst) func next-level)))) - -(define (visit-exceptions exceptions func2) - (visit-list exceptions func2 (lambda (last-flag element func) (visit-exception last-flag element func)))) - -(define (visit-exception last-flag exception func2) - (let* - ( - (major (car exception)) - (minor-codes (cdr exception)) - (func3 (func2 last-flag major))) - (visit-minor-codes minor-codes func3))) - -(define (visit-minor-codes minor-codes func3) - (visit-list minor-codes func3 (lambda (last-flag element func) (visit-minor-code last-flag element func)))) - -(define (visit-minor-code last-flag minor-code func3) - (let* - ( - (name (car minor-code)) - (minor (cadr minor-code)) - (level (caddr minor-code)) - (msg (cadddr minor-code))) - (func3 last-flag name minor level msg))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; The visitors -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; A simple visitor that just echoes the input for test purposes -(define (simple-visitor package class group) - (let* - ( - (pw (IndentingPrintWriter. System.out$))) - (begin - (.indent pw) - (.printMsg pw "package=@ class=@ group=@" (list package class group)) - (.flush pw) - (lambda (last-flag major) - (begin - (.indent pw) - (.printMsg pw "major=@" (list major)) - (.flush pw) - (lambda (last-flag name minor level message) - (begin - (if last-flag (.undent pw)) - (.printMsg pw "name=@ minor=@ level=@ message=@" (list name minor level message)) - (.flush pw)))))))) - -; Function that returns a visitor that writes out the resource file in the form: -; id="MSGID: explanation" -; outdir: Output directory -(define (resource-visitor outdir) - (lambda (package class group) - (let* - ( - (file-name (string-append outdir java.io.File.separator$ class ".resource")) - (pw (IndentingPrintWriter. (FileOutputStream. file-name)))) - (begin - (dprint (string-append "package= " package " class=" class " group=" group " file-name=" file-name)) - (lambda (last-flag1 major) - (begin - ; (dprint (string-append "last-flag1=" last-flag1 " major=" major)) - (lambda (last-flag2 name minor level message) - (begin - ; (dprint (string-append "last-flag2=" last-flag2 " name=" name - ; " minor=" minor " level=" level " message=" message)) - (let* - ( - (msgid (get-message-id major group minor)) - (ident (StringUtil.toMixedCase (symbol->string name)))) - (begin - ; (dprint (string-append "msgid=" msgid " ident=" ident)) - (.printMsg pw "@.@=\"@: (@) @\"" (list group ident msgid major message)) - (.flush pw) - (if (and last-flag1 last-flag2) - (begin - ; (dprint "closing file") - (.close pw))))))))))))) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Top-level functions for creating the products. All have names of the form make-xxx -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Read the minor codes from the infile and write out a resource file. -(define (make-resource infile outdir) - (tryCatch - (visit-top (read-file infile) (resource-visitor outdir)) - (lambda (exc) - (begin - (.println System.out$ (string-append "make-resource failed with exception " (.toString exc))) - (System.exit 1))))) - -; Read the minor codes from the infile and write a Java implementation to -; handle them to outfile under outdir -(define (make-class infile outdir) - (tryCatch - (write-class infile outdir (read-file infile)) - (lambda (exc) - (begin - (.println System.out$ (string-append "make-class failed with exception " (.toString exc))) - (System.exit 1))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; The original make-class implementation (this should be replaced by two visitors) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Write out the Java source code for the StandardExceptions class -; outdir: Output directory to write the generated files -; obj: the data from the input file -(define (write-class infile outdir obj) - (let* - ( - (package-name (car obj)) - (class-name (cadr obj)) - (exception-group-name (caddr obj)) - (exceptions (cadddr obj)) - (file (FileOutputStream. (string-append outdir java.io.File.separator$ class-name ".java"))) - (pw (IndentingPrintWriter. file)) - ) - (begin - (write-class-header infile package-name class-name exception-group-name pw) - (.printMsg pw "package @ ;" - (list package-name)) - (.println pw) - (.println pw "import java.util.logging.Logger ;") - (.println pw "import java.util.logging.Level ;") - (.println pw) - (.println pw "import org.omg.CORBA.OMGVMCID ;") - (.println pw "import com.sun.corba.se.impl.util.SUNVMCID ;") - (.println pw "import org.omg.CORBA.CompletionStatus ;") - (.println pw "import org.omg.CORBA.SystemException ;") - (.println pw) - (.println pw "import com.sun.corba.se.spi.orb.ORB ;") - (.println pw) - (.println pw "import com.sun.corba.se.spi.logging.LogWrapperFactory;") - (.println pw) - (.println pw "import com.sun.corba.se.spi.logging.LogWrapperBase;") - (.println pw) - (write-imports exceptions pw) - (.println pw) - (.indent pw) - (.printMsg pw "public class @ extends LogWrapperBase {" - (list class-name)) - (.println pw) - (.printMsg pw "public @( Logger logger )" - (list class-name)) - (.indent pw) - (.println pw "{") - (.undent pw) - (.println pw "super( logger ) ;") - (.println pw "}") - (.println pw) - (.flush pw) - (write-factory-method class-name exception-group-name pw) - (write-exceptions exception-group-name exceptions (get-base exception-group-name) class-name pw) - (.undent pw) - (.println pw ) - (.println pw "}") - (.flush pw) - (.close pw) - ))) - -; Write out the header for the resource file -(define (write-class-header infile package class group pw) - (begin - (if (eqv? group 'OMG) - (.println pw "// Log wrapper class for standard exceptions") - (.printMsg pw "// Log wrapper class for Sun private system exceptions in group @" (list group))) - (.println pw "//") - (.printMsg pw "// Generated by mc.scm version @, DO NOT EDIT BY HAND!" (list version-string)) - (.printMsg pw "// Generated from input file @ on @" (list infile (java.util.Date.))) - (.println pw))) - -(define (write-factory-method class-name exception-group-name pw) - (begin - (.indent pw) - (.println pw "private static LogWrapperFactory factory = new LogWrapperFactory() {") - (.println pw "public LogWrapperBase create( Logger logger )" ) - (.indent pw) - (.println pw "{") - (.undent pw) - (.printMsg pw "return new @( logger ) ;" (list class-name)) - (.undent pw) - (.println pw "}" ) - (.println pw "} ;" ) - (.println pw) - (.printMsg pw "public static @ get( ORB orb, String logDomain )" (list class-name)) - (.indent pw) - (.println pw "{") - (.indent pw) - (.printMsg pw "@ wrapper = " - (list class-name)) - (.indent pw) - (.printMsg pw "(@) orb.getLogWrapper( logDomain, " - (list class-name)) - (.undent pw) - (.undent pw) - (.printMsg pw "\"@\", factory ) ;" - (list exception-group-name)) - (.undent pw) - (.println pw "return wrapper ;" ) - (.println pw "} " ) - (.println pw) - (.printMsg pw "public static @ get( String logDomain )" (list class-name)) - (.indent pw) - (.println pw "{") - (.indent pw) - (.printMsg pw "@ wrapper = " - (list class-name)) - (.indent pw) - (.printMsg pw "(@) ORB.staticGetLogWrapper( logDomain, " - (list class-name)) - (.undent pw) - (.undent pw) - (.printMsg pw "\"@\", factory ) ;" - (list exception-group-name)) - (.undent pw) - (.println pw "return wrapper ;" ) - (.println pw "} " ) - (.println pw))) - -; Write out the import list for the exceptions listed in obj -; obj: the data from the input file -; pw: an IndentingPrintWriter for the output file -(define (write-imports obj pw) - (if (null? obj) - () - (let - ( - (exception (caar obj)) - ) - (begin - (.print pw "import org.omg.CORBA.") - (.print pw exception) - (.println pw " ;") - (write-imports (cdr obj) pw) - )))) - -; Write out the list of exceptions starting with the first one -; obj: the data from the input file -; base: the lambda that returns the string defining the minor code value -; pw: an IndentingPrintWriter for the output file -(define (write-exceptions group-name obj base class-name pw) - (if (null? obj) - () - (let* - ( - (record (car obj)) - (exception (car record)) - (minor-codes (cdr record)) - ) - (begin - (write-exception group-name exception minor-codes base class-name pw) - (write-exceptions group-name (cdr obj) base class-name pw) - )))) - -; Write out a single exception -; exception: the CORBA SystemException type -; base: the base for the minor code value -; minor-codes: a list of minor code data for each minor exception type -; pw: an IndentingPrintWriter for the output file -(define (write-exception group-name exception minor-codes base class-name pw) - (begin - (.println pw "///////////////////////////////////////////////////////////") - (.printMsg pw "// @" (list exception)) - (.println pw "///////////////////////////////////////////////////////////") - (.println pw) - (write-methods group-name exception minor-codes base class-name pw) - (.flush pw))) - -; Write all of the methods for a single exception -; exception: the CORBA SystemException type -; base: the base for the minor code value -; minor-codes: a list of minor code data for each minor exception type -; pw: an IndentingPrintWriter for the output file -(define (write-methods group-name exception minor-codes base class-name pw) - (if (null? minor-codes) - () - (begin - (write-method group-name exception (car minor-codes) base class-name pw) - (write-methods group-name exception (cdr minor-codes) base class-name pw) - ))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Code that writes out the Java methods for exception handling -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Write the methods for a single minor code within an exception -; exception: the CORBA SystemException type -; minor-code: minor code data for one minor exception type -; (name value level explanation) -; base: the base for the minor code value -; pw: an IndentingPrintWriter for the output file -(define (write-method group-name exception minor-code base class-name pw) - (let* - ( - (x (symbol->string (car minor-code))) - (ident (cons x (StringUtil.toMixedCase x))) - (value (cadr minor-code)) - (level (symbol->string (caddr minor-code))) - (explanation (cadddr minor-code)) - (num-params (StringUtil.countArgs explanation))) - (begin - (.printMsg pw "public static final int @ = @ ;" - (list x (base value))) - (.println pw ) - (.flush pw ) - (write-method-status-cause group-name exception ident level num-params class-name pw) - (.println pw) - (.flush pw) - (write-method-status exception ident level num-params pw) - (.println pw) - (.flush pw) - (write-method-cause exception ident level num-params pw) - (.println pw) - (.flush pw) - (write-method-no-args exception ident level num-params pw) - (.println pw) - (.flush pw)))) - -; Construct a string of the form arg1, ..., argn where n is num-params -(define (make-arg-string fixed leading-comma-flag num-args) - (let - ( - (helper (lambda (lcf n) - (let* - ( - (numstr (number->string (- n 1)))) - (if (or lcf (> n 1)) - (string-append ", " fixed numstr) - (string-append " " fixed numstr)))))) - (cond - ((eqv? num-args 0) " ") - ((eqv? num-args 1) (helper leading-comma-flag 1)) - (else (string-append - (make-arg-string fixed leading-comma-flag (- num-args 1)) - (helper leading-comma-flag num-args )))))) - -(define (make-decl-args leading-comma-flag num-args) - (make-arg-string "Object arg" leading-comma-flag num-args)) - -(define (make-call-args leading-comma-flag num-args) - (make-arg-string "arg" leading-comma-flag num-args)) - -; make-xxx-args patterns: -; leading-comma-flag #t -; -; 0 " " -; 1 ", arg0" -; 2 ", arg0, arg1" -; 3 ", arg0, arg1, arg2" -; -; 0 " " -; 1 ", Object arg0" -; 2 ", Object arg0, Object arg1" -; 3 ", Object arg0, Object arg1, Object arg2" -; -; leading-comma-flag #f -; -; 0 " " -; 1 " arg0" -; 2 " arg0, arg1" -; 3 " arg0, arg1, arg2" -; -; 0 " " -; 1 " Object arg0" -; 2 " Object arg0, Object arg1" -; 3 " Object arg0, Object arg1, Object arg2" - -(define (emit-assignments num pw) - (let - ( - (helper - (lambda (n) - (.printMsg pw "parameters[@] = arg@ ;" (list n n))))) - (if (= num 1) - (helper (- num 1)) - (begin - (emit-assignments (- num 1) pw) - (helper (- num 1)))))) - -; Write a method for an exception that takes a CompletionStatus and a cause -; exception: the CORBA system exception type -; id: the identifier for this exception in the form ( ident . mixed-case-ident ) -; level: the logging level -; num-params: number of parameters in the explanation string, which determines -; how many argn parameters we need -; pw: the indenting print writer we are using -(define (write-method-status-cause group-name exception id level num-params class-name pw) - (let* - ( - (ident (car id)) - (ident-mc (cdr id))) - (begin - (.indent pw) - (.printMsg pw "public @ @( CompletionStatus cs, Throwable t@) {" - (list exception ident-mc (make-decl-args #t num-params))) - (.printMsg pw "@ exc = new @( @, cs ) ;" - (list exception exception ident )) - - (.indent pw) - (.println pw "if (t != null)" ) - (.undent pw) - (.println pw "exc.initCause( t ) ;" ) - (.println pw) - - (.indent pw) - (.printMsg pw "if (logger.isLoggable( Level.@ )) {" - (list level)) - - (if (> num-params 0) - (begin - (.printMsg pw "Object[] parameters = new Object[@] ;" - (list (number->string num-params))) - (emit-assignments num-params pw) - ) - (begin - (.println pw "Object[] parameters = null ;" - ))) - - (.indent pw) - (.printMsg pw "doLog( Level.@, \"@.@\"," (list level group-name ident-mc)) - (.undent pw) - (.undent pw) - (.printMsg pw "parameters, @.class, exc ) ;" (list class-name)) - (.println pw "}") - (.println pw) - - (.undent pw) - (.println pw "return exc ;") - - (.println pw "}")))) - -; Write a method for an exception that takes a CompletionStatus. The cause is null. -; -; exception: the CORBA system exception type -; id: the identifier for this exception in the form ( ident . mixed-case-ident ) -; level: the logging level -; num-params: number of parameters in the explanation string, which determines -; how many argn parameters we need -; pw: the indenting print writer we are using -(define (write-method-status exception id level num-params pw) - (let* - ( - (ident-mc (cdr id))) - (begin - (.indent pw) - (.printMsg pw "public @ @( CompletionStatus cs@) {" - (list exception ident-mc (make-decl-args #t num-params))) - (.undent pw) - (.printMsg pw "return @( cs, null@ ) ;" - (list ident-mc (make-call-args #t num-params))) - (.println pw "}")))) - -; Write a method for an exception that takes a cause. The status is COMPLETED_NO. -; -; exception: the CORBA system exception type -; id: the identifier for this exception in the form ( ident . mixed-case-ident ) -; level: the logging level -; num-params: number of parameters in the explanation string, which determines -; how many argn parameters we need -; pw: the indenting print writer we are using -(define (write-method-cause exception id level num-params pw) - (let* - ( - (ident-mc (cdr id))) - (begin - (.indent pw) - (.printMsg pw "public @ @( Throwable t@) {" - (list exception ident-mc (make-decl-args #t num-params))) - (.undent pw) - (.printMsg pw "return @( CompletionStatus.COMPLETED_NO, t@ ) ;" - (list ident-mc (make-call-args #t num-params))) - (.println pw "}")))) - -; Write a method for an exception that takes no arguments. This is COMPLETED_NO and -; a null cause. -; -; exception: the CORBA system exception type -; id: the identifier for this exception in the form ( ident . mixed-case-ident ) -; level: the logging level -; num-params: number of parameters in the explanation string, which determines -; how many argn parameters we need -; pw: the indenting print writer we are using -(define (write-method-no-args exception id level num-params pw) - (let* - ( - (ident-mc (cdr id))) - (begin - (.indent pw) - (.printMsg pw "public @ @( @) {" - (list exception ident-mc (make-decl-args #f num-params))) - (.undent pw) - (.printMsg pw "return @( CompletionStatus.COMPLETED_NO, null@ ) ;" - (list ident-mc (make-call-args #t num-params))) - (.println pw "}")))) - -;;; end of file diff --git a/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/run b/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/run deleted file mode 100644 index 81efed3479a..00000000000 --- a/corba/src/share/classes/com/sun/tools/corba/se/logutil/scripts/run +++ /dev/null @@ -1,2 +0,0 @@ -#! /bin/sh -java -cp ${CLASSPATH}:lib/jscheme.jar:lib/util.jar jscheme.REPL mc.scm diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 21dac82c44e..475bfa37988 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -26,3 +26,4 @@ bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48 8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49 dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50 2581d90c6c9b2012da930eb4742add94a03069a0 jdk7-b51 +1b1e8f1a4fe8cebc01c022484f78148e17b62a0d jdk7-b52 diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java index acbb90d4b66..41e71c2228e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java @@ -118,9 +118,9 @@ public interface Debugger extends SymbolLookup, ThreadAccess { public long getJIntSize(); public long getJLongSize(); public long getJShortSize(); - public long getHeapBase(); public long getHeapOopSize(); - public long getLogMinObjAlignmentInBytes(); + public long getNarrowOopBase(); + public int getNarrowOopShift(); public ReadResult readBytesFromProcess(long address, long numBytes) throws DebuggerException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java index 7b4ca75f431..8f5c732499b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java @@ -56,8 +56,8 @@ public abstract class DebuggerBase implements Debugger { // heap data. protected long oopSize; protected long heapOopSize; - protected long heapBase; // heap base for compressed oops. - protected long logMinObjAlignmentInBytes; // Used to decode compressed oops. + protected long narrowOopBase; // heap base for compressed oops. + protected int narrowOopShift; // shift to decode compressed oops. // Should be initialized if desired by calling initCache() private PageCache cache; @@ -159,10 +159,10 @@ public abstract class DebuggerBase implements Debugger { javaPrimitiveTypesConfigured = true; } - public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignmentInBytes) { - this.heapBase = heapBase; + public void putHeapConst(long heapOopSize, long narrowOopBase, int narrowOopShift) { this.heapOopSize = heapOopSize; - this.logMinObjAlignmentInBytes = logMinObjAlignmentInBytes; + this.narrowOopBase = narrowOopBase; + this.narrowOopShift = narrowOopShift; } /** May be called by subclasses if desired to initialize the page @@ -459,7 +459,7 @@ public abstract class DebuggerBase implements Debugger { long value = readCInteger(address, getHeapOopSize(), true); if (value != 0) { // See oop.inline.hpp decode_heap_oop - value = (long)(heapBase + (long)(value << logMinObjAlignmentInBytes)); + value = (long)(narrowOopBase + (long)(value << narrowOopShift)); } return value; } @@ -545,10 +545,10 @@ public abstract class DebuggerBase implements Debugger { return heapOopSize; } - public long getHeapBase() { - return heapBase; + public long getNarrowOopBase() { + return narrowOopBase; } - public long getLogMinObjAlignmentInBytes() { - return logMinObjAlignmentInBytes; + public int getNarrowOopShift() { + return narrowOopShift; } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java index 679036cdac0..80b71637393 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java @@ -42,5 +42,5 @@ public interface JVMDebugger extends Debugger { long jintSize, long jlongSize, long jshortSize); - public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignment); + public void putHeapConst(long heapOopSize, long narrowOopBase, int narrowOopShift); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java index 179fc1e9d64..df03ce3e01c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java @@ -65,9 +65,10 @@ public interface RemoteDebugger extends Remote { public long getJIntSize() throws RemoteException; public long getJLongSize() throws RemoteException; public long getJShortSize() throws RemoteException; - public long getHeapBase() throws RemoteException; public long getHeapOopSize() throws RemoteException; - public long getLogMinObjAlignmentInBytes() throws RemoteException; + public long getNarrowOopBase() throws RemoteException; + public int getNarrowOopShift() throws RemoteException; + public boolean areThreadsEqual(long addrOrId1, boolean isAddress1, long addrOrId2, boolean isAddress2) throws RemoteException; public int getThreadHashCode(long addrOrId, boolean isAddress) throws RemoteException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java index c1464f3d98c..8a1bacb2fee 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java @@ -85,9 +85,9 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger { jlongSize = remoteDebugger.getJLongSize(); jshortSize = remoteDebugger.getJShortSize(); javaPrimitiveTypesConfigured = true; - heapBase = remoteDebugger.getHeapBase(); + narrowOopBase = remoteDebugger.getNarrowOopBase(); + narrowOopShift = remoteDebugger.getNarrowOopShift(); heapOopSize = remoteDebugger.getHeapOopSize(); - logMinObjAlignmentInBytes = remoteDebugger.getLogMinObjAlignmentInBytes(); } catch (RemoteException e) { throw new DebuggerException(e); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java index cdc5c713619..edb52a65012 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java @@ -114,17 +114,18 @@ public class RemoteDebuggerServer extends UnicastRemoteObject return debugger.getJShortSize(); } - public long getHeapBase() throws RemoteException { - return debugger.getHeapBase(); - } - public long getHeapOopSize() throws RemoteException { return debugger.getHeapOopSize(); } - public long getLogMinObjAlignmentInBytes() throws RemoteException { - return debugger.getLogMinObjAlignmentInBytes(); + public long getNarrowOopBase() throws RemoteException { + return debugger.getNarrowOopBase(); } + + public int getNarrowOopShift() throws RemoteException { + return debugger.getNarrowOopShift(); + } + public boolean areThreadsEqual(long addrOrId1, boolean isAddress1, long addrOrId2, boolean isAddress2) throws RemoteException { ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java index d20dfae7445..b9cdc92ff03 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java @@ -53,7 +53,8 @@ public class Universe { // system obj array klass object private static sun.jvm.hotspot.types.OopField systemObjArrayKlassObjField; - private static AddressField heapBaseField; + private static AddressField narrowOopBaseField; + private static CIntegerField narrowOopShiftField; static { VM.registerVMInitializedObserver(new Observer() { @@ -86,7 +87,8 @@ public class Universe { systemObjArrayKlassObjField = type.getOopField("_systemObjArrayKlassObj"); - heapBaseField = type.getAddressField("_heap_base"); + narrowOopBaseField = type.getAddressField("_narrow_oop._base"); + narrowOopShiftField = type.getCIntegerField("_narrow_oop._shift"); } public Universe() { @@ -100,14 +102,18 @@ public class Universe { } } - public static long getHeapBase() { - if (heapBaseField.getValue() == null) { + public static long getNarrowOopBase() { + if (narrowOopBaseField.getValue() == null) { return 0; } else { - return heapBaseField.getValue().minus(null); + return narrowOopBaseField.getValue().minus(null); } } + public static int getNarrowOopShift() { + return (int)narrowOopShiftField.getValue(); + } + /** Returns "TRUE" iff "p" points into the allocated area of the heap. */ public boolean isIn(Address p) { return heap().isIn(p); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 0272c069352..67a0d47eafd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -342,11 +342,12 @@ public class VM { throw new RuntimeException("Attempt to initialize VM twice"); } soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); - debugger.putHeapConst(Universe.getHeapBase(), soleInstance.getHeapOopSize(), - soleInstance.logMinObjAlignmentInBytes); + debugger.putHeapConst(soleInstance.getHeapOopSize(), Universe.getNarrowOopBase(), + Universe.getNarrowOopShift()); for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { ((Observer) iter.next()).update(null, null); } + } /** This is used by the debugging system */ diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index d0da3b6ce8d..f3f6bc5d15b 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2008 HS_MAJOR_VER=15 HS_MINOR_VER=0 -HS_BUILD_NUMBER=03 +HS_BUILD_NUMBER=04 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index 012015262ae..63320086cd8 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -19,12 +19,12 @@ # Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, # CA 95054 USA or visit www.sun.com if you need additional information or # have any questions. -# +# # # Properties for jprt -# All build result bundles are full jdks, so the 64bit testing does not +# All build result bundles are full jdks, so the 64bit testing does not # need the 32bit sibling bundle installed. # Note: If the hotspot/make/Makefile changed to only bundle the 64bit files # when bundling 64bit, and stripped out the 64bit files from any 32bit @@ -89,60 +89,52 @@ jprt.my.solaris.sparc.test.targets= \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \ - ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese_Xcomp, \ - ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese_Xcomp_2, \ - ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese_Xcomp_3, \ ${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_default, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_default_2, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC_2, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC_2, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC_2, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_CMS_2, \ + ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ + ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_default, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParallelGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParNewGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_CMS, \ + ${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}-{c1|c2}-jbb_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark_2, \ - ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark_3 + ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_G1, \ + ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParOldGC jprt.my.solaris.sparcv9.test.targets= \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.sparcv9}-product-c2-runThese, \ - ${jprt.my.solaris.sparcv9}-product-c2-runThese_Xcomp, \ - ${jprt.my.solaris.sparcv9}-product-c2-runThese_Xcomp_2, \ - ${jprt.my.solaris.sparcv9}-product-c2-runThese_Xcomp_3, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_CMS, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default_2, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_SerialGC_2, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParallelGC_2, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParNewGC_2, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_CMS_2, \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_G1, \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_CMS, \ + ${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_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_CMS, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark_2, \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark_3 + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_G1, \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParOldGC jprt.my.solaris.x64.test.targets= \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98, \ @@ -154,73 +146,80 @@ jprt.my.solaris.x64.test.targets= \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_default_2, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_SerialGC_2, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC_2, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC_2, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_CMS_2, \ + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_G1, \ + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \ + ${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_SerialGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_CMS + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \ + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_G1, \ + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParOldGC jprt.my.solaris.i586.test.targets= \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \ - ${jprt.my.solaris.i586}-product-c2-runThese_Xcomp_2, \ - ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp_2, \ + ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp, \ ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xshare, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_default, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_SerialGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_ParallelGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_ParNewGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_CMS, \ + ${jprt.my.solaris.i586}-product-c1-GCBasher_G1, \ + ${jprt.my.solaris.i586}-product-c1-GCBasher_ParOldGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_default, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_SerialGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParNewGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_CMS, \ + ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_G1, \ + ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParOldGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_default, \ ${jprt.my.solaris.i586}-product-c1-GCOld_SerialGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParallelGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParNewGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_CMS, \ + ${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_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \ - ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark_2, \ - ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark_3 + ${jprt.my.solaris.i586}-fastdebug-c2-jbb_G1, \ + ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParOldGC jprt.my.linux.i586.test.targets = \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.linux.i586}-product-c1-runThese_Xcomp, \ - ${jprt.my.linux.i586}-product-c1-runThese_Xcomp_2, \ - ${jprt.my.linux.i586}-product-c1-runThese_Xcomp_3, \ ${jprt.my.linux.i586}-fastdebug-c1-runThese_Xshare, \ ${jprt.my.linux.i586}-fastdebug-c2-runThese_Xcomp, \ - ${jprt.my.linux.i586}-fastdebug-c2-runThese_Xcomp_2, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_default, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ + ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ + ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_default, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_SerialGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParallelGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParNewGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_CMS, \ + ${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}-c1-jbb_ParallelGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c2-scimark_2, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c2-scimark_3 + ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_G1, \ + ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParOldGC jprt.my.linux.x64.test.targets = \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \ @@ -230,15 +229,19 @@ jprt.my.linux.x64.test.targets = \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ + ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_G1, \ + ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_CMS, \ + ${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_ParallelGC, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark_2, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark_3 + ${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, \ @@ -251,16 +254,20 @@ jprt.my.windows.i586.test.targets = \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ + ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_G1, \ + ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_default, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_SerialGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParallelGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParNewGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_CMS, \ + ${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-{c1|c2}-jbb_ParallelGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \ - ${jprt.my.windows.i586}-product-{c1|c2}-scimark_2, \ - ${jprt.my.windows.i586}-product-{c1|c2}-scimark_3 + ${jprt.my.windows.i586}-product-{c1|c2}-jbb_G1, \ + ${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParOldGC jprt.my.windows.x64.test.targets = \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98, \ @@ -272,16 +279,20 @@ jprt.my.windows.x64.test.targets = \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_CMS, \ + ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_G1, \ + ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_default, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_CMS, \ + ${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-c2-jbb_CMS, \ ${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \ - ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark_2, \ - ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark_3 + ${jprt.my.windows.x64}-product-c2-jbb_G1, \ + ${jprt.my.windows.x64}-product-c2-jbb_ParOldGC # The complete list of test targets for jprt diff --git a/hotspot/make/windows/build_vm_def.sh b/hotspot/make/windows/build_vm_def.sh index 6cc931963b2..99e30bb1b9e 100644 --- a/hotspot/make/windows/build_vm_def.sh +++ b/hotspot/make/windows/build_vm_def.sh @@ -52,6 +52,19 @@ CAT="$MKS_HOME/cat.exe" RM="$MKS_HOME/rm.exe" DUMPBIN="link.exe /dump" +# When called from IDE the first param should contain the link version, otherwise may be nill +if [ "x$1" != "x" ]; then +LINK_VER="$1" +fi + +if [ "x$LINK_VER" != "x800" -a "x$LINK_VER" != "x900" ]; then $DUMPBIN /symbols *.obj | "$GREP" "??_7.*@@6B@" | "$AWK" '{print $7}' | "$SORT" | "$UNIQ" > vm2.def +else +# Can't use pipes when calling cl.exe or link.exe from IDE. Using transit file vm3.def +$DUMPBIN /OUT:vm3.def /symbols *.obj +"$CAT" vm3.def | "$GREP" "??_7.*@@6B@" | "$AWK" '{print $7}' | "$SORT" | "$UNIQ" > vm2.def +"$RM" -f vm3.def +fi + "$CAT" vm1.def vm2.def > vm.def "$RM" -f vm1.def vm2.def diff --git a/hotspot/make/windows/create.bat b/hotspot/make/windows/create.bat index 21f97033669..bdb1916107d 100644 --- a/hotspot/make/windows/create.bat +++ b/hotspot/make/windows/create.bat @@ -72,12 +72,20 @@ REM figure out MSC version for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i echo ************************************************************** +set ProjectFile=vm.vcproj if "%MSC_VER%" == "1200" ( set ProjectFile=vm.dsp echo Will generate VC6 project {unsupported} ) else ( -set ProjectFile=vm.vcproj -echo Will generate VC7 project +if "%MSC_VER%" == "1400" ( +echo Will generate VC8 {Visual Studio 2005} +) else ( +if "%MSC_VER%" == "1500" ( +echo Will generate VC9 {Visual Studio 2008} +) else ( +echo Will generate VC7 project {Visual Studio 2003 .NET} +) +) ) echo %ProjectFile% echo ************************************************************** diff --git a/hotspot/make/windows/get_msc_ver.sh b/hotspot/make/windows/get_msc_ver.sh index 6bbbbef7859..67df0d0dd95 100644 --- a/hotspot/make/windows/get_msc_ver.sh +++ b/hotspot/make/windows/get_msc_ver.sh @@ -29,6 +29,7 @@ # cl version 13.10.3077 returns "MSC_VER=1310" # cl version 14.00.30701 returns "MSC_VER=1399" (OLD_MSSDK version) # cl version 14.00.40310.41 returns "MSC_VER=1400" +# cl version 15.00.21022.8 returns "MSC_VER=1500" # Note that we currently do not have a way to set HotSpotMksHome in # the batch build, but so far this has not seemed to be a problem. The diff --git a/hotspot/make/windows/makefiles/adlc.make b/hotspot/make/windows/makefiles/adlc.make index b6feb0e78b9..e9af2f964bb 100644 --- a/hotspot/make/windows/makefiles/adlc.make +++ b/hotspot/make/windows/makefiles/adlc.make @@ -46,6 +46,7 @@ ADLCFLAGS=-q -T -D_LP64 ADLCFLAGS=-q -T -U_LP64 !endif +CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE CPP_INCLUDE_DIRS=\ /I "..\generated" \ diff --git a/hotspot/make/windows/makefiles/compile.make b/hotspot/make/windows/makefiles/compile.make index ddc9ea11a9f..4906ab5a989 100644 --- a/hotspot/make/windows/makefiles/compile.make +++ b/hotspot/make/windows/makefiles/compile.make @@ -170,10 +170,6 @@ LINK_FLAGS = /manifest $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) # Manifest Tool - used in VS2005 and later to adjust manifests stored # as resources inside build artifacts. MT=mt.exe -!if "$(BUILDARCH)" == "i486" -# VS2005 on x86 restricts the use of certain libc functions without this -CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE -!endif !endif !if "$(COMPILER_NAME)" == "VS2008" @@ -185,10 +181,6 @@ LINK_FLAGS = /manifest $(LINK_FLAGS) # Manifest Tool - used in VS2005 and later to adjust manifests stored # as resources inside build artifacts. MT=mt.exe -!if "$(BUILDARCH)" == "i486" -# VS2005 on x86 restricts the use of certain libc functions without this -CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE -!endif !endif # Compile for space above time. diff --git a/hotspot/make/windows/makefiles/makedeps.make b/hotspot/make/windows/makefiles/makedeps.make index 8bfe00737ab..43f25a4666d 100644 --- a/hotspot/make/windows/makefiles/makedeps.make +++ b/hotspot/make/windows/makefiles/makedeps.make @@ -48,6 +48,8 @@ MakeDepsSources=\ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatform.java \ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC6.java \ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC7.java \ + $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC8.java \ + $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC9.java \ $(WorkSpace)\src\share\tools\MakeDeps\Util.java \ $(WorkSpace)\src\share\tools\MakeDeps\BuildConfig.java \ $(WorkSpace)\src\share\tools\MakeDeps\ArgsParser.java @@ -121,7 +123,7 @@ MakeDepsIDEOptions=\ -additionalFile includeDB_gc_shared \ -additionalFile includeDB_gc_serial \ -additionalGeneratedFile $(HOTSPOTBUILDSPACE)\%f\%b vm.def \ - -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh" \ + -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \ $(MakeDepsIncludesPRIVATE) # Add in build-specific options diff --git a/hotspot/make/windows/makefiles/rules.make b/hotspot/make/windows/makefiles/rules.make index f07f84aee1d..064fb3f231d 100644 --- a/hotspot/make/windows/makefiles/rules.make +++ b/hotspot/make/windows/makefiles/rules.make @@ -42,10 +42,23 @@ COMPILE_RMIC=rmic BOOT_JAVA_HOME= !endif +ProjectFile=vm.vcproj + !if "$(MSC_VER)" == "1200" + VcVersion=VC6 ProjectFile=vm.dsp + +!elseif "$(MSC_VER)" == "1400" + +VcVersion=VC8 + +!elseif "$(MSC_VER)" == "1500" + +VcVersion=VC9 + !else + VcVersion=VC7 -ProjectFile=vm.vcproj + !endif diff --git a/hotspot/make/windows/makefiles/sa.make b/hotspot/make/windows/makefiles/sa.make index c1956057188..1970f116b45 100644 --- a/hotspot/make/windows/makefiles/sa.make +++ b/hotspot/make/windows/makefiles/sa.make @@ -89,9 +89,11 @@ checkAndBuildSA:: $(SAWINDBG) SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 $(GX_OPTION) /Od /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c !elseif "$(BUILDARCH)" == "amd64" SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 $(GX_OPTION) /Od /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +!if "$(COMPILER_NAME)" == "VS2005" # On amd64, VS2005 compiler requires bufferoverflowU.lib on the link command line, # otherwise we get missing __security_check_cookie externals at link time. SA_LINK_FLAGS = bufferoverflowU.lib +!endif !else SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /ZI /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c !endif diff --git a/hotspot/make/windows/makefiles/sanity.make b/hotspot/make/windows/makefiles/sanity.make index 5b4293d27f8..dd5c7499f1d 100644 --- a/hotspot/make/windows/makefiles/sanity.make +++ b/hotspot/make/windows/makefiles/sanity.make @@ -27,9 +27,9 @@ all: checkCL checkLink checkCL: - @ if "$(MSC_VER)" NEQ "1310" if "$(MSC_VER)" NEQ "1399" if "$(MSC_VER)" NEQ "1400" \ + @ if "$(MSC_VER)" NEQ "1310" if "$(MSC_VER)" NEQ "1399" if "$(MSC_VER)" NEQ "1400" if "$(MSC_VER)" NEQ "1500" \ echo *** WARNING *** unrecognized cl.exe version $(MSC_VER) ($(RAW_MSC_VER)). Use FORCE_MSC_VER to override automatic detection. checkLink: - @ if "$(LINK_VER)" NEQ "710" if "$(LINK_VER)" NEQ "800" \ + @ if "$(LINK_VER)" NEQ "710" if "$(LINK_VER)" NEQ "800" if "$(LINK_VER)" NEQ "900" \ echo *** WARNING *** unrecognized link.exe version $(LINK_VER) ($(RAW_LINK_VER)). Use FORCE_LINK_VER to override automatic detection. diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index d9a7cf076da..4a61d2f2c5d 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -2767,6 +2767,268 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, } +void MacroAssembler::check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label& L_success) { + Label L_failure, L_pop_to_failure; + check_klass_subtype_fast_path(sub_klass, super_klass, + temp_reg, temp2_reg, + &L_success, &L_failure, NULL); + Register sub_2 = sub_klass; + Register sup_2 = super_klass; + if (!sub_2->is_global()) sub_2 = L0; + if (!sup_2->is_global()) sup_2 = L1; + + save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); + check_klass_subtype_slow_path(sub_2, sup_2, + L2, L3, L4, L5, + NULL, &L_pop_to_failure); + + // on success: + restore(); + ba(false, L_success); + delayed()->nop(); + + // on failure: + bind(L_pop_to_failure); + restore(); + bind(L_failure); +} + + +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterConstant super_check_offset, + Register instanceof_hack) { + int sc_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::secondary_super_cache_offset_in_bytes()); + int sco_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::super_check_offset_offset_in_bytes()); + + bool must_load_sco = (super_check_offset.constant_or_zero() == -1); + bool need_slow_path = (must_load_sco || + super_check_offset.constant_or_zero() == sco_offset); + + assert_different_registers(sub_klass, super_klass, temp_reg); + if (super_check_offset.is_register()) { + assert_different_registers(sub_klass, super_klass, + super_check_offset.as_register()); + } else if (must_load_sco) { + assert(temp2_reg != noreg, "supply either a temp or a register offset"); + } + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1 || instanceof_hack != noreg || + (L_slow_path == &L_fallthrough && label_nulls <= 2 && !need_slow_path), + "at most one NULL in the batch, usually"); + + // Support for the instanceof hack, which uses delay slots to + // set a destination register to zero or one. + bool do_bool_sets = (instanceof_hack != noreg); +#define BOOL_SET(bool_value) \ + if (do_bool_sets && bool_value >= 0) \ + set(bool_value, instanceof_hack) +#define DELAYED_BOOL_SET(bool_value) \ + if (do_bool_sets && bool_value >= 0) \ + delayed()->set(bool_value, instanceof_hack); \ + else delayed()->nop() + // Hacked ba(), which may only be used just before L_fallthrough. +#define FINAL_JUMP(label, bool_value) \ + if (&(label) == &L_fallthrough) { \ + BOOL_SET(bool_value); \ + } else { \ + ba((do_bool_sets && bool_value >= 0), label); \ + DELAYED_BOOL_SET(bool_value); \ + } + + // If the pointers are equal, we are done (e.g., String[] elements). + // This self-check enables sharing of secondary supertype arrays among + // non-primary types such as array-of-interface. Otherwise, each such + // type would need its own customized SSA. + // We move this check to the front of the fast path because many + // type checks are in fact trivially successful in this manner, + // so we get a nicely predicted branch right at the start of the check. + cmp(super_klass, sub_klass); + brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success); + DELAYED_BOOL_SET(1); + + // Check the supertype display: + if (must_load_sco) { + // The super check offset is always positive... + lduw(super_klass, sco_offset, temp2_reg); + super_check_offset = RegisterConstant(temp2_reg); + } + ld_ptr(sub_klass, super_check_offset, temp_reg); + cmp(super_klass, temp_reg); + + // This check has worked decisively for primary supers. + // Secondary supers are sought in the super_cache ('super_cache_addr'). + // (Secondary supers are interfaces and very deeply nested subtypes.) + // This works in the same check above because of a tricky aliasing + // between the super_cache and the primary super display elements. + // (The 'super_check_addr' can address either, as the case requires.) + // Note that the cache is updated below if it does not help us find + // what we need immediately. + // So if it was a primary super, we can just fail immediately. + // Otherwise, it's the slow path for us (no success at this point). + + if (super_check_offset.is_register()) { + brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success); + delayed(); if (do_bool_sets) BOOL_SET(1); + // if !do_bool_sets, sneak the next cmp into the delay slot: + cmp(super_check_offset.as_register(), sc_offset); + + if (L_failure == &L_fallthrough) { + brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_slow_path); + delayed()->nop(); + BOOL_SET(0); // fallthrough on failure + } else { + brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure); + DELAYED_BOOL_SET(0); + FINAL_JUMP(*L_slow_path, -1); // -1 => vanilla delay slot + } + } else if (super_check_offset.as_constant() == sc_offset) { + // Need a slow path; fast failure is impossible. + if (L_slow_path == &L_fallthrough) { + brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success); + DELAYED_BOOL_SET(1); + } else { + brx(Assembler::notEqual, false, Assembler::pn, *L_slow_path); + delayed()->nop(); + FINAL_JUMP(*L_success, 1); + } + } else { + // No slow path; it's a fast decision. + if (L_failure == &L_fallthrough) { + brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success); + DELAYED_BOOL_SET(1); + BOOL_SET(0); + } else { + brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure); + DELAYED_BOOL_SET(0); + FINAL_JUMP(*L_success, 1); + } + } + + bind(L_fallthrough); + +#undef final_jump +#undef bool_set +#undef DELAYED_BOOL_SET +#undef final_jump +} + + +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register count_temp, + Register scan_temp, + Register scratch_reg, + Register coop_reg, + Label* L_success, + Label* L_failure) { + assert_different_registers(sub_klass, super_klass, + count_temp, scan_temp, scratch_reg, coop_reg); + + Label L_fallthrough, L_loop; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one NULL in the batch"); + + // a couple of useful fields in sub_klass: + int ss_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::secondary_supers_offset_in_bytes()); + int sc_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::secondary_super_cache_offset_in_bytes()); + + // Do a linear scan of the secondary super-klass chain. + // This code is rarely used, so simplicity is a virtue here. + +#ifndef PRODUCT + int* pst_counter = &SharedRuntime::_partial_subtype_ctr; + inc_counter((address) pst_counter, count_temp, scan_temp); +#endif + + // We will consult the secondary-super array. + ld_ptr(sub_klass, ss_offset, scan_temp); + + // Compress superclass if necessary. + Register search_key = super_klass; + bool decode_super_klass = false; + if (UseCompressedOops) { + if (coop_reg != noreg) { + encode_heap_oop_not_null(super_klass, coop_reg); + search_key = coop_reg; + } else { + encode_heap_oop_not_null(super_klass); + decode_super_klass = true; // scarce temps! + } + // The superclass is never null; it would be a basic system error if a null + // pointer were to sneak in here. Note that we have already loaded the + // Klass::super_check_offset from the super_klass in the fast path, + // so if there is a null in that register, we are already in the afterlife. + } + + // Load the array length. (Positive movl does right thing on LP64.) + lduw(scan_temp, arrayOopDesc::length_offset_in_bytes(), count_temp); + + // Check for empty secondary super list + tst(count_temp); + + // Top of search loop + bind(L_loop); + br(Assembler::equal, false, Assembler::pn, *L_failure); + delayed()->add(scan_temp, heapOopSize, scan_temp); + assert(heapOopSize != 0, "heapOopSize should be initialized"); + + // Skip the array header in all array accesses. + int elem_offset = arrayOopDesc::base_offset_in_bytes(T_OBJECT); + elem_offset -= heapOopSize; // the scan pointer was pre-incremented also + + // Load next super to check + if (UseCompressedOops) { + // Don't use load_heap_oop; we don't want to decode the element. + lduw( scan_temp, elem_offset, scratch_reg ); + } else { + ld_ptr( scan_temp, elem_offset, scratch_reg ); + } + + // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list + cmp(scratch_reg, search_key); + + // A miss means we are NOT a subtype and need to keep looping + brx(Assembler::notEqual, false, Assembler::pn, L_loop); + delayed()->deccc(count_temp); // decrement trip counter in delay slot + + // Falling out the bottom means we found a hit; we ARE a subtype + if (decode_super_klass) decode_heap_oop(super_klass); + + // Success. Cache the super we found and proceed in triumph. + st_ptr(super_klass, sub_klass, sc_offset); + + if (L_success != &L_fallthrough) { + ba(false, *L_success); + delayed()->nop(); + } + + bind(L_fallthrough); +} + + + + void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, Register temp_reg, Label& done, Label* slow_case, @@ -4316,7 +4578,13 @@ void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) { void MacroAssembler::encode_heap_oop(Register src, Register dst) { assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); verify_oop(src); + if (Universe::narrow_oop_base() == NULL) { + srlx(src, LogMinObjAlignmentInBytes, dst); + return; + } Label done; if (src == dst) { // optimize for frequent case src == dst @@ -4338,26 +4606,39 @@ void MacroAssembler::encode_heap_oop(Register src, Register dst) { void MacroAssembler::encode_heap_oop_not_null(Register r) { assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); verify_oop(r); - sub(r, G6_heapbase, r); + if (Universe::narrow_oop_base() != NULL) + sub(r, G6_heapbase, r); srlx(r, LogMinObjAlignmentInBytes, r); } void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) { assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); verify_oop(src); - sub(src, G6_heapbase, dst); - srlx(dst, LogMinObjAlignmentInBytes, dst); + if (Universe::narrow_oop_base() == NULL) { + srlx(src, LogMinObjAlignmentInBytes, dst); + } else { + sub(src, G6_heapbase, dst); + srlx(dst, LogMinObjAlignmentInBytes, dst); + } } // Same algorithm as oops.inline.hpp decode_heap_oop. void MacroAssembler::decode_heap_oop(Register src, Register dst) { assert (UseCompressedOops, "must be compressed"); - Label done; + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); sllx(src, LogMinObjAlignmentInBytes, dst); - bpr(rc_nz, true, Assembler::pt, dst, done); - delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken - bind(done); + if (Universe::narrow_oop_base() != NULL) { + Label done; + bpr(rc_nz, true, Assembler::pt, dst, done); + delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken + bind(done); + } verify_oop(dst); } @@ -4366,8 +4647,11 @@ void MacroAssembler::decode_heap_oop_not_null(Register r) { // pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); sllx(r, LogMinObjAlignmentInBytes, r); - add(r, G6_heapbase, r); + if (Universe::narrow_oop_base() != NULL) + add(r, G6_heapbase, r); } void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { @@ -4375,14 +4659,17 @@ void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { // pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); sllx(src, LogMinObjAlignmentInBytes, dst); - add(dst, G6_heapbase, dst); + if (Universe::narrow_oop_base() != NULL) + add(dst, G6_heapbase, dst); } void MacroAssembler::reinit_heapbase() { if (UseCompressedOops) { // call indirectly to solve generation ordering problem - Address base(G6_heapbase, (address)Universe::heap_base_addr()); + Address base(G6_heapbase, (address)Universe::narrow_oop_base_addr()); load_ptr_contents(base, G6_heapbase); } } diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 8f1de780c28..fc05cef68a4 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -2327,6 +2327,46 @@ class MacroAssembler: public Assembler { Register temp_reg, Register temp2_reg, Label& no_such_interface); + // Test sub_klass against super_klass, with fast and slow paths. + + // The fast path produces a tri-state answer: yes / no / maybe-slow. + // One of the three labels can be NULL, meaning take the fall-through. + // If super_check_offset is -1, the value is loaded up from super_klass. + // No registers are killed, except temp_reg and temp2_reg. + // If super_check_offset is not -1, temp2_reg is not used and can be noreg. + void check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterConstant super_check_offset = RegisterConstant(-1), + Register instanceof_hack = noreg); + + // The rest of the type check; must be wired to a corresponding fast path. + // It does not repeat the fast path logic, so don't use it standalone. + // The temp_reg can be noreg, if no temps are available. + // It can also be sub_klass or super_klass, meaning it's OK to kill that one. + // Updates the sub's secondary super cache as necessary. + void check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Register temp3_reg, + Register temp4_reg, + Label* L_success, + Label* L_failure); + + // Simplified, combined version, good for typical uses. + // Falls through on failure. + void check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label& L_success); + + // Stack overflow checking // Note: this clobbers G3_scratch diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index dabea15a087..389acd2ee26 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -2393,23 +2393,11 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { // get instance klass load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL); - // get super_check_offset - load(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), Rtmp1, T_INT, NULL); - // See if we get an immediate positive hit - __ ld_ptr(klass_RInfo, Rtmp1, FrameMap::O7_oop_opr->as_register()); - __ cmp(k_RInfo, O7); - __ br(Assembler::equal, false, Assembler::pn, done); - __ delayed()->nop(); - // check for immediate negative hit - __ cmp(Rtmp1, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); - __ br(Assembler::notEqual, false, Assembler::pn, *stub->entry()); - __ delayed()->nop(); - // check for self - __ cmp(klass_RInfo, k_RInfo); - __ br(Assembler::equal, false, Assembler::pn, done); - __ delayed()->nop(); + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, &done, stub->entry(), NULL); - // assert(sub.is_same(FrameMap::G3_RInfo) && super.is_same(FrameMap::G1_RInfo), "incorrect call setup"); + // call out-of-line instance of __ check_klass_subtype_slow_path(...): + assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); __ delayed()->nop(); __ cmp(G3, 0); @@ -2493,58 +2481,30 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ delayed()->nop(); __ bind(done); } else { + bool need_slow_path = true; if (k->is_loaded()) { - load(klass_RInfo, k->super_check_offset(), Rtmp1, T_OBJECT, NULL); - - if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { - // See if we get an immediate positive hit - __ cmp(Rtmp1, k_RInfo ); - __ br(Assembler::notEqual, false, Assembler::pn, *stub->entry()); - __ delayed()->nop(); - } else { - // See if we get an immediate positive hit - assert_different_registers(Rtmp1, k_RInfo, klass_RInfo); - __ cmp(Rtmp1, k_RInfo ); - __ br(Assembler::equal, false, Assembler::pn, done); - // check for self - __ delayed()->cmp(klass_RInfo, k_RInfo); - __ br(Assembler::equal, false, Assembler::pn, done); - __ delayed()->nop(); - - // assert(sub.is_same(FrameMap::G3_RInfo) && super.is_same(FrameMap::G1_RInfo), "incorrect call setup"); - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); - __ delayed()->nop(); - __ cmp(G3, 0); - __ br(Assembler::equal, false, Assembler::pn, *stub->entry()); - __ delayed()->nop(); - } - __ bind(done); + if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()) + need_slow_path = false; + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg, + (need_slow_path ? &done : NULL), + stub->entry(), NULL, + RegisterConstant(k->super_check_offset())); } else { - assert_different_registers(Rtmp1, klass_RInfo, k_RInfo); - - load(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), Rtmp1, T_INT, NULL); - // See if we get an immediate positive hit - load(klass_RInfo, Rtmp1, FrameMap::O7_oop_opr, T_OBJECT); - __ cmp(k_RInfo, O7); - __ br(Assembler::equal, false, Assembler::pn, done); - __ delayed()->nop(); - // check for immediate negative hit - __ cmp(Rtmp1, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); - __ br(Assembler::notEqual, false, Assembler::pn, *stub->entry()); - // check for self - __ delayed()->cmp(klass_RInfo, k_RInfo); - __ br(Assembler::equal, false, Assembler::pn, done); - __ delayed()->nop(); - - // assert(sub.is_same(FrameMap::G3_RInfo) && super.is_same(FrameMap::G1_RInfo), "incorrect call setup"); + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, + &done, stub->entry(), NULL); + } + if (need_slow_path) { + // call out-of-line instance of __ check_klass_subtype_slow_path(...): + assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); __ delayed()->nop(); __ cmp(G3, 0); __ br(Assembler::equal, false, Assembler::pn, *stub->entry()); __ delayed()->nop(); - __ bind(done); } - + __ bind(done); } __ mov(obj, dst); } else if (code == lir_instanceof) { @@ -2582,58 +2542,32 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ set(0, dst); __ bind(done); } else { + bool need_slow_path = true; if (k->is_loaded()) { - assert_different_registers(Rtmp1, klass_RInfo, k_RInfo); - load(klass_RInfo, k->super_check_offset(), Rtmp1, T_OBJECT, NULL); - - if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { - // See if we get an immediate positive hit - __ cmp(Rtmp1, k_RInfo ); - __ br(Assembler::equal, true, Assembler::pt, done); - __ delayed()->set(1, dst); - __ set(0, dst); - __ bind(done); - } else { - // See if we get an immediate positive hit - assert_different_registers(Rtmp1, k_RInfo, klass_RInfo); - __ cmp(Rtmp1, k_RInfo ); - __ br(Assembler::equal, true, Assembler::pt, done); - __ delayed()->set(1, dst); - // check for self - __ cmp(klass_RInfo, k_RInfo); - __ br(Assembler::equal, true, Assembler::pt, done); - __ delayed()->set(1, dst); - - // assert(sub.is_same(FrameMap::G3_RInfo) && super.is_same(FrameMap::G1_RInfo), "incorrect call setup"); - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); - __ delayed()->nop(); - __ mov(G3, dst); - __ bind(done); - } + if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()) + need_slow_path = false; + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, noreg, + (need_slow_path ? &done : NULL), + (need_slow_path ? &done : NULL), NULL, + RegisterConstant(k->super_check_offset()), + dst); } else { assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); - - load(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), dst, T_INT, NULL); - // See if we get an immediate positive hit - load(klass_RInfo, dst, FrameMap::O7_oop_opr, T_OBJECT); - __ cmp(k_RInfo, O7); - __ br(Assembler::equal, true, Assembler::pt, done); - __ delayed()->set(1, dst); - // check for immediate negative hit - __ cmp(dst, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); - __ br(Assembler::notEqual, true, Assembler::pt, done); - __ delayed()->set(0, dst); - // check for self - __ cmp(klass_RInfo, k_RInfo); - __ br(Assembler::equal, true, Assembler::pt, done); - __ delayed()->set(1, dst); - - // assert(sub.is_same(FrameMap::G3_RInfo) && super.is_same(FrameMap::G1_RInfo), "incorrect call setup"); + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, dst, + &done, &done, NULL, + RegisterConstant(-1), + dst); + } + if (need_slow_path) { + // call out-of-line instance of __ check_klass_subtype_slow_path(...): + assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); __ delayed()->nop(); __ mov(G3, dst); - __ bind(done); } + __ bind(done); } } else { ShouldNotReachHere(); diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 489e84dd58c..6dfb8efbc7c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -714,38 +714,19 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // sub : G3, argument, destroyed // super: G1, argument, not changed // raddr: O7, blown by call - Label loop, miss; + Label miss; __ save_frame(0); // Blow no registers! - __ ld_ptr( G3, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), L3 ); - __ lduw(L3,arrayOopDesc::length_offset_in_bytes(),L0); // length in l0 - __ add(L3,arrayOopDesc::base_offset_in_bytes(T_OBJECT),L1); // ptr into array - __ clr(L4); // Index - // Load a little early; will load 1 off the end of the array. - // Ok for now; revisit if we have other uses of this routine. - __ ld_ptr(L1,0,L2); // Will load a little early - - // The scan loop - __ bind(loop); - __ add(L1,wordSize,L1); // Bump by OOP size - __ cmp(L4,L0); - __ br(Assembler::equal,false,Assembler::pn,miss); - __ delayed()->inc(L4); // Bump index - __ subcc(L2,G1,L3); // Check for match; zero in L3 for a hit - __ brx( Assembler::notEqual, false, Assembler::pt, loop ); - __ delayed()->ld_ptr(L1,0,L2); // Will load a little early - - // Got a hit; report success; set cache - __ st_ptr( G1, G3, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); + __ check_klass_subtype_slow_path(G3, G1, L0, L1, L2, L4, NULL, &miss); __ mov(1, G3); - __ ret(); // Result in G5 is ok; flags set + __ ret(); // Result in G5 is 'true' __ delayed()->restore(); // free copy or add can go here __ bind(miss); __ mov(0, G3); - __ ret(); // Result in G5 is ok; flags set + __ ret(); // Result in G5 is 'false' __ delayed()->restore(); // free copy or add can go here } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index dee9fcc3cd0..e843d3fad8b 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -866,65 +866,18 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rtmp2, Register Rtmp3, Label &ok_is_subtype ) { - Label not_subtype, loop; + Label not_subtype; // Profile the not-null value's klass. profile_typecheck(Rsub_klass, Rtmp1); - // Load the super-klass's check offset into Rtmp1 - ld( Rsuper_klass, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), Rtmp1 ); - // Load from the sub-klass's super-class display list, or a 1-word cache of - // the secondary superclass list, or a failing value with a sentinel offset - // if the super-klass is an interface or exceptionally deep in the Java - // hierarchy and we have to scan the secondary superclass list the hard way. - ld_ptr( Rsub_klass, Rtmp1, Rtmp2 ); - // See if we get an immediate positive hit - cmp( Rtmp2, Rsuper_klass ); - brx( Assembler::equal, false, Assembler::pt, ok_is_subtype ); - // In the delay slot, check for immediate negative hit - delayed()->cmp( Rtmp1, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); - br( Assembler::notEqual, false, Assembler::pt, not_subtype ); - // In the delay slot, check for self - delayed()->cmp( Rsub_klass, Rsuper_klass ); - brx( Assembler::equal, false, Assembler::pt, ok_is_subtype ); + check_klass_subtype_fast_path(Rsub_klass, Rsuper_klass, + Rtmp1, Rtmp2, + &ok_is_subtype, ¬_subtype, NULL); - // Now do a linear scan of the secondary super-klass chain. - delayed()->ld_ptr( Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), Rtmp2 ); - - // compress superclass - if (UseCompressedOops) encode_heap_oop(Rsuper_klass); - - // Rtmp2 holds the objArrayOop of secondary supers. - ld( Rtmp2, arrayOopDesc::length_offset_in_bytes(), Rtmp1 );// Load the array length - // Check for empty secondary super list - tst(Rtmp1); - - // Top of search loop - bind( loop ); - br( Assembler::equal, false, Assembler::pn, not_subtype ); - delayed()->nop(); - - // load next super to check - if (UseCompressedOops) { - lduw( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); - // Bump array pointer forward one oop - add( Rtmp2, 4, Rtmp2 ); - } else { - ld_ptr( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); - // Bump array pointer forward one oop - add( Rtmp2, wordSize, Rtmp2); - } - // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list - cmp( Rtmp3, Rsuper_klass ); - // A miss means we are NOT a subtype and need to keep looping - brx( Assembler::notEqual, false, Assembler::pt, loop ); - delayed()->deccc( Rtmp1 ); // dec trip counter in delay slot - // Falling out the bottom means we found a hit; we ARE a subtype - if (UseCompressedOops) decode_heap_oop(Rsuper_klass); - br( Assembler::always, false, Assembler::pt, ok_is_subtype ); - // Update the cache - delayed()->st_ptr( Rsuper_klass, Rsub_klass, - sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); + check_klass_subtype_slow_path(Rsub_klass, Rsuper_klass, + Rtmp1, Rtmp2, Rtmp3, /*hack:*/ noreg, + &ok_is_subtype, NULL); bind(not_subtype); profile_typecheck_failed(Rtmp1); diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index f9631ddf61d..df6e9049ebb 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -547,7 +547,11 @@ int MachCallDynamicJavaNode::ret_addr_offset() { int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); int klass_load_size; if (UseCompressedOops) { - klass_load_size = 3*BytesPerInstWord; // see MacroAssembler::load_klass() + assert(Universe::heap() != NULL, "java heap should be initialized"); + if (Universe::narrow_oop_base() == NULL) + klass_load_size = 2*BytesPerInstWord; // see MacroAssembler::load_klass() + else + klass_load_size = 3*BytesPerInstWord; } else { klass_load_size = 1*BytesPerInstWord; } @@ -1601,9 +1605,11 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { st->print_cr("\nUEP:"); #ifdef _LP64 if (UseCompressedOops) { + assert(Universe::heap() != NULL, "java heap should be initialized"); st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); st->print_cr("\tSLL R_G5,3,R_G5"); - st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5"); + if (Universe::narrow_oop_base() != NULL) + st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5"); } else { st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); } @@ -2502,7 +2508,11 @@ encode %{ __ load_klass(O0, G3_scratch); int klass_load_size; if (UseCompressedOops) { - klass_load_size = 3*BytesPerInstWord; + assert(Universe::heap() != NULL, "java heap should be initialized"); + if (Universe::narrow_oop_base() == NULL) + klass_load_size = 2*BytesPerInstWord; + else + klass_load_size = 3*BytesPerInstWord; } else { klass_load_size = 1*BytesPerInstWord; } @@ -9005,6 +9015,33 @@ instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, note ins_pipe(long_memory_op); %} + +//---------- Population Count Instructions ------------------------------------- + +instruct popCountI(iRegI dst, iRegI src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + format %{ "POPC $src, $dst" %} + ins_encode %{ + __ popc($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(iRegI dst, iRegL src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + + format %{ "POPC $src, $dst" %} + ins_encode %{ + __ popc($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + + // ============================================================================ //------------Bytes reverse-------------------------------------------------- diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 9b4981dff7a..e4a3806da86 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -900,19 +900,7 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", "partial_subtype_check"); address start = __ pc(); - Label loop, miss; - - // Compare super with sub directly, since super is not in its own SSA. - // The compiler used to emit this test, but we fold it in here, - // to increase overall code density, with no real loss of speed. - { Label L; - __ cmp(O1, O2); - __ brx(Assembler::notEqual, false, Assembler::pt, L); - __ delayed()->nop(); - __ retl(); - __ delayed()->addcc(G0,0,O0); // set Z flags, zero result - __ bind(L); - } + Label miss; #if defined(COMPILER2) && !defined(_LP64) // Do not use a 'save' because it blows the 64-bit O registers. @@ -936,56 +924,12 @@ class StubGenerator: public StubCodeGenerator { Register L2_super = L2; Register L3_index = L3; -#ifdef _LP64 - Register L4_ooptmp = L4; + __ check_klass_subtype_slow_path(Rsub, Rsuper, + L0, L1, L2, L3, + NULL, &miss); - if (UseCompressedOops) { - // this must be under UseCompressedOops check, as we rely upon fact - // that L4 not clobbered in C2 on 32-bit platforms, where we do explicit save - // on stack, see several lines above - __ encode_heap_oop(Rsuper, L4_ooptmp); - } -#endif - - inc_counter_np(SharedRuntime::_partial_subtype_ctr, L0, L1); - - __ ld_ptr( Rsub, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), L3 ); - __ lduw(L3,arrayOopDesc::length_offset_in_bytes(),L0_ary_len); - __ add(L3,arrayOopDesc::base_offset_in_bytes(T_OBJECT),L1_ary_ptr); - __ clr(L3_index); // zero index - // Load a little early; will load 1 off the end of the array. - // Ok for now; revisit if we have other uses of this routine. - if (UseCompressedOops) { - __ lduw(L1_ary_ptr,0,L2_super);// Will load a little early - } else { - __ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early - } - - assert(heapOopSize != 0, "heapOopSize should be initialized"); - // The scan loop - __ BIND(loop); - __ add(L1_ary_ptr, heapOopSize, L1_ary_ptr); // Bump by OOP size - __ cmp(L3_index,L0_ary_len); - __ br(Assembler::equal,false,Assembler::pn,miss); - __ delayed()->inc(L3_index); // Bump index - - if (UseCompressedOops) { -#ifdef _LP64 - __ subcc(L2_super,L4_ooptmp,Rret); // Check for match; zero in Rret for a hit - __ br( Assembler::notEqual, false, Assembler::pt, loop ); - __ delayed()->lduw(L1_ary_ptr,0,L2_super);// Will load a little early -#else - ShouldNotReachHere(); -#endif - } else { - __ subcc(L2_super,Rsuper,Rret); // Check for match; zero in Rret for a hit - __ brx( Assembler::notEqual, false, Assembler::pt, loop ); - __ delayed()->ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early - } - - // Got a hit; report success; set cache. Cache load doesn't - // happen here; for speed it is directly emitted by the compiler. - __ st_ptr( Rsuper, Rsub, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); + // Match falls through here. + __ addcc(G0,0,Rret); // set Z flags, Z result #if defined(COMPILER2) && !defined(_LP64) __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0); @@ -999,7 +943,6 @@ class StubGenerator: public StubCodeGenerator { __ delayed()->restore(); #endif - // Hit or miss falls through here __ BIND(miss); __ addcc(G0,1,Rret); // set NZ flags, NZ result @@ -2330,51 +2273,31 @@ class StubGenerator: public StubCodeGenerator { Register super_check_offset, Register super_klass, Register temp, - Label& L_success, - Register deccc_hack = noreg) { + Label& L_success) { assert_different_registers(sub_klass, super_check_offset, super_klass, temp); BLOCK_COMMENT("type_check:"); - Label L_miss; + Label L_miss, L_pop_to_miss; assert_clean_int(super_check_offset, temp); - // maybe decrement caller's trip count: -#define DELAY_SLOT delayed(); \ - { if (deccc_hack == noreg) __ nop(); else __ deccc(deccc_hack); } - - // if the pointers are equal, we are done (e.g., String[] elements) - __ cmp(sub_klass, super_klass); - __ brx(Assembler::equal, true, Assembler::pt, L_success); - __ DELAY_SLOT; - - // check the supertype display: - __ ld_ptr(sub_klass, super_check_offset, temp); // query the super type - __ cmp(super_klass, temp); // test the super type - __ brx(Assembler::equal, true, Assembler::pt, L_success); - __ DELAY_SLOT; - - int sc_offset = (klassOopDesc::header_size() * HeapWordSize + - Klass::secondary_super_cache_offset_in_bytes()); - __ cmp(super_klass, sc_offset); - __ brx(Assembler::notEqual, true, Assembler::pt, L_miss); - __ delayed()->nop(); + __ check_klass_subtype_fast_path(sub_klass, super_klass, temp, noreg, + &L_success, &L_miss, NULL, + super_check_offset); + BLOCK_COMMENT("type_check_slow_path:"); __ save_frame(0); - __ mov(sub_klass->after_save(), O1); - // mov(super_klass->after_save(), O2); //fill delay slot - assert(StubRoutines::Sparc::_partial_subtype_check != NULL, "order of generation"); - __ call(StubRoutines::Sparc::_partial_subtype_check); - __ delayed()->mov(super_klass->after_save(), O2); + __ check_klass_subtype_slow_path(sub_klass->after_save(), + super_klass->after_save(), + L0, L1, L2, L4, + NULL, &L_pop_to_miss); + __ ba(false, L_success); + __ delayed()->restore(); + + __ bind(L_pop_to_miss); __ restore(); - // Upon return, the condition codes are already set. - __ brx(Assembler::equal, true, Assembler::pt, L_success); - __ DELAY_SLOT; - -#undef DELAY_SLOT - // Fall through on failure! __ BIND(L_miss); } @@ -2411,7 +2334,7 @@ class StubGenerator: public StubCodeGenerator { gen_write_ref_array_pre_barrier(O1, O2); #ifdef ASSERT - // We sometimes save a frame (see partial_subtype_check below). + // We sometimes save a frame (see generate_type_check below). // If this will cause trouble, let's fail now instead of later. __ save_frame(0); __ restore(); @@ -2455,41 +2378,39 @@ class StubGenerator: public StubCodeGenerator { // G3, G4, G5 --- current oop, oop.klass, oop.klass.super __ align(16); - __ bind(store_element); - // deccc(G1_remain); // decrement the count (hoisted) + __ BIND(store_element); + __ deccc(G1_remain); // decrement the count __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop __ inc(O5_offset, heapOopSize); // step to next offset __ brx(Assembler::zero, true, Assembler::pt, do_card_marks); __ delayed()->set(0, O0); // return -1 on success // ======== loop entry is here ======== - __ bind(load_element); + __ BIND(load_element); __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop __ br_null(G3_oop, true, Assembler::pt, store_element); - __ delayed()->deccc(G1_remain); // decrement the count + __ delayed()->nop(); __ load_klass(G3_oop, G4_klass); // query the object klass generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super, // branch to this on success: - store_element, - // decrement this on success: - G1_remain); + store_element); // ======== end loop ======== // It was a real error; we must depend on the caller to finish the job. // Register G1 has number of *remaining* oops, O2 number of *total* oops. // Emit GC store barriers for the oops we have copied (O2 minus G1), // and report their number to the caller. - __ bind(fail); + __ BIND(fail); __ subcc(O2_count, G1_remain, O2_count); __ brx(Assembler::zero, false, Assembler::pt, done); __ delayed()->not1(O2_count, O0); // report (-1^K) to caller - __ bind(do_card_marks); + __ BIND(do_card_marks); gen_write_ref_array_post_barrier(O1_to, O2_count, O3); // store check on O1[0..O2] - __ bind(done); + __ BIND(done); inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4); __ retl(); __ delayed()->nop(); // return value in 00 @@ -2942,14 +2863,15 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry; StubRoutines::_fence_entry = generate_fence(); #endif // COMPILER2 !=> _LP64 - - StubRoutines::Sparc::_partial_subtype_check = generate_partial_subtype_check(); } void generate_all() { // Generates all stubs and initializes the entry points + // Generate partial_subtype_check first here since its code depends on + // UseZeroBaseCompressedOops which is defined after heap initialization. + StubRoutines::Sparc::_partial_subtype_check = generate_partial_subtype_check(); // These entry points require SharedInfo::stack0 to be set up in non-core builds StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false); StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index a870c7dc15b..dc7f6b5bdbe 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,9 @@ void VM_Version::initialize() { FLAG_SET_ERGO(bool, UseCompressedOops, false); } } + // 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. + Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); #endif // _LP64 #ifdef COMPILER2 // Indirect branch is the same cost as direct @@ -89,16 +92,26 @@ void VM_Version::initialize() { #endif } + // Use hardware population count instruction if available. + if (has_hardware_popc()) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + UsePopCountInstruction = true; + } + } + char buf[512]; - jio_snprintf(buf, sizeof(buf), "%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", (has_v8() ? ", has_v8" : ""), (has_v9() ? ", has_v9" : ""), + (has_hardware_popc() ? ", popc" : ""), (has_vis1() ? ", has_vis1" : ""), (has_vis2() ? ", has_vis2" : ""), (is_ultra3() ? ", is_ultra3" : ""), (is_sun4v() ? ", is_sun4v" : ""), (is_niagara1() ? ", is_niagara1" : ""), - (!has_hardware_int_muldiv() ? ", no-muldiv" : ""), + (is_niagara1_plus() ? ", is_niagara1_plus" : ""), + (!has_hardware_mul32() ? ", no-mul32" : ""), + (!has_hardware_div32() ? ", no-div32" : ""), (!has_hardware_fsmuld() ? ", no-fsmuld" : "")); // buf is started with ", " or is empty diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index 050e7e68fcc..e057c608ce8 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,34 +25,38 @@ class VM_Version: public Abstract_VM_Version { protected: enum Feature_Flag { - v8_instructions = 0, - hardware_int_muldiv = 1, - hardware_fsmuld = 2, - v9_instructions = 3, - vis1_instructions = 4, - vis2_instructions = 5, - sun4v_instructions = 6 + v8_instructions = 0, + hardware_mul32 = 1, + hardware_div32 = 2, + hardware_fsmuld = 3, + hardware_popc = 4, + v9_instructions = 5, + vis1_instructions = 6, + vis2_instructions = 7, + sun4v_instructions = 8 }; enum Feature_Flag_Set { - unknown_m = 0, - all_features_m = -1, + unknown_m = 0, + all_features_m = -1, - v8_instructions_m = 1 << v8_instructions, - hardware_int_muldiv_m = 1 << hardware_int_muldiv, - hardware_fsmuld_m = 1 << hardware_fsmuld, - v9_instructions_m = 1 << v9_instructions, - vis1_instructions_m = 1 << vis1_instructions, - vis2_instructions_m = 1 << vis2_instructions, - sun4v_m = 1 << sun4v_instructions, + v8_instructions_m = 1 << v8_instructions, + hardware_mul32_m = 1 << hardware_mul32, + hardware_div32_m = 1 << hardware_div32, + hardware_fsmuld_m = 1 << hardware_fsmuld, + hardware_popc_m = 1 << hardware_popc, + v9_instructions_m = 1 << v9_instructions, + vis1_instructions_m = 1 << vis1_instructions, + vis2_instructions_m = 1 << vis2_instructions, + sun4v_m = 1 << sun4v_instructions, - generic_v8_m = v8_instructions_m | hardware_int_muldiv_m | hardware_fsmuld_m, - generic_v9_m = generic_v8_m | v9_instructions_m | vis1_instructions_m, - ultra3_m = generic_v9_m | vis2_instructions_m, + generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m, + generic_v9_m = generic_v8_m | v9_instructions_m, + ultra3_m = generic_v9_m | vis1_instructions_m | vis2_instructions_m, // Temporary until we have something more accurate - niagara1_unique_m = sun4v_m, - niagara1_m = generic_v9_m | niagara1_unique_m + niagara1_unique_m = sun4v_m, + niagara1_m = generic_v9_m | niagara1_unique_m }; static int _features; @@ -62,7 +66,7 @@ protected: static int determine_features(); static int platform_features(int features); - static bool is_niagara1(int features) { return (features & niagara1_m) == niagara1_m; } + static bool is_niagara1(int features) { return (features & sun4v_m) != 0; } static int maximum_niagara1_processor_count() { return 32; } // Returns true if the platform is in the niagara line and @@ -76,8 +80,10 @@ public: // Instruction support static bool has_v8() { return (_features & v8_instructions_m) != 0; } static bool has_v9() { return (_features & v9_instructions_m) != 0; } - static bool has_hardware_int_muldiv() { return (_features & hardware_int_muldiv_m) != 0; } + static bool has_hardware_mul32() { return (_features & hardware_mul32_m) != 0; } + static bool has_hardware_div32() { return (_features & hardware_div32_m) != 0; } static bool has_hardware_fsmuld() { return (_features & hardware_fsmuld_m) != 0; } + 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; } diff --git a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp index df9262ccbbd..ce2c8532d08 100644 --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -221,13 +221,15 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { if (is_vtable_stub) { // ld;ld;ld,jmp,nop const int basic = 5*BytesPerInstWord + - // shift;add for load_klass - (UseCompressedOops ? 2*BytesPerInstWord : 0); + // shift;add for load_klass (only shift with zero heap based) + (UseCompressedOops ? + ((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0); return basic + slop; } else { const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + - // shift;add for load_klass - (UseCompressedOops ? 2*BytesPerInstWord : 0); + // shift;add for load_klass (only shift with zero heap based) + (UseCompressedOops ? + ((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0); return (basic + slop); } } diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 46c5a24f45a..b043c9d3506 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -727,7 +727,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { } #ifdef _LP64 - assert(false, "fix locate_operand"); + assert(which == narrow_oop_operand && !is_64bit, "instruction is not a movl adr, imm32"); #else assert(which == imm_operand, "instruction has only an imm field"); #endif // LP64 @@ -2193,6 +2193,25 @@ void Assembler::pop(Register dst) { emit_byte(0x58 | encode); } +void Assembler::popcntl(Register dst, Address src) { + assert(VM_Version::supports_popcnt(), "must support"); + InstructionMark im(this); + emit_byte(0xF3); + prefix(src, dst); + emit_byte(0x0F); + emit_byte(0xB8); + emit_operand(dst, src); +} + +void Assembler::popcntl(Register dst, Register src) { + assert(VM_Version::supports_popcnt(), "must support"); + emit_byte(0xF3); + int encode = prefix_and_encode(dst->encoding(), src->encoding()); + emit_byte(0x0F); + emit_byte(0xB8); + emit_byte(0xC0 | encode); +} + void Assembler::popf() { emit_byte(0x9D); } @@ -3224,12 +3243,6 @@ void Assembler::fyl2x() { emit_byte(0xF1); } -void Assembler::mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec, int format) { - InstructionMark im(this); - int encode = prefix_and_encode(dst->encoding()); - emit_byte(0xB8 | encode); - emit_data((int)imm32, rspec, format); -} #ifndef _LP64 @@ -3249,6 +3262,12 @@ void Assembler::mov_literal32(Address dst, int32_t imm32, RelocationHolder cons emit_data((int)imm32, rspec, 0); } +void Assembler::mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); + int encode = prefix_and_encode(dst->encoding()); + emit_byte(0xB8 | encode); + emit_data((int)imm32, rspec, 0); +} void Assembler::popa() { // 32bit emit_byte(0x61); @@ -3857,6 +3876,37 @@ void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder con emit_data64(imm64, rspec); } +void Assembler::mov_narrow_oop(Register dst, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); + int encode = prefix_and_encode(dst->encoding()); + emit_byte(0xB8 | encode); + emit_data((int)imm32, rspec, narrow_oop_operand); +} + +void Assembler::mov_narrow_oop(Address dst, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); + prefix(dst); + emit_byte(0xC7); + emit_operand(rax, dst, 4); + emit_data((int)imm32, rspec, narrow_oop_operand); +} + +void Assembler::cmp_narrow_oop(Register src1, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); + int encode = prefix_and_encode(src1->encoding()); + emit_byte(0x81); + emit_byte(0xF8 | encode); + emit_data((int)imm32, rspec, narrow_oop_operand); +} + +void Assembler::cmp_narrow_oop(Address src1, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); + prefix(src1); + emit_byte(0x81); + emit_operand(rax, src1, 4); + emit_data((int)imm32, rspec, narrow_oop_operand); +} + void Assembler::movdq(XMMRegister dst, Register src) { // table D-1 says MMX/SSE2 NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); @@ -4049,6 +4099,25 @@ void Assembler::popa() { // 64bit addq(rsp, 16 * wordSize); } +void Assembler::popcntq(Register dst, Address src) { + assert(VM_Version::supports_popcnt(), "must support"); + InstructionMark im(this); + emit_byte(0xF3); + prefixq(src, dst); + emit_byte(0x0F); + emit_byte(0xB8); + emit_operand(dst, src); +} + +void Assembler::popcntq(Register dst, Register src) { + assert(VM_Version::supports_popcnt(), "must support"); + emit_byte(0xF3); + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); + emit_byte(0x0F); + emit_byte(0xB8); + emit_byte(0xC0 | encode); +} + void Assembler::popq(Address dst) { InstructionMark im(this); prefixq(dst); @@ -7217,6 +7286,225 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, } +void MacroAssembler::check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp_reg, + Label& L_success) { + Label L_failure; + check_klass_subtype_fast_path(sub_klass, super_klass, temp_reg, &L_success, &L_failure, NULL); + check_klass_subtype_slow_path(sub_klass, super_klass, temp_reg, noreg, &L_success, NULL); + bind(L_failure); +} + + +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterConstant super_check_offset) { + assert_different_registers(sub_klass, super_klass, temp_reg); + bool must_load_sco = (super_check_offset.constant_or_zero() == -1); + if (super_check_offset.is_register()) { + assert_different_registers(sub_klass, super_klass, + super_check_offset.as_register()); + } else if (must_load_sco) { + assert(temp_reg != noreg, "supply either a temp or a register offset"); + } + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one NULL in the batch"); + + int sc_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::secondary_super_cache_offset_in_bytes()); + int sco_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::super_check_offset_offset_in_bytes()); + Address super_check_offset_addr(super_klass, sco_offset); + + // Hacked jcc, which "knows" that L_fallthrough, at least, is in + // range of a jccb. If this routine grows larger, reconsider at + // least some of these. +#define local_jcc(assembler_cond, label) \ + if (&(label) == &L_fallthrough) jccb(assembler_cond, label); \ + else jcc( assembler_cond, label) /*omit semi*/ + + // Hacked jmp, which may only be used just before L_fallthrough. +#define final_jmp(label) \ + if (&(label) == &L_fallthrough) { /*do nothing*/ } \ + else jmp(label) /*omit semi*/ + + // If the pointers are equal, we are done (e.g., String[] elements). + // This self-check enables sharing of secondary supertype arrays among + // non-primary types such as array-of-interface. Otherwise, each such + // type would need its own customized SSA. + // We move this check to the front of the fast path because many + // type checks are in fact trivially successful in this manner, + // so we get a nicely predicted branch right at the start of the check. + cmpptr(sub_klass, super_klass); + local_jcc(Assembler::equal, *L_success); + + // Check the supertype display: + if (must_load_sco) { + // Positive movl does right thing on LP64. + movl(temp_reg, super_check_offset_addr); + super_check_offset = RegisterConstant(temp_reg); + } + Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); + cmpptr(super_klass, super_check_addr); // load displayed supertype + + // This check has worked decisively for primary supers. + // Secondary supers are sought in the super_cache ('super_cache_addr'). + // (Secondary supers are interfaces and very deeply nested subtypes.) + // This works in the same check above because of a tricky aliasing + // between the super_cache and the primary super display elements. + // (The 'super_check_addr' can address either, as the case requires.) + // Note that the cache is updated below if it does not help us find + // what we need immediately. + // So if it was a primary super, we can just fail immediately. + // Otherwise, it's the slow path for us (no success at this point). + + if (super_check_offset.is_register()) { + local_jcc(Assembler::equal, *L_success); + cmpl(super_check_offset.as_register(), sc_offset); + if (L_failure == &L_fallthrough) { + local_jcc(Assembler::equal, *L_slow_path); + } else { + local_jcc(Assembler::notEqual, *L_failure); + final_jmp(*L_slow_path); + } + } else if (super_check_offset.as_constant() == sc_offset) { + // Need a slow path; fast failure is impossible. + if (L_slow_path == &L_fallthrough) { + local_jcc(Assembler::equal, *L_success); + } else { + local_jcc(Assembler::notEqual, *L_slow_path); + final_jmp(*L_success); + } + } else { + // No slow path; it's a fast decision. + if (L_failure == &L_fallthrough) { + local_jcc(Assembler::equal, *L_success); + } else { + local_jcc(Assembler::notEqual, *L_failure); + final_jmp(*L_success); + } + } + + bind(L_fallthrough); + +#undef local_jcc +#undef final_jmp +} + + +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + bool set_cond_codes) { + assert_different_registers(sub_klass, super_klass, temp_reg); + if (temp2_reg != noreg) + assert_different_registers(sub_klass, super_klass, temp_reg, temp2_reg); +#define IS_A_TEMP(reg) ((reg) == temp_reg || (reg) == temp2_reg) + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one NULL in the batch"); + + // a couple of useful fields in sub_klass: + int ss_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::secondary_supers_offset_in_bytes()); + int sc_offset = (klassOopDesc::header_size() * HeapWordSize + + Klass::secondary_super_cache_offset_in_bytes()); + Address secondary_supers_addr(sub_klass, ss_offset); + Address super_cache_addr( sub_klass, sc_offset); + + // Do a linear scan of the secondary super-klass chain. + // This code is rarely used, so simplicity is a virtue here. + // The repne_scan instruction uses fixed registers, which we must spill. + // Don't worry too much about pre-existing connections with the input regs. + + assert(sub_klass != rax, "killed reg"); // killed by mov(rax, super) + assert(sub_klass != rcx, "killed reg"); // killed by lea(rcx, &pst_counter) + + // Get super_klass value into rax (even if it was in rdi or rcx). + bool pushed_rax = false, pushed_rcx = false, pushed_rdi = false; + if (super_klass != rax || UseCompressedOops) { + if (!IS_A_TEMP(rax)) { push(rax); pushed_rax = true; } + mov(rax, super_klass); + } + if (!IS_A_TEMP(rcx)) { push(rcx); pushed_rcx = true; } + if (!IS_A_TEMP(rdi)) { push(rdi); pushed_rdi = true; } + +#ifndef PRODUCT + int* pst_counter = &SharedRuntime::_partial_subtype_ctr; + ExternalAddress pst_counter_addr((address) pst_counter); + NOT_LP64( incrementl(pst_counter_addr) ); + LP64_ONLY( lea(rcx, pst_counter_addr) ); + LP64_ONLY( incrementl(Address(rcx, 0)) ); +#endif //PRODUCT + + // We will consult the secondary-super array. + movptr(rdi, secondary_supers_addr); + // Load the array length. (Positive movl does right thing on LP64.) + movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); + // Skip to start of data. + addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + + // Scan RCX words at [RDI] for an occurrence of RAX. + // Set NZ/Z based on last compare. +#ifdef _LP64 + // This part is tricky, as values in supers array could be 32 or 64 bit wide + // and we store values in objArrays always encoded, thus we need to encode + // the value of rax before repne. Note that rax is dead after the repne. + if (UseCompressedOops) { + encode_heap_oop_not_null(rax); + // The superclass is never null; it would be a basic system error if a null + // pointer were to sneak in here. Note that we have already loaded the + // Klass::super_check_offset from the super_klass in the fast path, + // so if there is a null in that register, we are already in the afterlife. + repne_scanl(); + } else +#endif // _LP64 + repne_scan(); + + // Unspill the temp. registers: + if (pushed_rdi) pop(rdi); + if (pushed_rcx) pop(rcx); + if (pushed_rax) pop(rax); + + if (set_cond_codes) { + // Special hack for the AD files: rdi is guaranteed non-zero. + assert(!pushed_rdi, "rdi must be left non-NULL"); + // Also, the condition codes are properly set Z/NZ on succeed/failure. + } + + if (L_failure == &L_fallthrough) + jccb(Assembler::notEqual, *L_failure); + else jcc(Assembler::notEqual, *L_failure); + + // Success. Cache the super we found and proceed in triumph. + movptr(super_cache_addr, super_klass); + + if (L_success != &L_fallthrough) { + jmp(*L_success); + } + +#undef IS_A_TEMP + + bind(L_fallthrough); +} + + void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { ucomisd(dst, as_Address(src)); } @@ -7710,14 +7998,21 @@ void MacroAssembler::load_klass(Register dst, Register src) { void MacroAssembler::load_prototype_header(Register dst, Register src) { #ifdef _LP64 if (UseCompressedOops) { + assert (Universe::heap() != NULL, "java heap should be initialized"); movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); - movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + if (Universe::narrow_oop_shift() != 0) { + assert(Address::times_8 == LogMinObjAlignmentInBytes && + Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); + movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + } else { + movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + } } else #endif - { - movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); - movptr(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); - } + { + movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); + movptr(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + } } void MacroAssembler::store_klass(Register dst, Register src) { @@ -7760,11 +8055,20 @@ void MacroAssembler::store_heap_oop(Address dst, Register src) { // Algorithm must match oop.inline.hpp encode_heap_oop. void MacroAssembler::encode_heap_oop(Register r) { assert (UseCompressedOops, "should be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + if (Universe::narrow_oop_base() == NULL) { + verify_oop(r, "broken oop in encode_heap_oop"); + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shrq(r, LogMinObjAlignmentInBytes); + } + return; + } #ifdef ASSERT if (CheckCompressedOops) { Label ok; push(rscratch1); // cmpptr trashes rscratch1 - cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); + cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); jcc(Assembler::equal, ok); stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); bind(ok); @@ -7780,6 +8084,7 @@ void MacroAssembler::encode_heap_oop(Register r) { void MacroAssembler::encode_heap_oop_not_null(Register r) { assert (UseCompressedOops, "should be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); #ifdef ASSERT if (CheckCompressedOops) { Label ok; @@ -7790,12 +8095,18 @@ void MacroAssembler::encode_heap_oop_not_null(Register r) { } #endif verify_oop(r, "broken oop in encode_heap_oop_not_null"); - subq(r, r12_heapbase); - shrq(r, LogMinObjAlignmentInBytes); + if (Universe::narrow_oop_base() != NULL) { + subq(r, r12_heapbase); + } + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shrq(r, LogMinObjAlignmentInBytes); + } } void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { assert (UseCompressedOops, "should be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); #ifdef ASSERT if (CheckCompressedOops) { Label ok; @@ -7809,18 +8120,32 @@ void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { if (dst != src) { movq(dst, src); } - subq(dst, r12_heapbase); - shrq(dst, LogMinObjAlignmentInBytes); + if (Universe::narrow_oop_base() != NULL) { + subq(dst, r12_heapbase); + } + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shrq(dst, LogMinObjAlignmentInBytes); + } } void MacroAssembler::decode_heap_oop(Register r) { assert (UseCompressedOops, "should be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + if (Universe::narrow_oop_base() == NULL) { + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shlq(r, LogMinObjAlignmentInBytes); + } + verify_oop(r, "broken oop in decode_heap_oop"); + return; + } #ifdef ASSERT if (CheckCompressedOops) { Label ok; push(rscratch1); cmpptr(r12_heapbase, - ExternalAddress((address)Universe::heap_base_addr())); + ExternalAddress((address)Universe::narrow_oop_base_addr())); jcc(Assembler::equal, ok); stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); bind(ok); @@ -7844,32 +8169,76 @@ void MacroAssembler::decode_heap_oop(Register r) { void MacroAssembler::decode_heap_oop_not_null(Register r) { assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. - assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); - leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); + if (Universe::narrow_oop_base() == NULL) { + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shlq(r, LogMinObjAlignmentInBytes); + } + } else { + assert (Address::times_8 == LogMinObjAlignmentInBytes && + Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); + leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); + } } void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. - assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); - leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); + if (Universe::narrow_oop_shift() != 0) { + assert (Address::times_8 == LogMinObjAlignmentInBytes && + Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); + leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); + } else if (dst != src) { + movq(dst, src); + } } void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { - assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); int oop_index = oop_recorder()->find_index(obj); RelocationHolder rspec = oop_Relocation::spec(oop_index); - mov_literal32(dst, oop_index, rspec, narrow_oop_operand); + mov_narrow_oop(dst, oop_index, rspec); +} + +void MacroAssembler::set_narrow_oop(Address dst, jobject obj) { + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + mov_narrow_oop(dst, oop_index, rspec); +} + +void MacroAssembler::cmp_narrow_oop(Register dst, jobject obj) { + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + Assembler::cmp_narrow_oop(dst, oop_index, rspec); +} + +void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) { + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + Assembler::cmp_narrow_oop(dst, oop_index, rspec); } void MacroAssembler::reinit_heapbase() { if (UseCompressedOops) { - movptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); + movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); } } #endif // _LP64 diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 546f8464efe..9b54b800ba1 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -578,20 +578,25 @@ private: // These are all easily abused and hence protected - void mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec, int format = 0); - // 32BIT ONLY SECTION #ifndef _LP64 // Make these disappear in 64bit mode since they would never be correct void cmp_literal32(Register src1, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY void cmp_literal32(Address src1, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY + void mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY void mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY void push_literal32(int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY #else // 64BIT ONLY SECTION void mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec); // 64BIT ONLY + + void cmp_narrow_oop(Register src1, int32_t imm32, RelocationHolder const& rspec); + void cmp_narrow_oop(Address src1, int32_t imm32, RelocationHolder const& rspec); + + void mov_narrow_oop(Register dst, int32_t imm32, RelocationHolder const& rspec); + void mov_narrow_oop(Address dst, int32_t imm32, RelocationHolder const& rspec); #endif // _LP64 // These are unique in that we are ensured by the caller that the 32bit @@ -1219,6 +1224,14 @@ private: void popq(Address dst); #endif + void popcntl(Register dst, Address src); + void popcntl(Register dst, Register src); + +#ifdef _LP64 + void popcntq(Register dst, Address src); + void popcntq(Register dst, Register src); +#endif + // Prefetches (SSE, SSE2, 3DNOW only) void prefetchnta(Address src); @@ -1647,6 +1660,9 @@ class MacroAssembler: public Assembler { void decode_heap_oop_not_null(Register dst, Register src); void set_narrow_oop(Register dst, jobject obj); + void set_narrow_oop(Address dst, jobject obj); + void cmp_narrow_oop(Register dst, jobject obj); + void cmp_narrow_oop(Address dst, jobject obj); // if heap base register is used - reinit it with the correct value void reinit_heapbase(); @@ -1791,6 +1807,40 @@ class MacroAssembler: public Assembler { Register scan_temp, Label& no_such_interface); + // Test sub_klass against super_klass, with fast and slow paths. + + // The fast path produces a tri-state answer: yes / no / maybe-slow. + // One of the three labels can be NULL, meaning take the fall-through. + // If super_check_offset is -1, the value is loaded up from super_klass. + // No registers are killed, except temp_reg. + void check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterConstant super_check_offset = RegisterConstant(-1)); + + // The rest of the type check; must be wired to a corresponding fast path. + // It does not repeat the fast path logic, so don't use it standalone. + // The temp_reg and temp2_reg can be noreg, if no temps are available. + // Updates the sub's secondary super cache as necessary. + // If set_cond_codes, condition codes will be Z on success, NZ on failure. + void check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + bool set_cond_codes = false); + + // Simplified, combined version, good for typical uses. + // Falls through on failure. + void check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp_reg, + Label& L_success); + //---- void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0 diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 64091052211..51a951d9725 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -1598,18 +1598,9 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { // get instance klass __ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc))); - // get super_check_offset - __ movl(Rtmp1, Address(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes())); - // See if we get an immediate positive hit - __ cmpptr(k_RInfo, Address(klass_RInfo, Rtmp1, Address::times_1)); - __ jcc(Assembler::equal, done); - // check for immediate negative hit - __ cmpl(Rtmp1, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); - __ jcc(Assembler::notEqual, *stub->entry()); - // check for self - __ cmpptr(klass_RInfo, k_RInfo); - __ jcc(Assembler::equal, done); - + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, stub->entry(), NULL); + // call out-of-line instance of __ check_klass_subtype_slow_path(...): __ push(klass_RInfo); __ push(k_RInfo); __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); @@ -1735,17 +1726,9 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { } __ bind(done); } else { - __ movl(Rtmp1, Address(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes())); - // See if we get an immediate positive hit - __ cmpptr(k_RInfo, Address(klass_RInfo, Rtmp1, Address::times_1)); - __ jcc(Assembler::equal, done); - // check for immediate negative hit - __ cmpl(Rtmp1, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); - __ jcc(Assembler::notEqual, *stub->entry()); - // check for self - __ cmpptr(klass_RInfo, k_RInfo); - __ jcc(Assembler::equal, done); - + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, stub->entry(), NULL); + // call out-of-line instance of __ check_klass_subtype_slow_path(...): __ push(klass_RInfo); __ push(k_RInfo); __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); @@ -1821,23 +1804,15 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { __ pop(dst); __ jmp(done); } - } else { -#else - { // YUCK + } + else // next block is unconditional if LP64: #endif // LP64 + { assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); - __ movl(dst, Address(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes())); - // See if we get an immediate positive hit - __ cmpptr(k_RInfo, Address(klass_RInfo, dst, Address::times_1)); - __ jcc(Assembler::equal, one); - // check for immediate negative hit - __ cmpl(dst, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); - __ jcc(Assembler::notEqual, zero); - // check for self - __ cmpptr(klass_RInfo, k_RInfo); - __ jcc(Assembler::equal, one); - + // perform the fast part of the checking logic + __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, dst, &one, &zero, NULL); + // call out-of-line instance of __ check_klass_subtype_slow_path(...): __ push(klass_RInfo); __ push(k_RInfo); __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index 3edbcbbd194..3a447754ede 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1354,6 +1354,13 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { case slow_subtype_check_id: { + // Typical calling sequence: + // __ push(klass_RInfo); // object klass or other subclass + // __ push(sup_k_RInfo); // array element klass or other superclass + // __ call(slow_subtype_check); + // Note that the subclass is pushed first, and is therefore deepest. + // Previous versions of this code reversed the names 'sub' and 'super'. + // This was operationally harmless but made the code unreadable. enum layout { rax_off, SLOT2(raxH_off) rcx_off, SLOT2(rcxH_off) @@ -1361,9 +1368,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { rdi_off, SLOT2(rdiH_off) // saved_rbp_off, SLOT2(saved_rbpH_off) return_off, SLOT2(returnH_off) - sub_off, SLOT2(subH_off) - super_off, SLOT2(superH_off) - framesize + sup_k_off, SLOT2(sup_kH_off) + klass_off, SLOT2(superH_off) + framesize, + result_off = klass_off // deepest argument is also the return value }; __ set_info("slow_subtype_check", dont_gc_arguments); @@ -1373,19 +1381,14 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ push(rax); // This is called by pushing args and not with C abi - __ movptr(rsi, Address(rsp, (super_off) * VMRegImpl::stack_slot_size)); // super - __ movptr(rax, Address(rsp, (sub_off ) * VMRegImpl::stack_slot_size)); // sub - - __ movptr(rdi,Address(rsi,sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())); - // since size is postive movl does right thing on 64bit - __ movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); - __ addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + __ movptr(rsi, Address(rsp, (klass_off) * VMRegImpl::stack_slot_size)); // subclass + __ movptr(rax, Address(rsp, (sup_k_off) * VMRegImpl::stack_slot_size)); // superclass Label miss; - __ repne_scan(); - __ jcc(Assembler::notEqual, miss); - __ movptr(Address(rsi,sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()), rax); - __ movptr(Address(rsp, (super_off) * VMRegImpl::stack_slot_size), 1); // result + __ check_klass_subtype_slow_path(rsi, rax, rcx, rdi, NULL, &miss); + + // fallthrough on success: + __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), 1); // result __ pop(rax); __ pop(rcx); __ pop(rsi); @@ -1393,7 +1396,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ ret(0); __ bind(miss); - __ movptr(Address(rsp, (super_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result + __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result __ pop(rax); __ pop(rcx); __ pop(rsi); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp index 4ad44f693b0..bb14db9056f 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp @@ -219,47 +219,16 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, R // Resets EDI to locals. Register sub_klass cannot be any of the above. void InterpreterMacroAssembler::gen_subtype_check( Register Rsub_klass, Label &ok_is_subtype ) { assert( Rsub_klass != rax, "rax, holds superklass" ); - assert( Rsub_klass != rcx, "rcx holds 2ndary super array length" ); - assert( Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr" ); - Label not_subtype, loop; + assert( Rsub_klass != rcx, "used as a temp" ); + assert( Rsub_klass != rdi, "used as a temp, restored from locals" ); // Profile the not-null value's klass. - profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, rdi + profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, reloads rdi - // Load the super-klass's check offset into ECX - movl( rcx, Address(rax, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes() ) ); - // Load from the sub-klass's super-class display list, or a 1-word cache of - // the secondary superclass list, or a failing value with a sentinel offset - // if the super-klass is an interface or exceptionally deep in the Java - // hierarchy and we have to scan the secondary superclass list the hard way. - // See if we get an immediate positive hit - cmpptr( rax, Address(Rsub_klass,rcx,Address::times_1) ); - jcc( Assembler::equal,ok_is_subtype ); + // Do the check. + check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx - // Check for immediate negative hit - cmpl( rcx, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); - jcc( Assembler::notEqual, not_subtype ); - // Check for self - cmpptr( Rsub_klass, rax ); - jcc( Assembler::equal, ok_is_subtype ); - - // Now do a linear scan of the secondary super-klass chain. - movptr( rdi, Address(Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes()) ); - // EDI holds the objArrayOop of secondary supers. - movl( rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));// Load the array length - // Skip to start of data; also clear Z flag incase ECX is zero - addptr( rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT) ); - // Scan ECX words at [EDI] for occurance of EAX - // Set NZ/Z based on last compare - repne_scan(); - restore_locals(); // Restore EDI; Must not blow flags - // Not equal? - jcc( Assembler::notEqual, not_subtype ); - // Must be equal but missed in cache. Update cache. - movptr( Address(Rsub_klass, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()), rax ); - jmp( ok_is_subtype ); - - bind(not_subtype); + // Profile the failure of the check. profile_typecheck_failed(rcx); // blows rcx } diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp index c0f0ec6fec3..56bd0c8c9eb 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -232,65 +232,13 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, assert(Rsub_klass != rcx, "rcx holds 2ndary super array length"); assert(Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr"); - Label not_subtype, not_subtype_pop, loop; - // Profile the not-null value's klass. - profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, rdi + profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, reloads rdi - // Load the super-klass's check offset into rcx - movl(rcx, Address(rax, sizeof(oopDesc) + - Klass::super_check_offset_offset_in_bytes())); - // Load from the sub-klass's super-class display list, or a 1-word - // cache of the secondary superclass list, or a failing value with a - // sentinel offset if the super-klass is an interface or - // exceptionally deep in the Java hierarchy and we have to scan the - // secondary superclass list the hard way. See if we get an - // immediate positive hit - cmpptr(rax, Address(Rsub_klass, rcx, Address::times_1)); - jcc(Assembler::equal,ok_is_subtype); + // Do the check. + check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx - // Check for immediate negative hit - cmpl(rcx, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); - jcc( Assembler::notEqual, not_subtype ); - // Check for self - cmpptr(Rsub_klass, rax); - jcc(Assembler::equal, ok_is_subtype); - - // Now do a linear scan of the secondary super-klass chain. - movptr(rdi, Address(Rsub_klass, sizeof(oopDesc) + - Klass::secondary_supers_offset_in_bytes())); - // rdi holds the objArrayOop of secondary supers. - // Load the array length - movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); - // Skip to start of data; also clear Z flag incase rcx is zero - addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - // Scan rcx words at [rdi] for occurance of rax - // Set NZ/Z based on last compare - - // this part is kind tricky, as values in supers array could be 32 or 64 bit wide - // and we store values in objArrays always encoded, thus we need to encode value - // before repne - if (UseCompressedOops) { - push(rax); - encode_heap_oop(rax); - repne_scanl(); - // Not equal? - jcc(Assembler::notEqual, not_subtype_pop); - // restore heap oop here for movq - pop(rax); - } else { - repne_scan(); - jcc(Assembler::notEqual, not_subtype); - } - // Must be equal but missed in cache. Update cache. - movptr(Address(Rsub_klass, sizeof(oopDesc) + - Klass::secondary_super_cache_offset_in_bytes()), rax); - jmp(ok_is_subtype); - - bind(not_subtype_pop); - // restore heap oop here for miss - if (UseCompressedOops) pop(rax); - bind(not_subtype); + // Profile the failure of the check. profile_typecheck_failed(rcx); // blows rcx } diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp index e3c8c6be94b..04f87f3bbab 100644 --- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp @@ -349,7 +349,7 @@ class SlowSignatureHandler if (_num_args < Argument::n_float_register_parameters_c-1) { *_reg_args++ = from_obj; - *_fp_identifiers |= (0x01 << (_num_args*2)); // mark as float + *_fp_identifiers |= (intptr_t)(0x01 << (_num_args*2)); // mark as float _num_args++; } else { *_to++ = from_obj; @@ -364,7 +364,7 @@ class SlowSignatureHandler if (_num_args < Argument::n_float_register_parameters_c-1) { *_reg_args++ = from_obj; - *_fp_identifiers |= (0x3 << (_num_args*2)); // mark as double + *_fp_identifiers |= (intptr_t)(0x3 << (_num_args*2)); // mark as double _num_args++; } else { *_to++ = from_obj; diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 870355a4ab4..aca93778050 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -1310,81 +1310,51 @@ class StubGenerator: public StubCodeGenerator { Address& super_check_offset_addr, Address& super_klass_addr, Register temp, - Label* L_success_ptr, Label* L_failure_ptr) { + Label* L_success, Label* L_failure) { BLOCK_COMMENT("type_check:"); Label L_fallthrough; - bool fall_through_on_success = (L_success_ptr == NULL); - if (fall_through_on_success) { - L_success_ptr = &L_fallthrough; - } else { - L_failure_ptr = &L_fallthrough; - } - Label& L_success = *L_success_ptr; - Label& L_failure = *L_failure_ptr; +#define LOCAL_JCC(assembler_con, label_ptr) \ + if (label_ptr != NULL) __ jcc(assembler_con, *(label_ptr)); \ + else __ jcc(assembler_con, L_fallthrough) /*omit semi*/ + // The following is a strange variation of the fast path which requires + // one less register, because needed values are on the argument stack. + // __ check_klass_subtype_fast_path(sub_klass, *super_klass*, temp, + // L_success, L_failure, NULL); assert_different_registers(sub_klass, temp); - // a couple of useful fields in sub_klass: - int ss_offset = (klassOopDesc::header_size() * HeapWordSize + - Klass::secondary_supers_offset_in_bytes()); int sc_offset = (klassOopDesc::header_size() * HeapWordSize + Klass::secondary_super_cache_offset_in_bytes()); - Address secondary_supers_addr(sub_klass, ss_offset); - Address super_cache_addr( sub_klass, sc_offset); // if the pointers are equal, we are done (e.g., String[] elements) __ cmpptr(sub_klass, super_klass_addr); - __ jcc(Assembler::equal, L_success); + LOCAL_JCC(Assembler::equal, L_success); // check the supertype display: __ movl2ptr(temp, super_check_offset_addr); Address super_check_addr(sub_klass, temp, Address::times_1, 0); __ movptr(temp, super_check_addr); // load displayed supertype __ cmpptr(temp, super_klass_addr); // test the super type - __ jcc(Assembler::equal, L_success); + LOCAL_JCC(Assembler::equal, L_success); // if it was a primary super, we can just fail immediately __ cmpl(super_check_offset_addr, sc_offset); - __ jcc(Assembler::notEqual, L_failure); + LOCAL_JCC(Assembler::notEqual, L_failure); - // Now do a linear scan of the secondary super-klass chain. - // This code is rarely used, so simplicity is a virtue here. - inc_counter_np(SharedRuntime::_partial_subtype_ctr); - { - // The repne_scan instruction uses fixed registers, which we must spill. - // (We need a couple more temps in any case.) - __ push(rax); - __ push(rcx); - __ push(rdi); - assert_different_registers(sub_klass, rax, rcx, rdi); + // The repne_scan instruction uses fixed registers, which will get spilled. + // We happen to know this works best when super_klass is in rax. + Register super_klass = temp; + __ movptr(super_klass, super_klass_addr); + __ check_klass_subtype_slow_path(sub_klass, super_klass, noreg, noreg, + L_success, L_failure); - __ movptr(rdi, secondary_supers_addr); - // Load the array length. - __ movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); - // Skip to start of data. - __ addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - // Scan rcx words at [edi] for occurance of rax, - // Set NZ/Z based on last compare - __ movptr(rax, super_klass_addr); - __ repne_scan(); - - // Unspill the temp. registers: - __ pop(rdi); - __ pop(rcx); - __ pop(rax); - } - __ jcc(Assembler::notEqual, L_failure); - - // Success. Cache the super we found and proceed in triumph. - __ movptr(temp, super_klass_addr); // note: rax, is dead - __ movptr(super_cache_addr, temp); - - if (!fall_through_on_success) - __ jmp(L_success); - - // Fall through on failure! __ bind(L_fallthrough); + + if (L_success == NULL) { BLOCK_COMMENT("L_success:"); } + if (L_failure == NULL) { BLOCK_COMMENT("L_failure:"); } + +#undef LOCAL_JCC } // diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 03f8a3c0d20..73d60542a4d 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -2091,66 +2091,9 @@ class StubGenerator: public StubCodeGenerator { Label L_miss; - // a couple of useful fields in sub_klass: - int ss_offset = (klassOopDesc::header_size() * HeapWordSize + - Klass::secondary_supers_offset_in_bytes()); - int sc_offset = (klassOopDesc::header_size() * HeapWordSize + - Klass::secondary_super_cache_offset_in_bytes()); - Address secondary_supers_addr(sub_klass, ss_offset); - Address super_cache_addr( sub_klass, sc_offset); - - // if the pointers are equal, we are done (e.g., String[] elements) - __ cmpptr(super_klass, sub_klass); - __ jcc(Assembler::equal, L_success); - - // check the supertype display: - Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); - __ cmpptr(super_klass, super_check_addr); // test the super type - __ jcc(Assembler::equal, L_success); - - // if it was a primary super, we can just fail immediately - __ cmpl(super_check_offset, sc_offset); - __ jcc(Assembler::notEqual, L_miss); - - // Now do a linear scan of the secondary super-klass chain. - // The repne_scan instruction uses fixed registers, which we must spill. - // (We need a couple more temps in any case.) - // This code is rarely used, so simplicity is a virtue here. - inc_counter_np(SharedRuntime::_partial_subtype_ctr); - { - __ push(rax); - __ push(rcx); - __ push(rdi); - assert_different_registers(sub_klass, super_klass, rax, rcx, rdi); - - __ movptr(rdi, secondary_supers_addr); - // Load the array length. - __ movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); - // Skip to start of data. - __ addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - // Scan rcx words at [rdi] for occurance of rax - // Set NZ/Z based on last compare - __ movptr(rax, super_klass); - if (UseCompressedOops) { - // Compare against compressed form. Don't need to uncompress because - // looks like orig rax is restored in popq below. - __ encode_heap_oop(rax); - __ repne_scanl(); - } else { - __ repne_scan(); - } - - // Unspill the temp. registers: - __ pop(rdi); - __ pop(rcx); - __ pop(rax); - - __ jcc(Assembler::notEqual, L_miss); - } - - // Success. Cache the super we found and proceed in triumph. - __ movptr(super_cache_addr, super_klass); // note: rax is dead - __ jmp(L_success); + __ check_klass_subtype_fast_path(sub_klass, super_klass, noreg, &L_success, &L_miss, NULL, + super_check_offset); + __ check_klass_subtype_slow_path(sub_klass, super_klass, noreg, noreg, &L_success, NULL); // Fall through on failure! __ BIND(L_miss); diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index cf112067fe4..1307dd1e54f 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -284,7 +284,7 @@ void VM_Version::get_processor_features() { } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -297,6 +297,7 @@ void VM_Version::get_processor_features() { (supports_ssse3()? ", ssse3": ""), (supports_sse4_1() ? ", sse4.1" : ""), (supports_sse4_2() ? ", sse4.2" : ""), + (supports_popcnt() ? ", popcnt" : ""), (supports_mmx_ext() ? ", mmxext" : ""), (supports_3dnow() ? ", 3dnow" : ""), (supports_3dnow2() ? ", 3dnowext" : ""), @@ -410,6 +411,13 @@ void VM_Version::get_processor_features() { } } + // Use population count instruction if available. + if (supports_popcnt()) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + UsePopCountInstruction = true; + } + } + assert(0 <= ReadPrefetchInstr && ReadPrefetchInstr <= 3, "invalid value"); assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value"); diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp index bf876fc92a6..7b6206b0e32 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp @@ -70,7 +70,9 @@ public: dca : 1, sse4_1 : 1, sse4_2 : 1, - : 11; + : 2, + popcnt : 1, + : 8; } bits; }; @@ -179,7 +181,8 @@ protected: CPU_SSSE3 = (1 << 9), CPU_SSE4A = (1 << 10), CPU_SSE4_1 = (1 << 11), - CPU_SSE4_2 = (1 << 12) + CPU_SSE4_2 = (1 << 12), + CPU_POPCNT = (1 << 13) } cpuFeatureFlags; // cpuid information block. All info derived from executing cpuid with @@ -290,6 +293,8 @@ protected: result |= CPU_SSE4_1; if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0) result |= CPU_SSE4_2; + if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0) + result |= CPU_POPCNT; return result; } @@ -379,6 +384,7 @@ public: static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; } static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; } static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; } + static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; } // // AMD features // diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 1e770159226..479adb1cbfd 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -1483,16 +1483,20 @@ encode %{ // main source block for now. In future, we can generalize this by // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class OpcP %{ // Emit opcode - emit_opcode(cbuf,$primary); + + // Emit primary opcode + enc_class OpcP %{ + emit_opcode(cbuf, $primary); %} - enc_class OpcS %{ // Emit opcode - emit_opcode(cbuf,$secondary); + // Emit secondary opcode + enc_class OpcS %{ + emit_opcode(cbuf, $secondary); %} - enc_class Opcode(immI d8 ) %{ // Emit opcode - emit_opcode(cbuf,$d8$$constant); + // Emit opcode directly + enc_class Opcode(immI d8) %{ + emit_opcode(cbuf, $d8$$constant); %} enc_class SizePrefix %{ @@ -1688,26 +1692,15 @@ encode %{ Register Reax = as_Register(EAX_enc); // super class Register Recx = as_Register(ECX_enc); // killed Register Resi = as_Register(ESI_enc); // sub class - Label hit, miss; + Label miss; MacroAssembler _masm(&cbuf); - // Compare super with sub directly, since super is not in its own SSA. - // The compiler used to emit this test, but we fold it in here, - // to allow platform-specific tweaking on sparc. - __ cmpptr(Reax, Resi); - __ jcc(Assembler::equal, hit); -#ifndef PRODUCT - __ incrementl(ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr)); -#endif //PRODUCT - __ movptr(Redi,Address(Resi,sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())); - __ movl(Recx,Address(Redi,arrayOopDesc::length_offset_in_bytes())); - __ addptr(Redi,arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - __ repne_scan(); - __ jcc(Assembler::notEqual, miss); - __ movptr(Address(Resi,sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()),Reax); - __ bind(hit); - if( $primary ) - __ xorptr(Redi,Redi); + __ check_klass_subtype_slow_path(Resi, Reax, Recx, Redi, + NULL, &miss, + /*set_cond_codes:*/ true); + if ($primary) { + __ xorptr(Redi, Redi); + } __ bind(miss); %} @@ -6387,6 +6380,67 @@ instruct bytes_reverse_long(eRegL dst) %{ %} +//---------- Population Count Instructions ------------------------------------- + +instruct popCountI(eRegI dst, eRegI src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + format %{ "POPCNT $dst, $src" %} + ins_encode %{ + __ popcntl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct popCountI_mem(eRegI dst, memory mem) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI (LoadI mem))); + + format %{ "POPCNT $dst, $mem" %} + ins_encode %{ + __ popcntl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(eRegI dst, eRegL src, eRegI tmp, eFlagsReg cr) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + effect(KILL cr, TEMP tmp, TEMP dst); + + format %{ "POPCNT $dst, $src.lo\n\t" + "POPCNT $tmp, $src.hi\n\t" + "ADD $dst, $tmp" %} + ins_encode %{ + __ popcntl($dst$$Register, $src$$Register); + __ popcntl($tmp$$Register, HIGH_FROM_LOW($src$$Register)); + __ addl($dst$$Register, $tmp$$Register); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL_mem(eRegI dst, memory mem, eRegI tmp, eFlagsReg cr) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL (LoadL mem))); + effect(KILL cr, TEMP tmp, TEMP dst); + + format %{ "POPCNT $dst, $mem\n\t" + "POPCNT $tmp, $mem+4\n\t" + "ADD $dst, $tmp" %} + ins_encode %{ + //__ popcntl($dst$$Register, $mem$$Address$$first); + //__ popcntl($tmp$$Register, $mem$$Address$$second); + __ popcntl($dst$$Register, Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, false)); + __ popcntl($tmp$$Register, Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, false)); + __ addl($dst$$Register, $tmp$$Register); + %} + ins_pipe(ialu_reg); +%} + + //----------Load/Store/Move Instructions--------------------------------------- //----------Load Instructions-------------------------------------------------- // Load Byte (8bit signed) @@ -12501,15 +12555,12 @@ instruct partialSubtypeCheck( eDIRegP result, eSIRegP sub, eAXRegP super, eCXReg effect( KILL rcx, KILL cr ); ins_cost(1100); // slightly larger than the next version - format %{ "CMPL EAX,ESI\n\t" - "JEQ,s hit\n\t" - "MOV EDI,[$sub+Klass::secondary_supers]\n\t" + format %{ "MOV EDI,[$sub+Klass::secondary_supers]\n\t" "MOV ECX,[EDI+arrayKlass::length]\t# length to scan\n\t" "ADD EDI,arrayKlass::base_offset\t# Skip to start of data; set NZ in case count is zero\n\t" "REPNE SCASD\t# Scan *EDI++ for a match with EAX while CX-- != 0\n\t" "JNE,s miss\t\t# Missed: EDI not-zero\n\t" "MOV [$sub+Klass::secondary_super_cache],$super\t# Hit: update cache\n\t" - "hit:\n\t" "XOR $result,$result\t\t Hit: EDI zero\n\t" "miss:\t" %} @@ -12523,9 +12574,7 @@ instruct partialSubtypeCheck_vs_Zero( eFlagsReg cr, eSIRegP sub, eAXRegP super, effect( KILL rcx, KILL result ); ins_cost(1000); - format %{ "CMPL EAX,ESI\n\t" - "JEQ,s miss\t# Actually a hit; we are done.\n\t" - "MOV EDI,[$sub+Klass::secondary_supers]\n\t" + format %{ "MOV EDI,[$sub+Klass::secondary_supers]\n\t" "MOV ECX,[EDI+arrayKlass::length]\t# length to scan\n\t" "ADD EDI,arrayKlass::base_offset\t# Skip to start of data; set NZ in case count is zero\n\t" "REPNE SCASD\t# Scan *EDI++ for a match with EAX while CX-- != 0\n\t" diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 6518663f4a8..0705c2a009e 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -326,7 +326,6 @@ reg_class ptr_no_rax_reg(RDX, RDX_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -340,7 +339,6 @@ reg_class ptr_no_rbp_reg(RDX, RDX_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -354,7 +352,6 @@ reg_class ptr_no_rax_rbx_reg(RDX, RDX_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -444,9 +441,6 @@ reg_class long_rcx_reg(RCX, RCX_H); // Singleton class for RDX long register reg_class long_rdx_reg(RDX, RDX_H); -// Singleton class for R12 long register -reg_class long_r12_reg(R12, R12_H); - // Class for all int registers (except RSP) reg_class int_reg(RAX, RDX, @@ -1842,7 +1836,9 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { if (UseCompressedOops) { st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t", oopDesc::klass_offset_in_bytes()); - st->print_cr("leaq rscratch1, [r12_heapbase, r, Address::times_8, 0]"); + if (Universe::narrow_oop_shift() != 0) { + st->print_cr("leaq rscratch1, [r12_heapbase, r, Address::times_8, 0]"); + } st->print_cr("cmpq rax, rscratch1\t # Inline cache check"); } else { st->print_cr("cmpq rax, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t" @@ -1891,7 +1887,11 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const uint MachUEPNode::size(PhaseRegAlloc* ra_) const { if (UseCompressedOops) { - return OptoBreakpoint ? 19 : 20; + if (Universe::narrow_oop_shift() == 0) { + return OptoBreakpoint ? 15 : 16; + } else { + return OptoBreakpoint ? 19 : 20; + } } else { return OptoBreakpoint ? 11 : 12; } @@ -2575,45 +2575,13 @@ encode %{ Register Rrax = as_Register(RAX_enc); // super class Register Rrcx = as_Register(RCX_enc); // killed Register Rrsi = as_Register(RSI_enc); // sub class - Label hit, miss, cmiss; + Label miss; + const bool set_cond_codes = true; MacroAssembler _masm(&cbuf); - // Compare super with sub directly, since super is not in its own SSA. - // The compiler used to emit this test, but we fold it in here, - // to allow platform-specific tweaking on sparc. - __ cmpptr(Rrax, Rrsi); - __ jcc(Assembler::equal, hit); -#ifndef PRODUCT - __ lea(Rrcx, ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr)); - __ incrementl(Address(Rrcx, 0)); -#endif //PRODUCT - __ movptr(Rrdi, Address(Rrsi, - sizeof(oopDesc) + - Klass::secondary_supers_offset_in_bytes())); - __ movl(Rrcx, Address(Rrdi, arrayOopDesc::length_offset_in_bytes())); - __ addptr(Rrdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - if (UseCompressedOops) { - __ encode_heap_oop(Rrax); - __ repne_scanl(); - __ jcc(Assembler::notEqual, cmiss); - __ decode_heap_oop(Rrax); - __ movptr(Address(Rrsi, - sizeof(oopDesc) + - Klass::secondary_super_cache_offset_in_bytes()), - Rrax); - __ jmp(hit); - __ bind(cmiss); - __ decode_heap_oop(Rrax); - __ jmp(miss); - } else { - __ repne_scan(); - __ jcc(Assembler::notEqual, miss); - __ movptr(Address(Rrsi, - sizeof(oopDesc) + - Klass::secondary_super_cache_offset_in_bytes()), - Rrax); - } - __ bind(hit); + __ check_klass_subtype_slow_path(Rrsi, Rrax, Rrcx, Rrdi, + NULL, &miss, + /*set_cond_codes:*/ true); if ($primary) { __ xorptr(Rrdi, Rrdi); } @@ -4906,15 +4874,6 @@ operand rRegP() interface(REG_INTER); %} - -operand r12RegL() %{ - constraint(ALLOC_IN_RC(long_r12_reg)); - match(RegL); - - format %{ %} - interface(REG_INTER); -%} - operand rRegN() %{ constraint(ALLOC_IN_RC(int_reg)); match(RegN); @@ -5289,21 +5248,6 @@ operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale) %} %} -// Indirect Narrow Oop Plus Offset Operand -operand indNarrowOopOffset(rRegN src, immL32 off) %{ - constraint(ALLOC_IN_RC(ptr_reg)); - match(AddP (DecodeN src) off); - - op_cost(10); - format %{"[R12 + $src << 3 + $off] (compressed oop addressing)" %} - interface(MEMORY_INTER) %{ - base(0xc); // R12 - index($src); - scale(0x3); - disp($off); - %} -%} - // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale) %{ @@ -5321,6 +5265,158 @@ operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale) %} %} +// Indirect Narrow Oop Plus Offset Operand +// Note: x86 architecture doesn't support "scale * index + offset" without a base +// we can't free r12 even with Universe::narrow_oop_base() == NULL. +operand indCompressedOopOffset(rRegN reg, immL32 off) %{ + predicate(UseCompressedOops && (Universe::narrow_oop_shift() != 0)); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) off); + + op_cost(10); + format %{"[R12 + $reg << 3 + $off] (compressed oop addressing)" %} + interface(MEMORY_INTER) %{ + base(0xc); // R12 + index($reg); + scale(0x3); + disp($off); + %} +%} + +// Indirect Memory Operand +operand indirectNarrow(rRegN reg) +%{ + predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(DecodeN reg); + + format %{ "[$reg]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x4); + scale(0x0); + disp(0x0); + %} +%} + +// Indirect Memory Plus Short Offset Operand +operand indOffset8Narrow(rRegN reg, immL8 off) +%{ + predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) off); + + format %{ "[$reg + $off (8-bit)]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x4); + scale(0x0); + disp($off); + %} +%} + +// Indirect Memory Plus Long Offset Operand +operand indOffset32Narrow(rRegN reg, immL32 off) +%{ + predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) off); + + format %{ "[$reg + $off (32-bit)]" %} + interface(MEMORY_INTER) %{ + base($reg); + index(0x4); + scale(0x0); + disp($off); + %} +%} + +// Indirect Memory Plus Index Register Plus Offset Operand +operand indIndexOffsetNarrow(rRegN reg, rRegL lreg, immL32 off) +%{ + predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (AddP (DecodeN reg) lreg) off); + + op_cost(10); + format %{"[$reg + $off + $lreg]" %} + interface(MEMORY_INTER) %{ + base($reg); + index($lreg); + scale(0x0); + disp($off); + %} +%} + +// Indirect Memory Plus Index Register Plus Offset Operand +operand indIndexNarrow(rRegN reg, rRegL lreg) +%{ + predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) lreg); + + op_cost(10); + format %{"[$reg + $lreg]" %} + interface(MEMORY_INTER) %{ + base($reg); + index($lreg); + scale(0x0); + disp(0x0); + %} +%} + +// Indirect Memory Times Scale Plus Index Register +operand indIndexScaleNarrow(rRegN reg, rRegL lreg, immI2 scale) +%{ + predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) (LShiftL lreg scale)); + + op_cost(10); + format %{"[$reg + $lreg << $scale]" %} + interface(MEMORY_INTER) %{ + base($reg); + index($lreg); + scale($scale); + disp(0x0); + %} +%} + +// Indirect Memory Times Scale Plus Index Register Plus Offset Operand +operand indIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegL lreg, immI2 scale) +%{ + predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (AddP (DecodeN reg) (LShiftL lreg scale)) off); + + op_cost(10); + format %{"[$reg + $off + $lreg << $scale]" %} + interface(MEMORY_INTER) %{ + base($reg); + index($lreg); + scale($scale); + disp($off); + %} +%} + +// Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand +operand indPosIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegI idx, immI2 scale) +%{ + constraint(ALLOC_IN_RC(ptr_reg)); + predicate(Universe::narrow_oop_shift() == 0 && n->in(2)->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0); + match(AddP (AddP (DecodeN reg) (LShiftL (ConvI2L idx) scale)) off); + + op_cost(10); + format %{"[$reg + $off + $idx << $scale]" %} + interface(MEMORY_INTER) %{ + base($reg); + index($idx); + scale($scale); + disp($off); + %} +%} + + //----------Special Memory Operands-------------------------------------------- // Stack Slot Operand - This operand is used for loading and storing temporary // values on the stack where a match requires a value to @@ -5488,7 +5584,10 @@ operand cmpOpUCF2() %{ opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex, indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset, - indNarrowOopOffset); + indCompressedOopOffset, + indirectNarrow, indOffset8Narrow, indOffset32Narrow, + indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow, + indIndexScaleOffsetNarrow, indPosIndexScaleOffsetNarrow); //----------PIPELINE----------------------------------------------------------- // Rules which define the behavior of the target architectures pipeline. @@ -6234,9 +6333,7 @@ instruct loadN(rRegN dst, memory mem) ins_cost(125); // XXX format %{ "movl $dst, $mem\t# compressed ptr" %} ins_encode %{ - Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); - Register dst = as_Register($dst$$reg); - __ movl(dst, addr); + __ movl($dst$$Register, $mem$$Address); %} ins_pipe(ialu_reg_mem); // XXX %} @@ -6262,9 +6359,7 @@ instruct loadNKlass(rRegN dst, memory mem) ins_cost(125); // XXX format %{ "movl $dst, $mem\t# compressed klass ptr" %} ins_encode %{ - Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); - Register dst = as_Register($dst$$reg); - __ movl(dst, addr); + __ movl($dst$$Register, $mem$$Address); %} ins_pipe(ialu_reg_mem); // XXX %} @@ -6418,6 +6513,102 @@ instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem) ins_pipe(ialu_reg_reg_fat); %} +instruct leaPPosIdxScaleOff(rRegP dst, indPosIndexScaleOffset mem) +%{ + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr posidxscaleoff" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + +// Load Effective Address which uses Narrow (32-bits) oop +instruct leaPCompressedOopOffset(rRegP dst, indCompressedOopOffset mem) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_shift() != 0)); + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr compressedoopoff32" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + +instruct leaP8Narrow(rRegP dst, indOffset8Narrow mem) +%{ + predicate(Universe::narrow_oop_shift() == 0); + match(Set dst mem); + + ins_cost(110); // XXX + format %{ "leaq $dst, $mem\t# ptr off8narrow" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + +instruct leaP32Narrow(rRegP dst, indOffset32Narrow mem) +%{ + predicate(Universe::narrow_oop_shift() == 0); + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr off32narrow" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + +instruct leaPIdxOffNarrow(rRegP dst, indIndexOffsetNarrow mem) +%{ + predicate(Universe::narrow_oop_shift() == 0); + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr idxoffnarrow" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + +instruct leaPIdxScaleNarrow(rRegP dst, indIndexScaleNarrow mem) +%{ + predicate(Universe::narrow_oop_shift() == 0); + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr idxscalenarrow" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + +instruct leaPIdxScaleOffNarrow(rRegP dst, indIndexScaleOffsetNarrow mem) +%{ + predicate(Universe::narrow_oop_shift() == 0); + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr idxscaleoffnarrow" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + +instruct leaPPosIdxScaleOffNarrow(rRegP dst, indPosIndexScaleOffsetNarrow mem) +%{ + predicate(Universe::narrow_oop_shift() == 0); + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr posidxscaleoffnarrow" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + instruct loadConI(rRegI dst, immI src) %{ match(Set dst src); @@ -6528,8 +6719,7 @@ instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{ effect(KILL cr); format %{ "xorq $dst, $src\t# compressed NULL ptr" %} ins_encode %{ - Register dst = $dst$$Register; - __ xorq(dst, dst); + __ xorq($dst$$Register, $dst$$Register); %} ins_pipe(ialu_reg); %} @@ -6541,11 +6731,10 @@ instruct loadConN(rRegN dst, immN src) %{ format %{ "movl $dst, $src\t# compressed ptr" %} ins_encode %{ address con = (address)$src$$constant; - Register dst = $dst$$Register; if (con == NULL) { ShouldNotReachHere(); } else { - __ set_narrow_oop(dst, (jobject)$src$$constant); + __ set_narrow_oop($dst$$Register, (jobject)$src$$constant); } %} ins_pipe(ialu_reg_fat); // XXX @@ -6794,12 +6983,25 @@ instruct storeP(memory mem, any_RegP src) ins_pipe(ialu_mem_reg); %} +instruct storeImmP0(memory mem, immP0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreP mem zero)); + + ins_cost(125); // XXX + format %{ "movq $mem, R12\t# ptr (R12_heapbase==0)" %} + ins_encode %{ + __ movq($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + // Store NULL Pointer, mark word, or other simple pointer constant. instruct storeImmP(memory mem, immP31 src) %{ match(Set mem (StoreP mem src)); - ins_cost(125); // XXX + ins_cost(150); // XXX format %{ "movq $mem, $src\t# ptr" %} opcode(0xC7); /* C7 /0 */ ins_encode(REX_mem_wide(mem), OpcP, RM_opc_mem(0x00, mem), Con32(src)); @@ -6814,14 +7016,55 @@ instruct storeN(memory mem, rRegN src) ins_cost(125); // XXX format %{ "movl $mem, $src\t# compressed ptr" %} ins_encode %{ - Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); - Register src = as_Register($src$$reg); - __ movl(addr, src); + __ movl($mem$$Address, $src$$Register); %} ins_pipe(ialu_mem_reg); %} +instruct storeImmN0(memory mem, immN0 zero) +%{ + predicate(Universe::narrow_oop_base() == NULL); + match(Set mem (StoreN mem zero)); + + ins_cost(125); // XXX + format %{ "movl $mem, R12\t# compressed ptr (R12_heapbase==0)" %} + ins_encode %{ + __ movl($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + +instruct storeImmN(memory mem, immN src) +%{ + match(Set mem (StoreN mem src)); + + ins_cost(150); // XXX + format %{ "movl $mem, $src\t# compressed ptr" %} + ins_encode %{ + address con = (address)$src$$constant; + if (con == NULL) { + __ movl($mem$$Address, (int32_t)0); + } else { + __ set_narrow_oop($mem$$Address, (jobject)$src$$constant); + } + %} + ins_pipe(ialu_mem_imm); +%} + // Store Integer Immediate +instruct storeImmI0(memory mem, immI0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreI mem zero)); + + ins_cost(125); // XXX + format %{ "movl $mem, R12\t# int (R12_heapbase==0)" %} + ins_encode %{ + __ movl($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + instruct storeImmI(memory mem, immI src) %{ match(Set mem (StoreI mem src)); @@ -6834,6 +7077,19 @@ instruct storeImmI(memory mem, immI src) %} // Store Long Immediate +instruct storeImmL0(memory mem, immL0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreL mem zero)); + + ins_cost(125); // XXX + format %{ "movq $mem, R12\t# long (R12_heapbase==0)" %} + ins_encode %{ + __ movq($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + instruct storeImmL(memory mem, immL32 src) %{ match(Set mem (StoreL mem src)); @@ -6846,6 +7102,19 @@ instruct storeImmL(memory mem, immL32 src) %} // Store Short/Char Immediate +instruct storeImmC0(memory mem, immI0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreC mem zero)); + + ins_cost(125); // XXX + format %{ "movw $mem, R12\t# short/char (R12_heapbase==0)" %} + ins_encode %{ + __ movw($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + instruct storeImmI16(memory mem, immI16 src) %{ predicate(UseStoreImmI16); @@ -6859,6 +7128,19 @@ instruct storeImmI16(memory mem, immI16 src) %} // Store Byte Immediate +instruct storeImmB0(memory mem, immI0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreB mem zero)); + + ins_cost(125); // XXX + format %{ "movb $mem, R12\t# short/char (R12_heapbase==0)" %} + ins_encode %{ + __ movb($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + instruct storeImmB(memory mem, immI8 src) %{ match(Set mem (StoreB mem src)); @@ -6898,6 +7180,19 @@ instruct storeA2I(memory mem, regD src) %{ %} // Store CMS card-mark Immediate +instruct storeImmCM0_reg(memory mem, immI0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreCM mem zero)); + + ins_cost(125); // XXX + format %{ "movb $mem, R12\t# CMS card-mark byte 0 (R12_heapbase==0)" %} + ins_encode %{ + __ movb($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + instruct storeImmCM0(memory mem, immI0 src) %{ match(Set mem (StoreCM mem src)); @@ -6931,6 +7226,19 @@ instruct storeF(memory mem, regF src) %} // Store immediate Float value (it is faster than store from XMM register) +instruct storeF0(memory mem, immF0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreF mem zero)); + + ins_cost(25); // XXX + format %{ "movl $mem, R12\t# float 0. (R12_heapbase==0)" %} + ins_encode %{ + __ movl($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + instruct storeF_imm(memory mem, immF src) %{ match(Set mem (StoreF mem src)); @@ -6957,6 +7265,7 @@ instruct storeD(memory mem, regD src) // Store immediate double 0.0 (it is faster than store from XMM register) instruct storeD0_imm(memory mem, immD0 src) %{ + predicate(!UseCompressedOops || (Universe::narrow_oop_base() != NULL)); match(Set mem (StoreD mem src)); ins_cost(50); @@ -6966,6 +7275,19 @@ instruct storeD0_imm(memory mem, immD0 src) ins_pipe(ialu_mem_imm); %} +instruct storeD0(memory mem, immD0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set mem (StoreD mem zero)); + + ins_cost(25); // XXX + format %{ "movq $mem, R12\t# double 0. (R12_heapbase==0)" %} + ins_encode %{ + __ movq($mem$$Address, r12); + %} + ins_pipe(ialu_mem_reg); +%} + instruct storeSSI(stackSlotI dst, rRegI src) %{ match(Set dst src); @@ -7077,6 +7399,56 @@ instruct storeL_reversed(memory dst, rRegL src) %{ ins_pipe( ialu_mem_reg ); %} + +//---------- Population Count Instructions ------------------------------------- + +instruct popCountI(rRegI dst, rRegI src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + format %{ "popcnt $dst, $src" %} + ins_encode %{ + __ popcntl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct popCountI_mem(rRegI dst, memory mem) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI (LoadI mem))); + + format %{ "popcnt $dst, $mem" %} + ins_encode %{ + __ popcntl($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(rRegI dst, rRegL src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + + format %{ "popcnt $dst, $src" %} + ins_encode %{ + __ popcntq($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL_mem(rRegI dst, memory mem) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL (LoadL mem))); + + format %{ "popcnt $dst, $mem" %} + ins_encode %{ + __ popcntq($dst$$Register, $mem$$Address); + %} + ins_pipe(ialu_reg); +%} + + //----------MemBar Instructions----------------------------------------------- // Memory barrier flavors @@ -7192,9 +7564,7 @@ instruct encodeHeapOop_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{ effect(KILL cr); format %{ "encode_heap_oop_not_null $dst,$src" %} ins_encode %{ - Register s = $src$$Register; - Register d = $dst$$Register; - __ encode_heap_oop_not_null(d, s); + __ encode_heap_oop_not_null($dst$$Register, $src$$Register); %} ins_pipe(ialu_reg_long); %} @@ -7224,7 +7594,11 @@ instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{ ins_encode %{ Register s = $src$$Register; Register d = $dst$$Register; - __ decode_heap_oop_not_null(d, s); + if (s != d) { + __ decode_heap_oop_not_null(d, s); + } else { + __ decode_heap_oop_not_null(d); + } %} ins_pipe(ialu_reg_long); %} @@ -11389,8 +11763,9 @@ instruct testP_reg(rFlagsReg cr, rRegP src, immP0 zero) // This will generate a signed flags result. This should be OK since // any compare to a zero should be eq/neq. -instruct testP_reg_mem(rFlagsReg cr, memory op, immP0 zero) +instruct testP_mem(rFlagsReg cr, memory op, immP0 zero) %{ + predicate(!UseCompressedOops || (Universe::narrow_oop_base() != NULL)); match(Set cr (CmpP (LoadP op) zero)); ins_cost(500); // XXX @@ -11401,13 +11776,24 @@ instruct testP_reg_mem(rFlagsReg cr, memory op, immP0 zero) ins_pipe(ialu_cr_reg_imm); %} +instruct testP_mem_reg0(rFlagsReg cr, memory mem, immP0 zero) +%{ + predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); + match(Set cr (CmpP (LoadP mem) zero)); + + format %{ "cmpq R12, $mem\t# ptr (R12_heapbase==0)" %} + ins_encode %{ + __ cmpq(r12, $mem$$Address); + %} + ins_pipe(ialu_cr_reg_mem); +%} instruct compN_rReg(rFlagsRegU cr, rRegN op1, rRegN op2) %{ match(Set cr (CmpN op1 op2)); format %{ "cmpl $op1, $op2\t# compressed ptr" %} - ins_encode %{ __ cmpl(as_Register($op1$$reg), as_Register($op2$$reg)); %} + ins_encode %{ __ cmpl($op1$$Register, $op2$$Register); %} ins_pipe(ialu_cr_reg_reg); %} @@ -11415,11 +11801,30 @@ instruct compN_rReg_mem(rFlagsRegU cr, rRegN src, memory mem) %{ match(Set cr (CmpN src (LoadN mem))); - ins_cost(500); // XXX - format %{ "cmpl $src, mem\t# compressed ptr" %} + format %{ "cmpl $src, $mem\t# compressed ptr" %} ins_encode %{ - Address adr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); - __ cmpl(as_Register($src$$reg), adr); + __ cmpl($src$$Register, $mem$$Address); + %} + ins_pipe(ialu_cr_reg_mem); +%} + +instruct compN_rReg_imm(rFlagsRegU cr, rRegN op1, immN op2) %{ + match(Set cr (CmpN op1 op2)); + + format %{ "cmpl $op1, $op2\t# compressed ptr" %} + ins_encode %{ + __ cmp_narrow_oop($op1$$Register, (jobject)$op2$$constant); + %} + ins_pipe(ialu_cr_reg_imm); +%} + +instruct compN_mem_imm(rFlagsRegU cr, memory mem, immN src) +%{ + match(Set cr (CmpN src (LoadN mem))); + + format %{ "cmpl $mem, $src\t# compressed ptr" %} + ins_encode %{ + __ cmp_narrow_oop($mem$$Address, (jobject)$src$$constant); %} ins_pipe(ialu_cr_reg_mem); %} @@ -11432,15 +11837,27 @@ instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{ ins_pipe(ialu_cr_reg_imm); %} -instruct testN_reg_mem(rFlagsReg cr, memory mem, immN0 zero) +instruct testN_mem(rFlagsReg cr, memory mem, immN0 zero) %{ + predicate(Universe::narrow_oop_base() != NULL); match(Set cr (CmpN (LoadN mem) zero)); ins_cost(500); // XXX format %{ "testl $mem, 0xffffffff\t# compressed ptr" %} ins_encode %{ - Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); - __ cmpl(addr, (int)0xFFFFFFFF); + __ cmpl($mem$$Address, (int)0xFFFFFFFF); + %} + ins_pipe(ialu_cr_reg_mem); +%} + +instruct testN_mem_reg0(rFlagsReg cr, memory mem, immN0 zero) +%{ + predicate(Universe::narrow_oop_base() == NULL); + match(Set cr (CmpN (LoadN mem) zero)); + + format %{ "cmpl R12, $mem\t# compressed ptr (R12_heapbase==0)" %} + ins_encode %{ + __ cmpl(r12, $mem$$Address); %} ins_pipe(ialu_cr_reg_mem); %} @@ -11472,7 +11889,6 @@ instruct compL_rReg_mem(rFlagsReg cr, rRegL op1, memory op2) %{ match(Set cr (CmpL op1 (LoadL op2))); - ins_cost(500); // XXX format %{ "cmpq $op1, $op2" %} opcode(0x3B); /* Opcode 3B /r */ ins_encode(REX_reg_mem_wide(op1, op2), OpcP, reg_mem(op1, op2)); @@ -11733,15 +12149,12 @@ instruct partialSubtypeCheck(rdi_RegP result, effect(KILL rcx, KILL cr); ins_cost(1100); // slightly larger than the next version - format %{ "cmpq rax, rsi\n\t" - "jeq,s hit\n\t" - "movq rdi, [$sub + (sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())]\n\t" + format %{ "movq rdi, [$sub + (sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())]\n\t" "movl rcx, [rdi + arrayOopDesc::length_offset_in_bytes()]\t# length to scan\n\t" "addq rdi, arrayOopDex::base_offset_in_bytes(T_OBJECT)\t# Skip to start of data; set NZ in case count is zero\n\t" "repne scasq\t# Scan *rdi++ for a match with rax while rcx--\n\t" "jne,s miss\t\t# Missed: rdi not-zero\n\t" "movq [$sub + (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes())], $super\t# Hit: update cache\n\t" - "hit:\n\t" "xorq $result, $result\t\t Hit: rdi zero\n\t" "miss:\t" %} @@ -11756,13 +12169,10 @@ instruct partialSubtypeCheck_vs_Zero(rFlagsReg cr, rdi_RegP result) %{ match(Set cr (CmpP (PartialSubtypeCheck sub super) zero)); - predicate(!UseCompressedOops); // decoding oop kills condition codes effect(KILL rcx, KILL result); ins_cost(1000); - format %{ "cmpq rax, rsi\n\t" - "jeq,s miss\t# Actually a hit; we are done.\n\t" - "movq rdi, [$sub + (sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())]\n\t" + format %{ "movq rdi, [$sub + (sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())]\n\t" "movl rcx, [rdi + arrayOopDesc::length_offset_in_bytes()]\t# length to scan\n\t" "addq rdi, arrayOopDex::base_offset_in_bytes(T_OBJECT)\t# Skip to start of data; set NZ in case count is zero\n\t" "repne scasq\t# Scan *rdi++ for a match with rax while cx-- != 0\n\t" diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 9f80f6611ae..3788eac461e 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2269,15 +2269,16 @@ void linux_wrap_code(char* base, size_t size) { // All it does is to check if there are enough free pages // left at the time of mmap(). This could be a potential // problem. -bool os::commit_memory(char* addr, size_t size) { - uintptr_t res = (uintptr_t) ::mmap(addr, size, - PROT_READ|PROT_WRITE|PROT_EXEC, +bool os::commit_memory(char* addr, size_t size, bool exec) { + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; + uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); return res != (uintptr_t) MAP_FAILED; } -bool os::commit_memory(char* addr, size_t size, size_t alignment_hint) { - return commit_memory(addr, size); +bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, + bool exec) { + return commit_memory(addr, size, exec); } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } @@ -2417,8 +2418,7 @@ os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory; unsigned long* os::Linux::_numa_all_nodes; bool os::uncommit_memory(char* addr, size_t size) { - return ::mmap(addr, size, - PROT_READ|PROT_WRITE|PROT_EXEC, + return ::mmap(addr, size, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0) != MAP_FAILED; } @@ -2441,7 +2441,9 @@ static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) { flags |= MAP_FIXED; } - addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE|PROT_EXEC, + // Map uncommitted pages PROT_READ and PROT_WRITE, change access + // to PROT_EXEC if executable when we commit the page. + addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE, flags, -1, 0); if (addr != MAP_FAILED) { @@ -2582,7 +2584,9 @@ bool os::large_page_init() { #define SHM_HUGETLB 04000 #endif -char* os::reserve_memory_special(size_t bytes) { +char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) { + // "exec" is passed in but not used. Creating the shared image for + // the code cache doesn't have an SHM_X executable permission to check. assert(UseLargePages, "only for large pages"); key_t key = IPC_PRIVATE; diff --git a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp index feedb287ada..5ad280c3b7b 100644 --- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp +++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp @@ -249,6 +249,10 @@ int generateJvmOffsets(GEN_variant gen_variant) { printf("\n"); + GEN_OFFS(NarrowOopStruct, _base); + GEN_OFFS(NarrowOopStruct, _shift); + printf("\n"); + GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header)); GEN_SIZE(oopDesc); GEN_SIZE(constantPoolOopDesc); diff --git a/hotspot/src/os/solaris/dtrace/jhelper.d b/hotspot/src/os/solaris/dtrace/jhelper.d index 6f2f6165c35..da5837238c8 100644 --- a/hotspot/src/os/solaris/dtrace/jhelper.d +++ b/hotspot/src/os/solaris/dtrace/jhelper.d @@ -46,7 +46,10 @@ extern pointer __JvmOffsets; extern pointer __1cJCodeCacheF_heap_; extern pointer __1cIUniverseP_methodKlassObj_; extern pointer __1cIUniverseO_collectedHeap_; -extern pointer __1cIUniverseK_heap_base_; +extern pointer __1cIUniverseL_narrow_oop_; +#ifdef _LP64 +extern pointer UseCompressedOops; +#endif extern pointer __1cHnmethodG__vtbl_; extern pointer __1cKBufferBlobG__vtbl_; @@ -56,6 +59,7 @@ extern pointer __1cKBufferBlobG__vtbl_; #define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t)) #define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t)) #define copyin_int32(ADDR) *(int32_t*) copyin((pointer) (ADDR), sizeof(int32_t)) +#define copyin_uint8(ADDR) *(uint8_t*) copyin((pointer) (ADDR), sizeof(uint8_t)) #define SAME(x) x #define copyin_offset(JVM_CONST) JVM_CONST = \ @@ -132,6 +136,9 @@ dtrace:helper:ustack: copyin_offset(SIZE_oopDesc); copyin_offset(SIZE_constantPoolOopDesc); + copyin_offset(OFFSET_NarrowOopStruct_base); + copyin_offset(OFFSET_NarrowOopStruct_shift); + /* * The PC to translate is in arg0. */ @@ -151,9 +158,19 @@ dtrace:helper:ustack: this->Universe_methodKlassOop = copyin_ptr(&``__1cIUniverseP_methodKlassObj_); this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_); - this->Universe_heap_base = copyin_ptr(&``__1cIUniverseK_heap_base_); /* Reading volatile values */ +#ifdef _LP64 + this->Use_Compressed_Oops = copyin_uint8(&``UseCompressedOops); +#else + this->Use_Compressed_Oops = 0; +#endif + + this->Universe_narrow_oop_base = copyin_ptr(&``__1cIUniverseL_narrow_oop_ + + OFFSET_NarrowOopStruct_base); + this->Universe_narrow_oop_shift = copyin_int32(&``__1cIUniverseL_narrow_oop_ + + OFFSET_NarrowOopStruct_shift); + this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); @@ -295,7 +312,7 @@ dtrace:helper:ustack: dtrace:helper:ustack: /!this->done && this->vtbl == this->BufferBlob_vtbl && -this->Universe_heap_base == NULL && +this->Use_Compressed_Oops == 0 && this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ { MARK_LINE; @@ -306,7 +323,7 @@ this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ dtrace:helper:ustack: /!this->done && this->vtbl == this->BufferBlob_vtbl && -this->Universe_heap_base != NULL && +this->Use_Compressed_Oops != 0 && this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ { MARK_LINE; @@ -314,8 +331,8 @@ this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ * Read compressed pointer and decode heap oop, same as oop.inline.hpp */ this->cklass = copyin_uint32(this->methodOopPtr + OFFSET_oopDesc_metadata); - this->klass = (uint64_t)((uintptr_t)this->Universe_heap_base + - ((uintptr_t)this->cklass << 3)); + this->klass = (uint64_t)((uintptr_t)this->Universe_narrow_oop_base + + ((uintptr_t)this->cklass << this->Universe_narrow_oop_shift)); this->methodOop = this->klass == this->Universe_methodKlassOop; this->done = !this->methodOop; } diff --git a/hotspot/src/os/solaris/dtrace/libjvm_db.c b/hotspot/src/os/solaris/dtrace/libjvm_db.c index ad0031e4b92..afa443092b4 100644 --- a/hotspot/src/os/solaris/dtrace/libjvm_db.c +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c @@ -146,13 +146,17 @@ struct jvm_agent { uint64_t BufferBlob_vtbl; uint64_t RuntimeStub_vtbl; + uint64_t Use_Compressed_Oops_address; uint64_t Universe_methodKlassObj_address; + uint64_t Universe_narrow_oop_base_address; + uint64_t Universe_narrow_oop_shift_address; uint64_t CodeCache_heap_address; - uint64_t Universe_heap_base_address; /* Volatiles */ + uint8_t Use_Compressed_Oops; uint64_t Universe_methodKlassObj; - uint64_t Universe_heap_base; + uint64_t Universe_narrow_oop_base; + uint32_t Universe_narrow_oop_shift; uint64_t CodeCache_low; uint64_t CodeCache_high; uint64_t CodeCache_segmap_low; @@ -279,8 +283,11 @@ static int parse_vmstructs(jvm_agent_t* J) { if (strcmp("_methodKlassObj", vmp->fieldName) == 0) { J->Universe_methodKlassObj_address = vmp->address; } - if (strcmp("_heap_base", vmp->fieldName) == 0) { - J->Universe_heap_base_address = vmp->address; + if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { + J->Universe_narrow_oop_base_address = vmp->address; + } + if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { + J->Universe_narrow_oop_shift_address = vmp->address; } } CHECK_FAIL(err); @@ -298,14 +305,39 @@ static int parse_vmstructs(jvm_agent_t* J) { return -1; } +static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { + psaddr_t sym_addr; + int err; + + err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); + if (err != PS_OK) goto fail; + *valuep = sym_addr; + return PS_OK; + + fail: + return err; +} + static int read_volatiles(jvm_agent_t* J) { uint64_t ptr; int err; + err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); + if (err == PS_OK) { + err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); + CHECK_FAIL(err); + } else { + J->Use_Compressed_Oops = 0; + } + err = read_pointer(J, J->Universe_methodKlassObj_address, &J->Universe_methodKlassObj); CHECK_FAIL(err); - err = read_pointer(J, J->Universe_heap_base_address, &J->Universe_heap_base); + + err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); CHECK_FAIL(err); + err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); + CHECK_FAIL(err); + err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low, &J->CodeCache_low); CHECK_FAIL(err); @@ -374,19 +406,6 @@ static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) { return -1; } -static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { - psaddr_t sym_addr; - int err; - - err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); - if (err != PS_OK) goto fail; - *valuep = sym_addr; - return PS_OK; - - fail: - return err; -} - static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) { psaddr_t sym_addr; int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); @@ -458,14 +477,14 @@ void Jagent_destroy(jvm_agent_t *J) { static int is_methodOop(jvm_agent_t* J, uint64_t methodOopPtr) { uint64_t klass; int err; - // If heap_base is nonnull, this was a compressed oop. - if (J->Universe_heap_base != NULL) { + // If UseCompressedOops, this was a compressed oop. + if (J->Use_Compressed_Oops != 0) { uint32_t cklass; err = read_compressed_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, &cklass); // decode heap oop, same as oop.inline.hpp - klass = (uint64_t)((uintptr_t)J->Universe_heap_base + - ((uintptr_t)cklass << 3)); + klass = (uint64_t)((uintptr_t)J->Universe_narrow_oop_base + + ((uintptr_t)cklass << J->Universe_narrow_oop_shift)); } else { err = read_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, &klass); } diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index a8aef4af965..23b4ff2f5f2 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2623,15 +2623,16 @@ int os::vm_allocation_granularity() { return page_size; } -bool os::commit_memory(char* addr, size_t bytes) { +bool os::commit_memory(char* addr, size_t bytes, bool exec) { + int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; size_t size = bytes; return - NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, - PROT_READ | PROT_WRITE | PROT_EXEC); + NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); } -bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint) { - if (commit_memory(addr, bytes)) { +bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint, + bool exec) { + if (commit_memory(addr, bytes, exec)) { if (UseMPSS && alignment_hint > (size_t)vm_page_size()) { // If the large page size has been set and the VM // is using large pages, use the large page size @@ -3220,7 +3221,9 @@ bool os::Solaris::set_mpss_range(caddr_t start, size_t bytes, size_t align) { return true; } -char* os::reserve_memory_special(size_t bytes) { +char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { + // "exec" is passed in but not used. Creating the shared image for + // the code cache doesn't have an SHM_X executable permission to check. assert(UseLargePages && UseISM, "only for ISM large pages"); size_t size = bytes; @@ -4451,6 +4454,9 @@ int_fnP_thread_t_i os::Solaris::_thr_setmutator; int_fnP_thread_t os::Solaris::_thr_suspend_mutator; int_fnP_thread_t os::Solaris::_thr_continue_mutator; +// (Static) wrapper for getisax(2) call. +os::Solaris::getisax_func_t os::Solaris::_getisax = 0; + // (Static) wrappers for the liblgrp API os::Solaris::lgrp_home_func_t os::Solaris::_lgrp_home; os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init; @@ -4465,16 +4471,19 @@ os::Solaris::lgrp_cookie_t os::Solaris::_lgrp_cookie = 0; // (Static) wrapper for meminfo() call. os::Solaris::meminfo_func_t os::Solaris::_meminfo = 0; -static address resolve_symbol(const char *name) { - address addr; - - addr = (address) dlsym(RTLD_DEFAULT, name); +static address resolve_symbol_lazy(const char* name) { + address addr = (address) dlsym(RTLD_DEFAULT, name); if(addr == NULL) { // RTLD_DEFAULT was not defined on some early versions of 2.5.1 addr = (address) dlsym(RTLD_NEXT, name); - if(addr == NULL) { - fatal(dlerror()); - } + } + return addr; +} + +static address resolve_symbol(const char* name) { + address addr = resolve_symbol_lazy(name); + if(addr == NULL) { + fatal(dlerror()); } return addr; } @@ -4673,15 +4682,26 @@ bool os::Solaris::liblgrp_init() { } void os::Solaris::misc_sym_init() { - address func = (address)dlsym(RTLD_DEFAULT, "meminfo"); - if(func == NULL) { - func = (address) dlsym(RTLD_NEXT, "meminfo"); + address func; + + // getisax + func = resolve_symbol_lazy("getisax"); + if (func != NULL) { + os::Solaris::_getisax = CAST_TO_FN_PTR(getisax_func_t, func); } + + // meminfo + func = resolve_symbol_lazy("meminfo"); if (func != NULL) { os::Solaris::set_meminfo(CAST_TO_FN_PTR(meminfo_func_t, func)); } } +uint_t os::Solaris::getisax(uint32_t* array, uint_t n) { + assert(_getisax != NULL, "_getisax not set"); + return _getisax(array, n); +} + // Symbol doesn't exist in Solaris 8 pset.h #ifndef PS_MYID #define PS_MYID -3 @@ -4716,6 +4736,10 @@ void os::init(void) { Solaris::initialize_system_info(); + // Initialize misc. symbols as soon as possible, so we can use them + // if we need them. + Solaris::misc_sym_init(); + int fd = open("/dev/zero", O_RDWR); if (fd < 0) { fatal1("os::init: cannot open /dev/zero (%s)", strerror(errno)); @@ -4857,7 +4881,6 @@ jint os::init_2(void) { } } - Solaris::misc_sym_init(); Solaris::signal_sets_init(); Solaris::init_signal_mem(); Solaris::install_signal_handlers(); diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index 8e322456d89..e4cbdbb5cd6 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,8 @@ class Solaris { LGRP_VIEW_OS /* what's available to operating system */ } lgrp_view_t; + typedef uint_t (*getisax_func_t)(uint32_t* array, uint_t n); + typedef lgrp_id_t (*lgrp_home_func_t)(idtype_t idtype, id_t id); typedef lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view); typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie); @@ -87,6 +89,8 @@ class Solaris { const uint_t info_req[], int info_count, uint64_t outdata[], uint_t validity[]); + static getisax_func_t _getisax; + static lgrp_home_func_t _lgrp_home; static lgrp_init_func_t _lgrp_init; static lgrp_fini_func_t _lgrp_fini; @@ -283,6 +287,9 @@ class Solaris { } static lgrp_cookie_t lgrp_cookie() { return _lgrp_cookie; } + static bool supports_getisax() { return _getisax != NULL; } + static uint_t getisax(uint32_t* array, uint_t n); + static void set_meminfo(meminfo_func_t func) { _meminfo = func; } static int meminfo (const uint64_t inaddr[], int addr_count, const uint_t info_req[], int info_count, diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 808bc7bd3a3..cc3c6202d65 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2189,7 +2189,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) { addr = (address)((uintptr_t)addr & (~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); - os::commit_memory( (char *)addr, thread->stack_base() - addr ); + os::commit_memory((char *)addr, thread->stack_base() - addr, + false ); return EXCEPTION_CONTINUE_EXECUTION; } else @@ -2565,8 +2566,7 @@ char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { assert((size_t)addr % os::vm_allocation_granularity() == 0, "reserve alignment"); assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size"); - char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, - PAGE_EXECUTE_READWRITE); + char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); assert(res == NULL || addr == NULL || addr == res, "Unexpected address from reserve."); return res; @@ -2595,7 +2595,7 @@ bool os::can_execute_large_page_memory() { return true; } -char* os::reserve_memory_special(size_t bytes) { +char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { if (UseLargePagesIndividualAllocation) { if (TracePageSizes && Verbose) { @@ -2615,10 +2615,10 @@ char* os::reserve_memory_special(size_t bytes) { "use -XX:-UseLargePagesIndividualAllocation to turn off"); return NULL; } - p_buf = (char *) VirtualAlloc(NULL, + p_buf = (char *) VirtualAlloc(addr, size_of_reserve, // size of Reserve MEM_RESERVE, - PAGE_EXECUTE_READWRITE); + PAGE_READWRITE); // If reservation failed, return NULL if (p_buf == NULL) return NULL; @@ -2659,7 +2659,13 @@ char* os::reserve_memory_special(size_t bytes) { p_new = (char *) VirtualAlloc(next_alloc_addr, bytes_to_rq, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, - PAGE_EXECUTE_READWRITE); + PAGE_READWRITE); + if (p_new != NULL && exec) { + DWORD oldprot; + // Windows doc says to use VirtualProtect to get execute permissions + VirtualProtect(next_alloc_addr, bytes_to_rq, + PAGE_EXECUTE_READWRITE, &oldprot); + } } if (p_new == NULL) { @@ -2688,10 +2694,12 @@ char* os::reserve_memory_special(size_t bytes) { } else { // normal policy just allocate it all at once DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; - char * res = (char *)VirtualAlloc(NULL, - bytes, - flag, - PAGE_EXECUTE_READWRITE); + char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_READWRITE); + if (res != NULL && exec) { + DWORD oldprot; + // Windows doc says to use VirtualProtect to get execute permissions + VirtualProtect(res, bytes, PAGE_EXECUTE_READWRITE, &oldprot); + } return res; } } @@ -2703,7 +2711,7 @@ bool os::release_memory_special(char* base, size_t bytes) { void os::print_statistics() { } -bool os::commit_memory(char* addr, size_t bytes) { +bool os::commit_memory(char* addr, size_t bytes, bool exec) { if (bytes == 0) { // Don't bother the OS with noops. return true; @@ -2712,11 +2720,19 @@ bool os::commit_memory(char* addr, size_t bytes) { assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks"); // Don't attempt to print anything if the OS call fails. We're // probably low on resources, so the print itself may cause crashes. - return VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE) != NULL; + bool result = VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) != 0; + if (result != NULL && exec) { + DWORD oldprot; + // Windows doc says to use VirtualProtect to get execute permissions + return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot) != 0; + } else { + return result; + } } -bool os::commit_memory(char* addr, size_t size, size_t alignment_hint) { - return commit_memory(addr, size); +bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, + bool exec) { + return commit_memory(addr, size, exec); } bool os::uncommit_memory(char* addr, size_t bytes) { @@ -2750,7 +2766,7 @@ bool os::protect_memory(char* addr, size_t bytes, ProtType prot, // Strange enough, but on Win32 one can change protection only for committed // memory, not a big deal anyway, as bytes less or equal than 64K - if (!is_committed && !commit_memory(addr, bytes)) { + if (!is_committed && !commit_memory(addr, bytes, prot == MEM_PROT_RWX)) { fatal("cannot commit protection page"); } // One cannot use os::guard_memory() here, as on Win32 guard page @@ -3248,10 +3264,10 @@ jint os::init_2(void) { #endif if (!UseMembar) { - address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_EXECUTE_READWRITE); + address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READWRITE); guarantee( mem_serialize_page != NULL, "Reserve Failed for memory serialize page"); - return_page = (address)VirtualAlloc(mem_serialize_page, os::vm_page_size(), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + return_page = (address)VirtualAlloc(mem_serialize_page, os::vm_page_size(), MEM_COMMIT, PAGE_READWRITE); guarantee( return_page != NULL, "Commit Failed for memory serialize page"); os::set_memory_serialize_page( mem_serialize_page ); diff --git a/hotspot/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp index ccc884e8329..68be1d43523 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp @@ -30,5 +30,7 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 12288); define_pd_global(intx, CompilerThreadStackSize, 0); +// Only used on 64 bit platforms +define_pd_global(uintx, HeapBaseMinAddress, 4*G); // Only used on 64 bit Windows platforms define_pd_global(bool, UseVectoredExceptions, false); diff --git a/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp b/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp index 317993ce58f..24d2bab7c19 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp @@ -43,5 +43,7 @@ define_pd_global(intx, SurvivorRatio, 8); define_pd_global(uintx, JVMInvokeMethodSlack, 8192); +// Only used on 64 bit platforms +define_pd_global(uintx, HeapBaseMinAddress, 2*G); // Only used on 64 bit Windows platforms define_pd_global(bool, UseVectoredExceptions, false); diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp index c0bf513235e..71f16d94158 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp @@ -30,5 +30,9 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 12288); define_pd_global(intx, CompilerThreadStackSize, 0); +// Only used on 64 bit platforms +define_pd_global(uintx, HeapBaseMinAddress, 4*G); // Only used on 64 bit Windows platforms define_pd_global(bool, UseVectoredExceptions, false); + + diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 5f2ec21027e..ec537c7fe54 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,58 +25,107 @@ # include "incls/_precompiled.incl" # include "incls/_vm_version_solaris_sparc.cpp.incl" +# include +# include # include -int VM_Version::platform_features(int features) { - // We determine what sort of hardware we have via sysinfo(SI_ISALIST, ...). - // This isn't the best of all possible ways because there's not enough - // detail in the isa list it returns, but it's a bit less arcane than - // generating assembly code and an illegal instruction handler. We used - // to generate a getpsr trap, but that's even more arcane. - // - // Another possibility would be to use sysinfo(SI_PLATFORM, ...), but - // that would require more knowledge here than is wise. +// We need to keep these here as long as we have to build on Solaris +// versions before 10. +#ifndef SI_ARCHITECTURE_32 +#define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ +#endif - // isalist spec via 'man isalist' as of 01-Aug-2001 +#ifndef SI_ARCHITECTURE_64 +#define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */ +#endif +static void do_sysinfo(int si, const char* string, int* features, int mask) { char tmp; - size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1); - char* buf = (char*)malloc(bufsize); + size_t bufsize = sysinfo(si, &tmp, 1); - if (buf != NULL) { - if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) { - // Figure out what kind of sparc we have - char *sparc_string = strstr(buf, "sparc"); - if (sparc_string != NULL) { features |= v8_instructions_m; - if (sparc_string[5] == 'v') { - if (sparc_string[6] == '8') { - if (sparc_string[7] == '-') features |= hardware_int_muldiv_m; - else if (sparc_string[7] == 'p') features |= generic_v9_m; - else features |= generic_v8_m; - } else if (sparc_string[6] == '9') features |= generic_v9_m; + // All SI defines used below must be supported. + guarantee(bufsize != -1, "must be supported"); + + char* buf = (char*) malloc(bufsize); + + if (buf == NULL) + return; + + if (sysinfo(si, buf, bufsize) == bufsize) { + // Compare the string. + if (strcmp(buf, string) == 0) { + *features |= mask; + } + } + + free(buf); +} + +int VM_Version::platform_features(int features) { + // getisax(2), SI_ARCHITECTURE_32, and SI_ARCHITECTURE_64 are + // supported on Solaris 10 and later. + if (os::Solaris::supports_getisax()) { +#ifndef PRODUCT + if (PrintMiscellaneous && Verbose) + tty->print_cr("getisax(2) supported."); +#endif + + // Check 32-bit architecture. + do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); + + // Check 64-bit architecture. + do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); + + // Extract valid instruction set extensions. + uint_t av; + uint_t avn = os::Solaris::getisax(&av, 1); + assert(avn == 1, "should only return one av"); + + if (av & AV_SPARC_MUL32) features |= hardware_mul32_m; + if (av & AV_SPARC_DIV32) features |= hardware_div32_m; + if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m; + if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m; + if (av & AV_SPARC_POPC) features |= hardware_popc_m; + if (av & AV_SPARC_VIS) features |= vis1_instructions_m; + if (av & AV_SPARC_VIS2) features |= vis2_instructions_m; + } else { + // getisax(2) failed, use the old legacy code. +#ifndef PRODUCT + if (PrintMiscellaneous && Verbose) + tty->print_cr("getisax(2) not supported."); +#endif + + char tmp; + size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1); + char* buf = (char*) malloc(bufsize); + + if (buf != NULL) { + if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) { + // Figure out what kind of sparc we have + char *sparc_string = strstr(buf, "sparc"); + if (sparc_string != NULL) { features |= v8_instructions_m; + if (sparc_string[5] == 'v') { + if (sparc_string[6] == '8') { + if (sparc_string[7] == '-') { features |= hardware_mul32_m; + features |= hardware_div32_m; + } else if (sparc_string[7] == 'p') features |= generic_v9_m; + else features |= generic_v8_m; + } else if (sparc_string[6] == '9') features |= generic_v9_m; + } + } + + // Check for visualization instructions + char *vis = strstr(buf, "vis"); + if (vis != NULL) { features |= vis1_instructions_m; + if (vis[3] == '2') features |= vis2_instructions_m; } } - - // Check for visualization instructions - char *vis = strstr(buf, "vis"); - if (vis != NULL) { features |= vis1_instructions_m; - if (vis[3] == '2') features |= vis2_instructions_m; - } + free(buf); } - free(buf); } - bufsize = sysinfo(SI_MACHINE, &tmp, 1); - buf = (char*)malloc(bufsize); - - if (buf != NULL) { - if (sysinfo(SI_MACHINE, buf, bufsize) == bufsize) { - if (strstr(buf, "sun4v") != NULL) { - features |= sun4v_m; - } - } - free(buf); - } + // Determine the machine type. + do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); return features; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp index aef1d7314d3..754195f10ff 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp @@ -46,5 +46,7 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 10*K); define_pd_global(intx, CompilerThreadStackSize, 0); +// Only used on 64 bit platforms +define_pd_global(uintx, HeapBaseMinAddress, 256*M); // Only used on 64 bit Windows platforms define_pd_global(bool, UseVectoredExceptions, false); diff --git a/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp b/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp index 7c578df700c..97226fa37dd 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp @@ -45,5 +45,7 @@ define_pd_global(intx, CompilerThreadStackSize, 0); define_pd_global(uintx, JVMInvokeMethodSlack, 8192); +// Only used on 64 bit platforms +define_pd_global(uintx, HeapBaseMinAddress, 2*G); // Only used on 64 bit Windows platforms define_pd_global(bool, UseVectoredExceptions, false); diff --git a/hotspot/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp b/hotspot/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp index 1e8ed078d54..5f8958567e0 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/unwind_windows_x86.hpp @@ -68,6 +68,9 @@ typedef struct _DISPATCHER_CONTEXT { PVOID HandlerData; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; +#if MSC_VER < 1500 + +/* Not needed for VS2008 compiler, comes from winnt.h. */ typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) ( IN PEXCEPTION_RECORD ExceptionRecord, IN ULONG64 EstablisherFrame, @@ -75,4 +78,6 @@ typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) ( IN OUT PDISPATCHER_CONTEXT DispatcherContext ); +#endif + #endif // AMD64 diff --git a/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC7.java b/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC7.java index 82159a41835..109613b45d7 100644 --- a/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC7.java +++ b/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC7.java @@ -27,6 +27,8 @@ import java.util.*; public class WinGammaPlatformVC7 extends WinGammaPlatform { + String projectVersion() {return "7.10";}; + public void writeProjectFile(String projectFileName, String projectName, Vector allConfigs) throws IOException { System.out.println(); @@ -40,7 +42,7 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform { "VisualStudioProject", new String[] { "ProjectType", "Visual C++", - "Version", "7.10", + "Version", projectVersion(), "Name", projectName, "ProjectGUID", "{8822CB5C-1C41-41C2-8493-9F6E1994338B}", "SccProjectName", "", @@ -417,7 +419,9 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform { new String[] { "Name", "VCPreLinkEventTool", "Description", BuildConfig.getFieldString(null, "PrelinkDescription"), - "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace('\t', '\n')) + //Caution: String.replace(String,String) is available from JDK5 onwards only + "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace + ("\t", " ")) } ); @@ -542,25 +546,41 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform { } class CompilerInterfaceVC7 extends CompilerInterface { - Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) { - Vector rv = new Vector(); + void getBaseCompilerFlags_common(Vector defines, Vector includes, String outDir,Vector rv) { // advanced M$ IDE (2003) can only recognize name if it's first or // second attribute in the tag - go guess addAttr(rv, "Name", "VCCLCompilerTool"); addAttr(rv, "AdditionalIncludeDirectories", Util.join(",", includes)); - addAttr(rv, "PreprocessorDefinitions", Util.join(";", defines).replace("\"",""")); - addAttr(rv, "UsePrecompiledHeader", "3"); - addAttr(rv, "PrecompiledHeaderThrough", "incls"+Util.sep+"_precompiled.incl"); + addAttr(rv, "PreprocessorDefinitions", + Util.join(";", defines).replace("\"",""")); + addAttr(rv, "PrecompiledHeaderThrough", + "incls"+Util.sep+"_precompiled.incl"); addAttr(rv, "PrecompiledHeaderFile", outDir+Util.sep+"vm.pch"); addAttr(rv, "AssemblerListingLocation", outDir); addAttr(rv, "ObjectFile", outDir+Util.sep); addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"vm.pdb"); + // Set /nologo optin addAttr(rv, "SuppressStartupBanner", "TRUE"); + // Surpass the default /Tc or /Tp. 0 is compileAsDefault addAttr(rv, "CompileAs", "0"); + // Set /W3 option. 3 is warningLevel_3 addAttr(rv, "WarningLevel", "3"); + // Set /WX option, addAttr(rv, "WarnAsError", "TRUE"); + // Set /GS option addAttr(rv, "BufferSecurityCheck", "FALSE"); + // Set /Zi option. 3 is debugEnabled + addAttr(rv, "DebugInformationFormat", "3"); + } + Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) { + Vector rv = new Vector(); + + getBaseCompilerFlags_common(defines,includes, outDir, rv); + // Set /Yu option. 3 is pchUseUsingSpecific + // Note: Starting VC8 pchUseUsingSpecific is 2 !!! + addAttr(rv, "UsePrecompiledHeader", "3"); + // Set /EHsc- option addAttr(rv, "ExceptionHandling", "FALSE"); return rv; @@ -579,27 +599,39 @@ class CompilerInterfaceVC7 extends CompilerInterface { "/export:jio_vsnprintf "); addAttr(rv, "AdditionalDependencies", "Wsock32.lib winmm.lib"); addAttr(rv, "OutputFile", outDll); + // Set /INCREMENTAL option. 1 is linkIncrementalNo addAttr(rv, "LinkIncremental", "1"); addAttr(rv, "SuppressStartupBanner", "TRUE"); addAttr(rv, "ModuleDefinitionFile", outDir+Util.sep+"vm.def"); addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"vm.pdb"); + // Set /SUBSYSTEM option. 2 is subSystemWindows addAttr(rv, "SubSystem", "2"); addAttr(rv, "BaseAddress", "0x8000000"); addAttr(rv, "ImportLibrary", outDir+Util.sep+"jvm.lib"); + // Set /MACHINE option. 1 is machineX86 addAttr(rv, "TargetMachine", "1"); return rv; } + void getDebugCompilerFlags_common(String opt,Vector rv) { + + // Set /On option + addAttr(rv, "Optimization", opt); + // Set /FR option. 1 is brAllInfo + addAttr(rv, "BrowseInformation", "1"); + addAttr(rv, "BrowseInformationFile", "$(IntDir)" + Util.sep); + // Set /MD option. 2 is rtMultiThreadedDLL + addAttr(rv, "RuntimeLibrary", "2"); + // Set /Oy- option + addAttr(rv, "OmitFramePointers", "FALSE"); + + } + Vector getDebugCompilerFlags(String opt) { Vector rv = new Vector(); - addAttr(rv, "Optimization", opt); - addAttr(rv, "OptimizeForProcessor", "1"); - addAttr(rv, "DebugInformationFormat", "3"); - addAttr(rv, "RuntimeLibrary", "2"); - addAttr(rv, "BrowseInformation", "1"); - addAttr(rv, "BrowseInformationFile", "$(IntDir)" + Util.sep); + getDebugCompilerFlags_common(opt,rv); return rv; } @@ -607,18 +639,29 @@ class CompilerInterfaceVC7 extends CompilerInterface { Vector getDebugLinkerFlags() { Vector rv = new Vector(); - addAttr(rv, "GenerateDebugInformation", "TRUE"); + addAttr(rv, "GenerateDebugInformation", "TRUE"); // == /DEBUG option return rv; } + void getProductCompilerFlags_common(Vector rv) { + // Set /O2 option. 2 is optimizeMaxSpeed + addAttr(rv, "Optimization", "2"); + // Set /Oy- option + addAttr(rv, "OmitFramePointers", "FALSE"); + } + Vector getProductCompilerFlags() { Vector rv = new Vector(); - addAttr(rv, "Optimization", "2"); + getProductCompilerFlags_common(rv); + // Set /Ob option. 1 is expandOnlyInline addAttr(rv, "InlineFunctionExpansion", "1"); + // Set /GF option. addAttr(rv, "StringPooling", "TRUE"); + // Set /MD option. 2 is rtMultiThreadedDLL addAttr(rv, "RuntimeLibrary", "2"); + // Set /Gy option addAttr(rv, "EnableFunctionLevelLinking", "TRUE"); return rv; @@ -627,7 +670,9 @@ class CompilerInterfaceVC7 extends CompilerInterface { Vector getProductLinkerFlags() { Vector rv = new Vector(); + // Set /OPT:REF option. 2 is optReferences addAttr(rv, "OptimizeReferences", "2"); + // Set /OPT:optFolding option. 2 is optFolding addAttr(rv, "EnableCOMDATFolding", "2"); return rv; diff --git a/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC8.java b/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC8.java new file mode 100644 index 00000000000..a346b611560 --- /dev/null +++ b/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC8.java @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +import java.io.*; +import java.util.*; + +public class WinGammaPlatformVC8 extends WinGammaPlatformVC7 { + + String projectVersion() {return "8.00";}; + +} + +class CompilerInterfaceVC8 extends CompilerInterfaceVC7 { + + Vector getBaseCompilerFlags(Vector defines, Vector includes, String outDir) { + Vector rv = new Vector(); + + getBaseCompilerFlags_common(defines,includes, outDir, rv); + // Set /Yu option. 2 is pchUseUsingSpecific + addAttr(rv, "UsePrecompiledHeader", "2"); + // Set /EHsc- option. 0 is cppExceptionHandlingNo + addAttr(rv, "ExceptionHandling", "0"); + + return rv; + } + + + Vector getDebugCompilerFlags(String opt) { + Vector rv = new Vector(); + + getDebugCompilerFlags_common(opt,rv); + + return rv; + } + + Vector getProductCompilerFlags() { + Vector rv = new Vector(); + + getProductCompilerFlags_common(rv); + + return rv; + } + + +} diff --git a/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC9.java b/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC9.java new file mode 100644 index 00000000000..4b64a555833 --- /dev/null +++ b/hotspot/src/share/tools/MakeDeps/WinGammaPlatformVC9.java @@ -0,0 +1,35 @@ +/* + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +import java.io.*; +import java.util.*; + +public class WinGammaPlatformVC9 extends WinGammaPlatformVC8 { + + String projectVersion() {return "9.00";}; + +} + +class CompilerInterfaceVC9 extends CompilerInterfaceVC8 { +} diff --git a/hotspot/src/share/vm/adlc/adlc.hpp b/hotspot/src/share/vm/adlc/adlc.hpp index 3d59b539b3e..6b92dfd8476 100644 --- a/hotspot/src/share/vm/adlc/adlc.hpp +++ b/hotspot/src/share/vm/adlc/adlc.hpp @@ -44,7 +44,7 @@ using namespace std; #error "Something is wrong with the detection of MSC_VER in the makefiles" #endif -#if _MSC_VER >= 1400 && !defined(_WIN64) +#if _MSC_VER >= 1400 #define strdup _strdup #endif diff --git a/hotspot/src/share/vm/asm/assembler.cpp b/hotspot/src/share/vm/asm/assembler.cpp index 1cbbad6d435..e41fc7e9d31 100644 --- a/hotspot/src/share/vm/asm/assembler.cpp +++ b/hotspot/src/share/vm/asm/assembler.cpp @@ -321,16 +321,19 @@ void AbstractAssembler::block_comment(const char* comment) { bool MacroAssembler::needs_explicit_null_check(intptr_t offset) { // Exception handler checks the nmethod's implicit null checks table // only when this method returns false. - if (UseCompressedOops) { +#ifdef _LP64 + if (UseCompressedOops && Universe::narrow_oop_base() != NULL) { + assert (Universe::heap() != NULL, "java heap should be initialized"); // The first page after heap_base is unmapped and // the 'offset' is equal to [heap_base + offset] for // narrow oop implicit null checks. - uintptr_t heap_base = (uintptr_t)Universe::heap_base(); - if ((uintptr_t)offset >= heap_base) { + uintptr_t base = (uintptr_t)Universe::narrow_oop_base(); + if ((uintptr_t)offset >= base) { // Normalize offset for the next check. - offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1)); + offset = (intptr_t)(pointer_delta((void*)offset, (void*)base, 1)); } } +#endif return offset < 0 || os::vm_page_size() <= offset; } diff --git a/hotspot/src/share/vm/ci/ciMethodBlocks.cpp b/hotspot/src/share/vm/ci/ciMethodBlocks.cpp index 4f7e52559e6..934cca6d99d 100644 --- a/hotspot/src/share/vm/ci/ciMethodBlocks.cpp +++ b/hotspot/src/share/vm/ci/ciMethodBlocks.cpp @@ -284,6 +284,11 @@ ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), // int ex_start = handler->start(); int ex_end = handler->limit(); + // ensure a block at the start of exception range and start of following code + (void) make_block_at(ex_start); + if (ex_end < _code_size) + (void) make_block_at(ex_end); + if (eb->is_handler()) { // Extend old handler exception range to cover additional range. int old_ex_start = eb->ex_start_bci(); @@ -295,10 +300,6 @@ ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth), eb->clear_exception_handler(); // Reset exception information } eb->set_exception_range(ex_start, ex_end); - // ensure a block at the start of exception range and start of following code - (void) make_block_at(ex_start); - if (ex_end < _code_size) - (void) make_block_at(ex_end); } } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index c49e4a62306..119b95adf46 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -2747,9 +2747,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, super_klass(), methods(), access_flags, - class_loader(), - class_name(), - local_interfaces()); + class_loader, + class_name, + local_interfaces(), + CHECK_(nullHandle)); // Size of Java itable (in words) itable_size = access_flags.is_interface() ? 0 : klassItable::compute_itable_size(transitive_interfaces); @@ -3229,7 +3230,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, // print out the superclass. const char * from = Klass::cast(this_klass())->external_name(); if (this_klass->java_super() != NULL) { - tty->print("RESOLVE %s %s\n", from, instanceKlass::cast(this_klass->java_super())->external_name()); + tty->print("RESOLVE %s %s (super)\n", from, instanceKlass::cast(this_klass->java_super())->external_name()); } // print out each of the interface classes referred to by this class. objArrayHandle local_interfaces(THREAD, this_klass->local_interfaces()); @@ -3239,7 +3240,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, klassOop k = klassOop(local_interfaces->obj_at(i)); instanceKlass* to_class = instanceKlass::cast(k); const char * to = to_class->external_name(); - tty->print("RESOLVE %s %s\n", from, to); + tty->print("RESOLVE %s %s (interface)\n", from, to); } } } diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 338b14877a0..6964de07c44 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -284,6 +284,7 @@ template(value_name, "value") \ template(frontCacheEnabled_name, "frontCacheEnabled") \ template(stringCacheEnabled_name, "stringCacheEnabled") \ + template(bitCount_name, "bitCount") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ @@ -304,6 +305,7 @@ template(double_long_signature, "(D)J") \ template(double_double_signature, "(D)D") \ template(int_float_signature, "(I)F") \ + template(long_int_signature, "(J)I") \ template(long_long_signature, "(J)J") \ template(long_double_signature, "(J)D") \ template(byte_signature, "B") \ @@ -376,7 +378,7 @@ template(unknown_class_name, "") \ \ /* used to identify class loaders handling parallel class loading */ \ - template(parallelCapable_name, "parallelLockMap;") \ + template(parallelCapable_name, "parallelLockMap") \ \ /* JVM monitoring and management support */ \ template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \ @@ -507,6 +509,10 @@ do_name( doubleToLongBits_name, "doubleToLongBits") \ do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \ do_name( longBitsToDouble_name, "longBitsToDouble") \ + \ + do_intrinsic(_bitCount_i, java_lang_Integer, bitCount_name, int_int_signature, F_S) \ + do_intrinsic(_bitCount_l, java_lang_Long, bitCount_name, long_int_signature, F_S) \ + \ do_intrinsic(_reverseBytes_i, java_lang_Integer, reverseBytes_name, int_int_signature, F_S) \ do_name( reverseBytes_name, "reverseBytes") \ do_intrinsic(_reverseBytes_l, java_lang_Long, reverseBytes_name, long_long_signature, F_S) \ @@ -696,7 +702,6 @@ do_signature(putShort_raw_signature, "(JS)V") \ do_signature(getChar_raw_signature, "(J)C") \ do_signature(putChar_raw_signature, "(JC)V") \ - do_signature(getInt_raw_signature, "(J)I") \ do_signature(putInt_raw_signature, "(JI)V") \ do_alias(getLong_raw_signature, /*(J)J*/ long_long_signature) \ do_alias(putLong_raw_signature, /*(JJ)V*/ long_long_void_signature) \ @@ -713,7 +718,7 @@ do_intrinsic(_getByte_raw, sun_misc_Unsafe, getByte_name, getByte_raw_signature, F_RN) \ do_intrinsic(_getShort_raw, sun_misc_Unsafe, getShort_name, getShort_raw_signature, F_RN) \ do_intrinsic(_getChar_raw, sun_misc_Unsafe, getChar_name, getChar_raw_signature, F_RN) \ - do_intrinsic(_getInt_raw, sun_misc_Unsafe, getInt_name, getInt_raw_signature, F_RN) \ + do_intrinsic(_getInt_raw, sun_misc_Unsafe, getInt_name, long_int_signature, F_RN) \ do_intrinsic(_getLong_raw, sun_misc_Unsafe, getLong_name, getLong_raw_signature, F_RN) \ do_intrinsic(_getFloat_raw, sun_misc_Unsafe, getFloat_name, getFloat_raw_signature, F_RN) \ do_intrinsic(_getDouble_raw, sun_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_RN) \ diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp index 2eb2bc0ca69..6f12a396216 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp @@ -145,14 +145,9 @@ void ConcurrentG1Refine::set_pya_restart() { if (G1RSBarrierUseQueue) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); dcqs.abandon_logs(); - if (_cg1rThread->do_traversal()) { - _pya = PYA_restart; - } else { - _cg1rThread->set_do_traversal(true); - // Reset the post-yield actions. - _pya = PYA_continue; - _last_pya = PYA_continue; - } + // Reset the post-yield actions. + _pya = PYA_continue; + _last_pya = PYA_continue; } else { _pya = PYA_restart; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 5b01157e9a4..fb4f502cf94 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -107,7 +107,7 @@ void CMBitMapRO::mostly_disjoint_range_union(BitMap* from_bitmap, #ifndef PRODUCT bool CMBitMapRO::covers(ReservedSpace rs) const { // assert(_bm.map() == _virtual_space.low(), "map inconsistency"); - assert(((size_t)_bm.size() * (1 << _shifter)) == _bmWordSize, + assert(((size_t)_bm.size() * (size_t)(1 << _shifter)) == _bmWordSize, "size inconsistency"); return _bmStartWord == (HeapWord*)(rs.base()) && _bmWordSize == rs.size()>>LogHeapWordSize; @@ -1232,7 +1232,16 @@ public: if (!_final && _regions_done == 0) _start_vtime_sec = os::elapsedVTime(); - if (hr->continuesHumongous()) return false; + if (hr->continuesHumongous()) { + HeapRegion* hum_start = hr->humongous_start_region(); + // If the head region of the humongous region has been determined + // to be alive, then all the tail regions should be marked + // such as well. + if (_region_bm->at(hum_start->hrs_index())) { + _region_bm->par_at_put(hr->hrs_index(), 1); + } + return false; + } HeapWord* nextTop = hr->next_top_at_mark_start(); HeapWord* start = hr->top_at_conc_mark_count(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index ecacfa6c74a..1966a7c59b4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -786,6 +786,12 @@ void G1CollectedHeap::abandon_cur_alloc_region() { } } +void G1CollectedHeap::abandon_gc_alloc_regions() { + // first, make sure that the GC alloc region list is empty (it should!) + assert(_gc_alloc_region_list == NULL, "invariant"); + release_gc_alloc_regions(true /* totally */); +} + class PostMCRemSetClearClosure: public HeapRegionClosure { ModRefBarrierSet* _mr_bs; public: @@ -914,6 +920,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, // Make sure we'll choose a new allocation region afterwards. abandon_cur_alloc_region(); + abandon_gc_alloc_regions(); assert(_cur_alloc_region == NULL, "Invariant."); g1_rem_set()->as_HRInto_G1RemSet()->cleanupHRRS(); tear_down_region_lists(); @@ -954,6 +961,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { HandleMark hm; // Discard invalid handles created during verification gclog_or_tty->print(" VerifyAfterGC:"); + prepare_for_verify(); Universe::verify(false); } NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); @@ -1306,7 +1314,7 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) } void G1CollectedHeap::shrink(size_t shrink_bytes) { - release_gc_alloc_regions(); + release_gc_alloc_regions(true /* totally */); tear_down_region_lists(); // We will rebuild them in a moment. shrink_helper(shrink_bytes); rebuild_region_lists(); @@ -1345,8 +1353,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _gc_time_stamp(0), _surviving_young_words(NULL), _in_cset_fast_test(NULL), - _in_cset_fast_test_base(NULL) -{ + _in_cset_fast_test_base(NULL) { _g1h = this; // To catch bugs. if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { vm_exit_during_initialization("Failed necessary allocation."); @@ -1371,9 +1378,19 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : } for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { - _gc_alloc_regions[ap] = NULL; - _gc_alloc_region_counts[ap] = 0; + _gc_alloc_regions[ap] = NULL; + _gc_alloc_region_counts[ap] = 0; + _retained_gc_alloc_regions[ap] = NULL; + // by default, we do not retain a GC alloc region for each ap; + // we'll override this, when appropriate, below + _retain_gc_alloc_region[ap] = false; } + + // We will try to remember the last half-full tenured region we + // allocated to at the end of a collection so that we can re-use it + // during the next collection. + _retain_gc_alloc_region[GCAllocForTenured] = true; + guarantee(_task_queues != NULL, "task_queues allocation failure."); } @@ -1405,9 +1422,34 @@ jint G1CollectedHeap::initialize() { // Reserve the maximum. PermanentGenerationSpec* pgs = collector_policy()->permanent_generation(); // Includes the perm-gen. + + const size_t total_reserved = max_byte_size + pgs->max_size(); + char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); + ReservedSpace heap_rs(max_byte_size + pgs->max_size(), HeapRegion::GrainBytes, - false /*ism*/); + false /*ism*/, addr); + + if (UseCompressedOops) { + if (addr != NULL && !heap_rs.is_reserved()) { + // Failed to reserve at specified address - the requested memory + // region is taken already, for example, by 'java' launcher. + // Try again to reserver heap higher. + addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop); + ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes, + false /*ism*/, addr); + if (addr != NULL && !heap_rs0.is_reserved()) { + // Failed to reserve at specified address again - give up. + addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop); + assert(addr == NULL, ""); + ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes, + false /*ism*/, addr); + heap_rs = heap_rs1; + } else { + heap_rs = heap_rs0; + } + } + } if (!heap_rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for object heap"); @@ -2119,15 +2161,7 @@ public: bool doHeapRegion(HeapRegion* r) { guarantee(_par || r->claim_value() == HeapRegion::InitialClaimValue, "Should be unclaimed at verify points."); - if (r->isHumongous()) { - if (r->startsHumongous()) { - // Verify the single H object. - oop(r->bottom())->verify(); - size_t word_sz = oop(r->bottom())->size(); - guarantee(r->top() == r->bottom() + word_sz, - "Only one object in a humongous region"); - } - } else { + if (!r->continuesHumongous()) { VerifyObjsInRegionClosure not_dead_yet_cl(r); r->verify(_allow_dirty); r->object_iterate(¬_dead_yet_cl); @@ -2179,6 +2213,7 @@ public: _g1h(g1h), _allow_dirty(allow_dirty) { } void work(int worker_i) { + HandleMark hm; VerifyRegionClosure blk(_allow_dirty, true); _g1h->heap_region_par_iterate_chunked(&blk, worker_i, HeapRegion::ParVerifyClaimValue); @@ -2644,7 +2679,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { popular_region->set_popular_pending(false); } - release_gc_alloc_regions(); + release_gc_alloc_regions(false /* totally */); cleanup_surviving_young_words(); @@ -2697,6 +2732,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { HandleMark hm; // Discard invalid handles created during verification gclog_or_tty->print(" VerifyAfterGC:"); + prepare_for_verify(); Universe::verify(false); } @@ -2735,6 +2771,10 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { void G1CollectedHeap::set_gc_alloc_region(int purpose, HeapRegion* r) { assert(purpose >= 0 && purpose < GCAllocPurposeCount, "invalid purpose"); + // make sure we don't call set_gc_alloc_region() multiple times on + // the same region + assert(r == NULL || !r->is_gc_alloc_region(), + "shouldn't already be a GC alloc region"); HeapWord* original_top = NULL; if (r != NULL) original_top = r->top(); @@ -2824,6 +2864,12 @@ void G1CollectedHeap::forget_alloc_region_list() { while (_gc_alloc_region_list != NULL) { HeapRegion* r = _gc_alloc_region_list; assert(r->is_gc_alloc_region(), "Invariant."); + // We need HeapRegion::oops_on_card_seq_iterate_careful() to work on + // newly allocated data in order to be able to apply deferred updates + // before the GC is done for verification purposes (i.e to allow + // G1HRRSFlushLogBuffersOnVerify). It's safe thing to do after the + // collection. + r->ContiguousSpace::set_saved_mark(); _gc_alloc_region_list = r->next_gc_alloc_region(); r->set_next_gc_alloc_region(NULL); r->set_is_gc_alloc_region(false); @@ -2851,23 +2897,55 @@ bool G1CollectedHeap::check_gc_alloc_regions() { } void G1CollectedHeap::get_gc_alloc_regions() { + // First, let's check that the GC alloc region list is empty (it should) + assert(_gc_alloc_region_list == NULL, "invariant"); + for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { + assert(_gc_alloc_regions[ap] == NULL, "invariant"); + // Create new GC alloc regions. - HeapRegion* alloc_region = _gc_alloc_regions[ap]; - // Clear this alloc region, so that in case it turns out to be - // unacceptable, we end up with no allocation region, rather than a bad - // one. - _gc_alloc_regions[ap] = NULL; - if (alloc_region == NULL || alloc_region->in_collection_set()) { - // Can't re-use old one. Allocate a new one. + HeapRegion* alloc_region = _retained_gc_alloc_regions[ap]; + _retained_gc_alloc_regions[ap] = NULL; + + if (alloc_region != NULL) { + assert(_retain_gc_alloc_region[ap], "only way to retain a GC region"); + + // let's make sure that the GC alloc region is not tagged as such + // outside a GC operation + assert(!alloc_region->is_gc_alloc_region(), "sanity"); + + if (alloc_region->in_collection_set() || + alloc_region->top() == alloc_region->end() || + alloc_region->top() == alloc_region->bottom()) { + // we will discard the current GC alloc region if it's in the + // collection set (it can happen!), if it's already full (no + // point in using it), or if it's empty (this means that it + // was emptied during a cleanup and it should be on the free + // list now). + + alloc_region = NULL; + } + } + + if (alloc_region == NULL) { + // we will get a new GC alloc region alloc_region = newAllocRegionWithExpansion(ap, 0); } + if (alloc_region != NULL) { + assert(_gc_alloc_regions[ap] == NULL, "pre-condition"); set_gc_alloc_region(ap, alloc_region); } + + assert(_gc_alloc_regions[ap] == NULL || + _gc_alloc_regions[ap]->is_gc_alloc_region(), + "the GC alloc region should be tagged as such"); + assert(_gc_alloc_regions[ap] == NULL || + _gc_alloc_regions[ap] == _gc_alloc_region_list, + "the GC alloc region should be the same as the GC alloc list head"); } // Set alternative regions for allocation purposes that have reached - // thier limit. + // their limit. for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { GCAllocPurpose alt_purpose = g1_policy()->alternative_purpose(ap); if (_gc_alloc_regions[ap] == NULL && alt_purpose != ap) { @@ -2877,28 +2955,56 @@ void G1CollectedHeap::get_gc_alloc_regions() { assert(check_gc_alloc_regions(), "alloc regions messed up"); } -void G1CollectedHeap::release_gc_alloc_regions() { +void G1CollectedHeap::release_gc_alloc_regions(bool totally) { // We keep a separate list of all regions that have been alloc regions in - // the current collection pause. Forget that now. + // the current collection pause. Forget that now. This method will + // untag the GC alloc regions and tear down the GC alloc region + // list. It's desirable that no regions are tagged as GC alloc + // outside GCs. forget_alloc_region_list(); // The current alloc regions contain objs that have survived // collection. Make them no longer GC alloc regions. for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { HeapRegion* r = _gc_alloc_regions[ap]; - if (r != NULL && r->is_empty()) { - { + _retained_gc_alloc_regions[ap] = NULL; + + if (r != NULL) { + // we retain nothing on _gc_alloc_regions between GCs + set_gc_alloc_region(ap, NULL); + _gc_alloc_region_counts[ap] = 0; + + if (r->is_empty()) { + // we didn't actually allocate anything in it; let's just put + // it on the free list MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag); r->set_zero_fill_complete(); put_free_region_on_list_locked(r); + } else if (_retain_gc_alloc_region[ap] && !totally) { + // retain it so that we can use it at the beginning of the next GC + _retained_gc_alloc_regions[ap] = r; } } - // set_gc_alloc_region will also NULLify all aliases to the region - set_gc_alloc_region(ap, NULL); - _gc_alloc_region_counts[ap] = 0; } } +#ifndef PRODUCT +// Useful for debugging + +void G1CollectedHeap::print_gc_alloc_regions() { + gclog_or_tty->print_cr("GC alloc regions"); + for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { + HeapRegion* r = _gc_alloc_regions[ap]; + if (r == NULL) { + gclog_or_tty->print_cr(" %2d : "PTR_FORMAT, ap, NULL); + } else { + gclog_or_tty->print_cr(" %2d : "PTR_FORMAT" "SIZE_FORMAT, + ap, r->bottom(), r->used()); + } + } +} +#endif // PRODUCT + void G1CollectedHeap::init_for_evac_failure(OopsInHeapRegionClosure* cl) { _drain_in_progress = false; set_evac_failure_closure(cl); @@ -3658,7 +3764,9 @@ protected: CardTableModRefBS* ctbs() { return _ct_bs; } void immediate_rs_update(HeapRegion* from, oop* p, int tid) { - _g1_rem->par_write_ref(from, p, tid); + if (!from->is_survivor()) { + _g1_rem->par_write_ref(from, p, tid); + } } void deferred_rs_update(HeapRegion* from, oop* p, int tid) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 4ac3cf220fb..e67e4d4cab3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -172,7 +172,6 @@ private: NumAPIs = HeapRegion::MaxAge }; - // The one and only G1CollectedHeap, so static functions can find it. static G1CollectedHeap* _g1h; @@ -217,11 +216,20 @@ private: // Postcondition: cur_alloc_region == NULL. void abandon_cur_alloc_region(); + void abandon_gc_alloc_regions(); // The to-space memory regions into which objects are being copied during // a GC. HeapRegion* _gc_alloc_regions[GCAllocPurposeCount]; size_t _gc_alloc_region_counts[GCAllocPurposeCount]; + // These are the regions, one per GCAllocPurpose, that are half-full + // at the end of a collection and that we want to reuse during the + // next collection. + HeapRegion* _retained_gc_alloc_regions[GCAllocPurposeCount]; + // This specifies whether we will keep the last half-full region at + // the end of a collection so that it can be reused during the next + // collection (this is specified per GCAllocPurpose) + bool _retain_gc_alloc_region[GCAllocPurposeCount]; // A list of the regions that have been set to be alloc regions in the // current collection. @@ -589,8 +597,21 @@ protected: // Ensure that the relevant gc_alloc regions are set. void get_gc_alloc_regions(); - // We're done with GC alloc regions; release them, as appropriate. - void release_gc_alloc_regions(); + // We're done with GC alloc regions. We are going to tear down the + // gc alloc list and remove the gc alloc tag from all the regions on + // that list. However, we will also retain the last (i.e., the one + // that is half-full) GC alloc region, per GCAllocPurpose, for + // possible reuse during the next collection, provided + // _retain_gc_alloc_region[] indicates that it should be the + // case. Said regions are kept in the _retained_gc_alloc_regions[] + // array. If the parameter totally is set, we will not retain any + // regions, irrespective of what _retain_gc_alloc_region[] + // indicates. + void release_gc_alloc_regions(bool totally); +#ifndef PRODUCT + // Useful for debugging. + void print_gc_alloc_regions(); +#endif // !PRODUCT // ("Weak") Reference processing support ReferenceProcessor* _ref_processor; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 5de297a4ebd..6147c8b6c67 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1087,6 +1087,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, assert(_g1->used_regions() == _g1->recalculate_used_regions(), "sanity"); + assert(_g1->used() == _g1->recalculate_used(), "sanity"); double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0; _all_stop_world_times_ms->add(s_w_t_ms); @@ -1636,7 +1637,9 @@ void G1CollectorPolicy::record_collection_pause_end(bool popular, double obj_copy_time = avg_value(_par_last_obj_copy_times_ms); double termination_time = avg_value(_par_last_termination_times_ms); - double parallel_other_time; + double parallel_other_time = _cur_collection_par_time_ms - + (update_rs_time + ext_root_scan_time + mark_stack_scan_time + + scan_only_time + scan_rs_time + obj_copy_time + termination_time); if (update_stats) { MainBodySummary* body_summary = summary->main_body_summary(); guarantee(body_summary != NULL, "should not be null!"); @@ -1655,9 +1658,6 @@ void G1CollectorPolicy::record_collection_pause_end(bool popular, body_summary->record_parallel_time_ms(_cur_collection_par_time_ms); body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms); body_summary->record_termination_time_ms(termination_time); - parallel_other_time = _cur_collection_par_time_ms - - (update_rs_time + ext_root_scan_time + mark_stack_scan_time + - scan_only_time + scan_rs_time + obj_copy_time + termination_time); body_summary->record_parallel_other_time_ms(parallel_other_time); } body_summary->record_mark_closure_time_ms(_mark_closure_time_ms); @@ -1802,8 +1802,10 @@ void G1CollectorPolicy::record_collection_pause_end(bool popular, gclog_or_tty->print_cr("]"); _all_pause_times_ms->add(elapsed_ms); - summary->record_total_time_ms(elapsed_ms); - summary->record_other_time_ms(other_time_ms); + if (update_stats) { + summary->record_total_time_ms(elapsed_ms); + summary->record_other_time_ms(other_time_ms); + } for (int i = 0; i < _aux_num; ++i) if (_cur_aux_times_set[i]) _all_aux_times_ms[i].add(_cur_aux_times_ms[i]); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index aff031a73ab..d0482ea1054 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -502,15 +502,26 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, } if (ParallelGCThreads > 0) { - // This is a temporary change to serialize the update and scanning - // of remembered sets. There are some race conditions when this is - // done in parallel and they are causing failures. When we resolve - // said race conditions, we'll revert back to parallel remembered - // set updating and scanning. See CRs 6677707 and 6677708. - if (worker_i == 0) { + // The two flags below were introduced temporarily to serialize + // the updating and scanning of remembered sets. There are some + // race conditions when these two operations are done in parallel + // and they are causing failures. When we resolve said race + // conditions, we'll revert back to parallel remembered set + // updating and scanning. See CRs 6677707 and 6677708. + if (G1EnableParallelRSetUpdating || (worker_i == 0)) { updateRS(worker_i); scanNewRefsRS(oc, worker_i); + } else { + _g1p->record_update_rs_start_time(worker_i, os::elapsedTime()); + _g1p->record_update_rs_processed_buffers(worker_i, 0.0); + _g1p->record_update_rs_time(worker_i, 0.0); + _g1p->record_scan_new_refs_time(worker_i, 0.0); + } + if (G1EnableParallelRSetScanning || (worker_i == 0)) { scanRS(oc, worker_i); + } else { + _g1p->record_scan_rs_start_time(worker_i, os::elapsedTime()); + _g1p->record_scan_rs_time(worker_i, 0.0); } } else { assert(worker_i == 0, "invariant"); @@ -716,8 +727,7 @@ public: bool doHeapRegion(HeapRegion* r) { if (!r->in_collection_set() && !r->continuesHumongous() && - !r->is_young() && - !r->is_survivor()) { + !r->is_young()) { _update_rs_oop_cl.set_from(r); UpdateRSObjectClosure update_rs_obj_cl(&_update_rs_oop_cl); @@ -854,7 +864,7 @@ void HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i) { // before all the cards on the region are dirtied. This is unlikely, // and it doesn't happen often, but it can happen. So, the extra // check below filters out those cards. - if (r->is_young() || r->is_survivor()) { + if (r->is_young()) { return; } // While we are processing RSet buffers during the collection, we @@ -1025,7 +1035,9 @@ void HRInto_G1RemSet::print_summary_info() { } } void HRInto_G1RemSet::prepare_for_verify() { - if (G1HRRSFlushLogBuffersOnVerify && VerifyBeforeGC && !_g1->full_collection()) { + if (G1HRRSFlushLogBuffersOnVerify && + (VerifyBeforeGC || VerifyAfterGC) + && !_g1->full_collection()) { cleanupHRRS(); _g1->set_refine_cte_cl_concurrency(false); if (SafepointSynchronize::is_at_safepoint()) { @@ -1036,5 +1048,7 @@ void HRInto_G1RemSet::prepare_for_verify() { _cg1r->set_use_cache(false); updateRS(0); _cg1r->set_use_cache(cg1r_use_cache); + + assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 98d512c9ec0..2b7a984a3fd 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -295,6 +295,14 @@ \ product(uintx, G1FixedSurvivorSpaceSize, 0, \ "If non-0 is the size of the G1 survivor space, " \ - "otherwise SurvivorRatio is used to determine the size") + "otherwise SurvivorRatio is used to determine the size") \ + \ + experimental(bool, G1EnableParallelRSetUpdating, false, \ + "Enables the parallelization of remembered set updating " \ + "during evacuation pauses") \ + \ + experimental(bool, G1EnableParallelRSetScanning, false, \ + "Enables the parallelization of remembered set scanning " \ + "during evacuation pauses") G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG) diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index acb51a4fc4d..92bfe7c55a2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -508,7 +508,7 @@ OtherRegionsTable::OtherRegionsTable(HeapRegion* hr) : typedef PosParPRT* PosParPRTPtr; if (_max_fine_entries == 0) { assert(_mod_max_fine_entries_mask == 0, "Both or none."); - _max_fine_entries = (1 << G1LogRSRegionEntries); + _max_fine_entries = (size_t)(1 << G1LogRSRegionEntries); _mod_max_fine_entries_mask = _max_fine_entries - 1; #if SAMPLE_FOR_EVICTION assert(_fine_eviction_sample_size == 0 diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp index 89331a81bd3..dddb3bb7d3c 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp @@ -63,9 +63,8 @@ public: // return NULL. HeapWord* allocate(size_t word_sz) { HeapWord* res = _top; - HeapWord* new_top = _top + word_sz; - if (new_top <= _end) { - _top = new_top; + if (pointer_delta(_end, _top) >= word_sz) { + _top = _top + word_sz; return res; } else { return NULL; @@ -75,10 +74,9 @@ public: // Undo the last allocation in the buffer, which is required to be of the // "obj" of the given "word_sz". void undo_allocation(HeapWord* obj, size_t word_sz) { - assert(_top - word_sz >= _bottom - && _top - word_sz == obj, - "Bad undo_allocation"); - _top = _top - word_sz; + assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo"); + assert(pointer_delta(_top, obj) == word_sz, "Bad undo"); + _top = obj; } // The total (word) size of the buffer, including both allocated and diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index 2d5334b780c..195847a66e2 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -104,12 +104,38 @@ jint ParallelScavengeHeap::initialize() { og_min_size, og_max_size, yg_min_size, yg_max_size); + const size_t total_reserved = pg_max_size + og_max_size + yg_max_size; + char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); + // The main part of the heap (old gen + young gen) can often use a larger page // size than is needed or wanted for the perm gen. Use the "compound // alignment" ReservedSpace ctor to avoid having to use the same page size for // all gens. + ReservedHeapSpace heap_rs(pg_max_size, pg_align, og_max_size + yg_max_size, - og_align); + og_align, addr); + + if (UseCompressedOops) { + if (addr != NULL && !heap_rs.is_reserved()) { + // Failed to reserve at specified address - the requested memory + // region is taken already, for example, by 'java' launcher. + // Try again to reserver heap higher. + addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop); + ReservedHeapSpace heap_rs0(pg_max_size, pg_align, og_max_size + yg_max_size, + og_align, addr); + if (addr != NULL && !heap_rs0.is_reserved()) { + // Failed to reserve at specified address again - give up. + addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop); + assert(addr == NULL, ""); + ReservedHeapSpace heap_rs1(pg_max_size, pg_align, og_max_size + yg_max_size, + og_align, addr); + heap_rs = heap_rs1; + } else { + heap_rs = heap_rs0; + } + } + } + os::trace_page_sizes("ps perm", pg_min_size, pg_max_size, pg_page_sz, heap_rs.base(), pg_max_size); os::trace_page_sizes("ps main", og_min_size + yg_min_size, diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index c7e5db81f88..b75a1ab39a8 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -4598,6 +4598,7 @@ vm_version_.cpp vm_version_.hpp vm_version_.hpp globals_extension.hpp vm_version_.hpp vm_version.hpp +vm_version_.cpp os.hpp vm_version_.cpp vm_version_.hpp vmreg.cpp assembler.hpp diff --git a/hotspot/src/share/vm/interpreter/invocationCounter.cpp b/hotspot/src/share/vm/interpreter/invocationCounter.cpp index cb650778556..7ecc70d1997 100644 --- a/hotspot/src/share/vm/interpreter/invocationCounter.cpp +++ b/hotspot/src/share/vm/interpreter/invocationCounter.cpp @@ -47,6 +47,8 @@ void InvocationCounter::set_carry() { // executed many more times before re-entering the VM. int old_count = count(); int new_count = MIN2(old_count, (int) (CompileThreshold / 2)); + // prevent from going to zero, to distinguish from never-executed methods + if (new_count == 0) new_count = 1; if (old_count != new_count) set(state(), new_count); } diff --git a/hotspot/src/share/vm/memory/blockOffsetTable.hpp b/hotspot/src/share/vm/memory/blockOffsetTable.hpp index 670dd86d79b..b812a243190 100644 --- a/hotspot/src/share/vm/memory/blockOffsetTable.hpp +++ b/hotspot/src/share/vm/memory/blockOffsetTable.hpp @@ -235,7 +235,7 @@ class BlockOffsetArray: public BlockOffsetTable { }; static size_t power_to_cards_back(uint i) { - return 1 << (LogBase * i); + return (size_t)(1 << (LogBase * i)); } static size_t power_to_words_back(uint i) { return power_to_cards_back(i) * N_words; diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 02e497a78d6..048bd0eca29 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -218,6 +218,31 @@ char* GenCollectedHeap::allocate(size_t alignment, heap_address -= total_reserved; } else { heap_address = NULL; // any address will do. + if (UseCompressedOops) { + heap_address = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); + *_total_reserved = total_reserved; + *_n_covered_regions = n_covered_regions; + *heap_rs = ReservedHeapSpace(total_reserved, alignment, + UseLargePages, heap_address); + + if (heap_address != NULL && !heap_rs->is_reserved()) { + // Failed to reserve at specified address - the requested memory + // region is taken already, for example, by 'java' launcher. + // Try again to reserver heap higher. + heap_address = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop); + *heap_rs = ReservedHeapSpace(total_reserved, alignment, + UseLargePages, heap_address); + + if (heap_address != NULL && !heap_rs->is_reserved()) { + // Failed to reserve at specified address again - give up. + heap_address = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop); + assert(heap_address == NULL, ""); + *heap_rs = ReservedHeapSpace(total_reserved, alignment, + UseLargePages, heap_address); + } + } + return heap_address; + } } *_total_reserved = total_reserved; diff --git a/hotspot/src/share/vm/memory/heap.cpp b/hotspot/src/share/vm/memory/heap.cpp index b0986d1e3ff..ced1bf23c01 100644 --- a/hotspot/src/share/vm/memory/heap.cpp +++ b/hotspot/src/share/vm/memory/heap.cpp @@ -112,7 +112,7 @@ bool CodeHeap::reserve(size_t reserved_size, size_t committed_size, const size_t rs_align = page_size == (size_t) os::vm_page_size() ? 0 : MAX2(page_size, granularity); - ReservedSpace rs(r_size, rs_align, rs_align > 0); + ReservedCodeSpace rs(r_size, rs_align, rs_align > 0); os::trace_page_sizes("code heap", committed_size, reserved_size, page_size, rs.base(), rs.size()); if (!_memory.initialize(rs, c_size)) { diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 3b0463308ea..b854d64892c 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -99,7 +99,8 @@ size_t Universe::_heap_capacity_at_last_gc; size_t Universe::_heap_used_at_last_gc = 0; CollectedHeap* Universe::_collectedHeap = NULL; -address Universe::_heap_base = NULL; + +NarrowOopStruct Universe::_narrow_oop = { NULL, 0, true }; void Universe::basic_type_classes_do(void f(klassOop)) { @@ -729,6 +730,53 @@ jint universe_init() { return JNI_OK; } +// Choose the heap base address and oop encoding mode +// when compressed oops are used: +// Unscaled - Use 32-bits oops without encoding when +// NarrowOopHeapBaseMin + heap_size < 4Gb +// ZeroBased - Use zero based compressed oops with encoding when +// NarrowOopHeapBaseMin + heap_size < 32Gb +// HeapBased - Use compressed oops with heap base + encoding. + +// 4Gb +static const uint64_t NarrowOopHeapMax = (uint64_t(max_juint) + 1); +// 32Gb +static const uint64_t OopEncodingHeapMax = NarrowOopHeapMax << LogMinObjAlignmentInBytes; + +char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { +#ifdef _LP64 + if (UseCompressedOops) { + assert(mode == UnscaledNarrowOop || + mode == ZeroBasedNarrowOop || + mode == HeapBasedNarrowOop, "mode is invalid"); + + const size_t total_size = heap_size + HeapBaseMinAddress; + if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) { + if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) && + (Universe::narrow_oop_shift() == 0)) { + // Use 32-bits oops without encoding and + // place heap's top on the 4Gb boundary + return (char*)(NarrowOopHeapMax - heap_size); + } else { + // Can't reserve with NarrowOopShift == 0 + Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); + if (mode == UnscaledNarrowOop || + mode == ZeroBasedNarrowOop && total_size <= NarrowOopHeapMax) { + // Use zero based compressed oops with encoding and + // place heap's top on the 32Gb boundary in case + // total_size > 4Gb or failed to reserve below 4Gb. + return (char*)(OopEncodingHeapMax - heap_size); + } + } + } else { + // Can't reserve below 32Gb. + Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); + } + } +#endif + return NULL; // also return NULL (don't care) for 32-bit VM +} + jint Universe::initialize_heap() { if (UseParallelGC) { @@ -773,6 +821,8 @@ jint Universe::initialize_heap() { if (status != JNI_OK) { return status; } + +#ifdef _LP64 if (UseCompressedOops) { // Subtract a page because something can get allocated at heap base. // This also makes implicit null checking work, because the @@ -780,8 +830,49 @@ jint Universe::initialize_heap() { // See needs_explicit_null_check. // Only set the heap base for compressed oops because it indicates // compressed oops for pstack code. - Universe::_heap_base = Universe::heap()->base() - os::vm_page_size(); + if (PrintCompressedOopsMode) { + tty->cr(); + tty->print("heap address: "PTR_FORMAT, Universe::heap()->base()); + } + if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) { + // 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) { + tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base()); + } + } else { + Universe::set_narrow_oop_base(0); + if (PrintCompressedOopsMode) { + tty->print(", zero based Compressed Oops"); + } +#ifdef _WIN64 + if (!Universe::narrow_oop_use_implicit_null_checks()) { + // Don't need guard page for implicit checks in indexed addressing + // mode with zero based Compressed Oops. + Universe::set_narrow_oop_use_implicit_null_checks(true); + } +#endif // _WIN64 + if((uint64_t)Universe::heap()->reserved_region().end() > NarrowOopHeapMax) { + // Can't reserve heap below 4Gb. + Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); + } else { + assert(Universe::narrow_oop_shift() == 0, "use unscaled narrow oop"); + if (PrintCompressedOopsMode) { + tty->print(", 32-bits Oops"); + } + } + } + if (PrintCompressedOopsMode) { + tty->cr(); + tty->cr(); + } } + assert(Universe::narrow_oop_base() == (Universe::heap()->base() - os::vm_page_size()) || + Universe::narrow_oop_base() == NULL, "invalid value"); + assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes || + Universe::narrow_oop_shift() == 0, "invalid value"); +#endif // We will never reach the CATCH below since Exceptions::_throw will cause // the VM to exit if an exception is thrown during initialization diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index 95a5f467d94..9e17a184450 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -90,6 +90,19 @@ class LatestMethodOopCache : public CommonMethodOopCache { methodOop get_methodOop(); }; +// For UseCompressedOops. +struct NarrowOopStruct { + // Base address for oop-within-java-object materialization. + // NULL if using wide oops or zero based narrow oops. + address _base; + // Number of shift bits for encoding/decoding narrow oops. + // 0 if using wide oops or zero based unscaled narrow oops, + // LogMinObjAlignmentInBytes otherwise. + int _shift; + // Generate code with implicit null checks for narrow oops. + bool _use_implicit_null_checks; +}; + class Universe: AllStatic { // Ugh. Universe is much too friendly. @@ -181,9 +194,9 @@ class Universe: AllStatic { // The particular choice of collected heap. static CollectedHeap* _collectedHeap; - // Base address for oop-within-java-object materialization. - // NULL if using wide oops. Doubles as heap oop null value. - static address _heap_base; + + // For UseCompressedOops. + static struct NarrowOopStruct _narrow_oop; // array of dummy objects used with +FullGCAlot debug_only(static objArrayOop _fullgc_alot_dummy_array;) @@ -328,8 +341,25 @@ class Universe: AllStatic { static CollectedHeap* heap() { return _collectedHeap; } // For UseCompressedOops - static address heap_base() { return _heap_base; } - static address* heap_base_addr() { return &_heap_base; } + static address* narrow_oop_base_addr() { return &_narrow_oop._base; } + static address narrow_oop_base() { return _narrow_oop._base; } + static int narrow_oop_shift() { return _narrow_oop._shift; } + static void set_narrow_oop_base(address base) { _narrow_oop._base = base; } + static void set_narrow_oop_shift(int shift) { _narrow_oop._shift = shift; } + static bool narrow_oop_use_implicit_null_checks() { return _narrow_oop._use_implicit_null_checks; } + static void set_narrow_oop_use_implicit_null_checks(bool use) { _narrow_oop._use_implicit_null_checks = use; } + // Narrow Oop encoding mode: + // 0 - Use 32-bits oops without encoding when + // NarrowOopHeapBaseMin + heap_size < 4Gb + // 1 - Use zero based compressed oops with encoding when + // NarrowOopHeapBaseMin + heap_size < 32Gb + // 2 - Use compressed oops with heap base + encoding. + enum NARROW_OOP_MODE { + UnscaledNarrowOop = 0, + ZeroBasedNarrowOop = 1, + HeapBasedNarrowOop = 2 + }; + static char* preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode); // Historic gc information static size_t get_heap_capacity_at_last_gc() { return _heap_capacity_at_last_gc; } diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 12adb12aba6..383b023c580 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1859,6 +1859,25 @@ bool instanceKlass::is_same_class_package(oop class_loader1, symbolOop class_nam } } +// Returns true iff super_method can be overridden by a method in targetclassname +// See JSL 3rd edition 8.4.6.1 +// Assumes name-signature match +// "this" is instanceKlass of super_method which must exist +// note that the instanceKlass of the method in the targetclassname has not always been created yet +bool instanceKlass::is_override(methodHandle super_method, Handle targetclassloader, symbolHandle targetclassname, TRAPS) { + // Private methods can not be overridden + if (super_method->is_private()) { + return false; + } + // If super method is accessible, then override + if ((super_method->is_protected()) || + (super_method->is_public())) { + return true; + } + // Package-private methods are not inherited outside of package + assert(super_method->is_package_private(), "must be package private"); + return(is_same_class_package(targetclassloader(), targetclassname())); +} jint instanceKlass::compute_modifier_flags(TRAPS) const { klassOop k = as_klassOop(); diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 8586ecba03b..b2a5c4b287e 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -303,6 +303,9 @@ class instanceKlass: public Klass { inner_class_next_offset = 4 }; + // method override check + bool is_override(methodHandle super_method, Handle targetclassloader, symbolHandle targetclassname, TRAPS); + // package bool is_same_class_package(klassOop class2); bool is_same_class_package(oop classloader2, symbolOop classname2); diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 9411e76509b..1efd00f7513 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -45,9 +45,10 @@ void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length, klassOop super, objArrayOop methods, AccessFlags class_flags, - oop classloader, - symbolOop classname, - objArrayOop local_interfaces + Handle classloader, + symbolHandle classname, + objArrayOop local_interfaces, + TRAPS ) { No_Safepoint_Verifier nsv; @@ -64,9 +65,9 @@ void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length, int len = methods->length(); for (int i = 0; i < len; i++) { assert(methods->obj_at(i)->is_method(), "must be a methodOop"); - methodOop m = methodOop(methods->obj_at(i)); + methodHandle mh(THREAD, methodOop(methods->obj_at(i))); - if (needs_new_vtable_entry(m, super, classloader, classname, class_flags)) { + if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) { vtable_length += vtableEntry::size(); // we need a new entry } } @@ -117,6 +118,7 @@ int klassVtable::initialize_from_super(KlassHandle super) { superVtable->copy_vtable_to(table()); #ifndef PRODUCT if (PrintVtables && Verbose) { + ResourceMark rm; tty->print_cr("copy vtable from %s to %s size %d", sk->internal_name(), klass()->internal_name(), _length); } #endif @@ -159,13 +161,13 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { int len = methods()->length(); int initialized = super_vtable_len; - // update_super_vtable can stop for gc - ensure using handles + // update_inherited_vtable can stop for gc - ensure using handles for (int i = 0; i < len; i++) { HandleMark hm(THREAD); assert(methods()->obj_at(i)->is_method(), "must be a methodOop"); methodHandle mh(THREAD, (methodOop)methods()->obj_at(i)); - bool needs_new_entry = update_super_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK); + bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, checkconstraints, CHECK); if (needs_new_entry) { put_method_at(mh(), initialized); @@ -177,7 +179,7 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { // add miranda methods; it will also update the value of initialized fill_in_mirandas(initialized); - // In class hierachieswhere the accesibility is not increasing (i.e., going from private -> + // In class hierarchies where the accessibility is not increasing (i.e., going from private -> // package_private -> publicprotected), the vtable might actually be smaller than our initial // calculation. assert(initialized <= _length, "vtable initialization failed"); @@ -188,26 +190,49 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { } } -// Interates through the vtables to find the broadest access level. This -// will always be monotomic for valid Java programs - but not neccesarily -// for incompatible class files. -klassVtable::AccessType klassVtable::vtable_accessibility_at(int i) { - // This vtable is not implementing the specific method - if (i >= length()) return acc_private; +// Called for cases where a method does not override its superclass' vtable entry +// For bytecodes not produced by javac together it is possible that a method does not override +// the superclass's method, but might indirectly override a super-super class's vtable entry +// If none found, return a null superk, else return the superk of the method this does override +instanceKlass* klassVtable::find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, + int vtable_index, Handle target_loader, symbolHandle target_classname, Thread * THREAD) { + instanceKlass* superk = initialsuper; + while (superk != NULL && superk->super() != NULL) { + instanceKlass* supersuperklass = instanceKlass::cast(superk->super()); + klassVtable* ssVtable = supersuperklass->vtable(); + if (vtable_index < ssVtable->length()) { + methodOop super_method = ssVtable->method_at(vtable_index); +#ifndef PRODUCT + symbolHandle name(THREAD,target_method()->name()); + symbolHandle signature(THREAD,target_method()->signature()); + assert(super_method->name() == name() && super_method->signature() == signature(), "vtable entry name/sig mismatch"); +#endif + if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) { +#ifndef PRODUCT + if (PrintVtables && Verbose) { + ResourceMark rm(THREAD); + tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ", + supersuperklass->internal_name(), + _klass->internal_name(), (target_method() != NULL) ? + target_method()->name()->as_C_string() : "", vtable_index); + super_method->access_flags().print_on(tty); + tty->print("overriders flags: "); + target_method->access_flags().print_on(tty); + tty->cr(); + } +#endif /*PRODUCT*/ + break; // return found superk + } + } else { + // super class has no vtable entry here, stop transitive search + superk = (instanceKlass*)NULL; + break; + } + // if no override found yet, continue to search up + superk = instanceKlass::cast(superk->super()); + } - // Compute AccessType for current method. public or protected we are done. - methodOop m = method_at(i); - if (m->is_protected() || m->is_public()) return acc_publicprotected; - - AccessType acc = m->is_package_private() ? acc_package_private : acc_private; - - // Compute AccessType for method in super classes - klassOop super = klass()->super(); - AccessType super_acc = (super != NULL) ? instanceKlass::cast(klass()->super())->vtable()->vtable_accessibility_at(i) - : acc_private; - - // Merge - return (AccessType)MAX2((int)acc, (int)super_acc); + return superk; } @@ -215,7 +240,8 @@ klassVtable::AccessType klassVtable::vtable_accessibility_at(int i) { // OR return true if a new vtable entry is required // Only called for instanceKlass's, i.e. not for arrays // If that changed, could not use _klass as handle for klass -bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS) { +bool klassVtable::update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, + bool checkconstraints, TRAPS) { ResourceMark rm; bool allocate_new = true; assert(klass->oop_is_instance(), "must be instanceKlass"); @@ -242,58 +268,35 @@ bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_ } // private methods always have a new entry in the vtable + // specification interpretation since classic has + // private methods not overriding if (target_method()->is_private()) { return allocate_new; } // search through the vtable and update overridden entries // Since check_signature_loaders acquires SystemDictionary_lock - // which can block for gc, once we are in this loop, use handles, not - // unhandled oops unless they are reinitialized for each loop - // handles for name, signature, klass, target_method - // not for match_method, holder + // which can block for gc, once we are in this loop, use handles + // For classfiles built with >= jdk7, we now look for transitive overrides symbolHandle name(THREAD,target_method()->name()); symbolHandle signature(THREAD,target_method()->signature()); + Handle target_loader(THREAD, _klass->class_loader()); + symbolHandle target_classname(THREAD, _klass->name()); for(int i = 0; i < super_vtable_len; i++) { - methodOop match_method = method_at(i); + methodOop super_method = method_at(i); // Check if method name matches - if (match_method->name() == name() && match_method->signature() == signature()) { + if (super_method->name() == name() && super_method->signature() == signature()) { - instanceKlass* holder = (THREAD, instanceKlass::cast(match_method->method_holder())); + // get super_klass for method_holder for the found method + instanceKlass* super_klass = instanceKlass::cast(super_method->method_holder()); - // Check if the match_method is accessable from current class - - bool same_package_init = false; - bool same_package_flag = false; - bool simple_match = match_method->is_public() || match_method->is_protected(); - if (!simple_match) { - same_package_init = true; - same_package_flag = holder->is_same_class_package(_klass->class_loader(), _klass->name()); - - simple_match = match_method->is_package_private() && same_package_flag; - } - // match_method is the superclass' method. Note we can't override - // and shouldn't access superclass' ACC_PRIVATE methods - // (although they have been copied into our vtable) - // A simple form of this statement is: - // if ( (match_method->is_public() || match_method->is_protected()) || - // (match_method->is_package_private() && holder->is_same_class_package(klass->class_loader(), klass->name()))) { - // - // The complexity is introduced it avoid recomputing 'is_same_class_package' which is expensive. - if (simple_match) { - // Check if target_method and match_method has same level of accessibility. The accesibility of the - // match method is the "most-general" visibility of all entries at it's particular vtable index for - // all superclasses. This check must be done before we override the current entry in the vtable. - AccessType at = vtable_accessibility_at(i); - bool same_access = false; - - if ( (at == acc_publicprotected && (target_method()->is_public() || target_method()->is_protected()) - || (at == acc_package_private && (target_method()->is_package_private() && - (( same_package_init && same_package_flag) || - (!same_package_init && holder->is_same_class_package(_klass->class_loader(), _klass->name()))))))) { - same_access = true; - } + if ((super_klass->is_override(super_method, target_loader, target_classname, THREAD)) || + ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION) + && ((super_klass = find_transitive_override(super_klass, target_method, i, target_loader, + target_classname, THREAD)) != (instanceKlass*)NULL))) { + // overriding, so no new entry + allocate_new = false; if (checkconstraints) { // Override vtable entry if passes loader constraint check @@ -302,15 +305,12 @@ bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_ // have already made any needed loader constraints. // Since loader constraints are transitive, it is enough // to link to the first super, and we get all the others. - symbolHandle signature(THREAD, target_method()->signature()); - Handle this_loader(THREAD, _klass->class_loader()); - instanceKlassHandle super_klass(THREAD, _klass->super()); Handle super_loader(THREAD, super_klass->class_loader()); - if (this_loader() != super_loader()) { + if (target_loader() != super_loader()) { ResourceMark rm(THREAD); char* failed_type_name = - SystemDictionary::check_signature_loaders(signature, this_loader, + SystemDictionary::check_signature_loaders(signature, target_loader, super_loader, true, CHECK_(false)); if (failed_type_name != NULL) { @@ -320,7 +320,7 @@ bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_ "(instance of %s), have different Class objects for the type " "%s used in the signature"; char* sig = target_method()->name_and_sig_as_C_string(); - const char* loader1 = SystemDictionary::loader_name(this_loader()); + const char* loader1 = SystemDictionary::loader_name(target_loader()); char* current = _klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(super_loader()); size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + @@ -331,59 +331,46 @@ bool klassVtable::update_super_vtable(instanceKlass* klass, methodHandle target_ THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false); } } - } + } + put_method_at(target_method(), i); - - - if (same_access) { - // target and match has same accessiblity - share entry - allocate_new = false; - target_method()->set_vtable_index(i); + target_method()->set_vtable_index(i); #ifndef PRODUCT - if (PrintVtables && Verbose) { - AccessType targetacc; - if (target_method()->is_protected() || - target_method()->is_public()) { - targetacc = acc_publicprotected; - } else { - targetacc = target_method()->is_package_private() ? acc_package_private : acc_private; - } - tty->print_cr("overriding with %s::%s index %d, original flags: %x overriders flags: %x", - _klass->internal_name(), (target_method() != NULL) ? - target_method()->name()->as_C_string() : "", i, - at, targetacc); - } -#endif /*PRODUCT*/ - } else { -#ifndef PRODUCT - if (PrintVtables && Verbose) { - AccessType targetacc; - if (target_method()->is_protected() || - target_method()->is_public()) { - targetacc = acc_publicprotected; - } else { - targetacc = target_method()->is_package_private() ? acc_package_private : acc_private; - } - tty->print_cr("override %s %s::%s at index %d, original flags: %x overriders flags: %x", - allocate_new ? "+ new" : "only", - _klass->internal_name(), (target_method() != NULL) ? - target_method()->name()->as_C_string() : "", i, - at, targetacc); - } -#endif /*PRODUCT*/ + if (PrintVtables && Verbose) { + tty->print("overriding with %s::%s index %d, original flags: ", + _klass->internal_name(), (target_method() != NULL) ? + target_method()->name()->as_C_string() : "", i); + super_method->access_flags().print_on(tty); + tty->print("overriders flags: "); + target_method->access_flags().print_on(tty); + tty->cr(); } +#endif /*PRODUCT*/ + } else { + // allocate_new = true; default. We might override one entry, + // but not override another. Once we override one, not need new +#ifndef PRODUCT + if (PrintVtables && Verbose) { + tty->print("NOT overriding with %s::%s index %d, original flags: ", + _klass->internal_name(), (target_method() != NULL) ? + target_method()->name()->as_C_string() : "", i); + super_method->access_flags().print_on(tty); + tty->print("overriders flags: "); + target_method->access_flags().print_on(tty); + tty->cr(); + } +#endif /*PRODUCT*/ } } } return allocate_new; } - - void klassVtable::put_method_at(methodOop m, int index) { assert(m->is_oop_or_null(), "Not an oop or null"); #ifndef PRODUCT if (PrintVtables && Verbose) { + ResourceMark rm; tty->print_cr("adding %s::%s at index %d", _klass->internal_name(), (m != NULL) ? m->name()->as_C_string() : "", index); } @@ -397,19 +384,23 @@ void klassVtable::put_method_at(methodOop m, int index) { // by "classloader" and "classname". // NOTE: The logic used here is very similar to the one used for computing // the vtables indices for a method. We cannot directly use that function because, -// when the Universe is boostrapping, a super's vtable might not be initialized. -bool klassVtable::needs_new_vtable_entry(methodOop target_method, +// we allocate the instanceKlass at load time, and that requires that the +// superclass has been loaded. +// However, the vtable entries are filled in at link time, and therefore +// the superclass' vtable may not yet have been filled in. +bool klassVtable::needs_new_vtable_entry(methodHandle target_method, klassOop super, - oop classloader, - symbolOop classname, - AccessFlags class_flags) { - if ((class_flags.is_final() || target_method->is_final()) || + Handle classloader, + symbolHandle classname, + AccessFlags class_flags, + TRAPS) { + if ((class_flags.is_final() || target_method()->is_final()) || // a final method never needs a new entry; final methods can be statically // resolved and they have to be present in the vtable only if they override // a super's method, in which case they re-use its entry - (target_method->is_static()) || + (target_method()->is_static()) || // static methods don't need to be in vtable - (target_method->name() == vmSymbols::object_initializer_name()) + (target_method()->name() == vmSymbols::object_initializer_name()) // is never called dynamically-bound ) { return false; @@ -421,55 +412,58 @@ bool klassVtable::needs_new_vtable_entry(methodOop target_method, } // private methods always have a new entry in the vtable - if (target_method->is_private()) { + // specification interpretation since classic has + // private methods not overriding + if (target_method()->is_private()) { return true; } // search through the super class hierarchy to see if we need // a new entry - symbolOop name = target_method->name(); - symbolOop signature = target_method->signature(); + ResourceMark rm; + symbolOop name = target_method()->name(); + symbolOop signature = target_method()->signature(); klassOop k = super; - methodOop match_method = NULL; + methodOop super_method = NULL; instanceKlass *holder = NULL; + methodOop recheck_method = NULL; while (k != NULL) { // lookup through the hierarchy for a method with matching name and sign. - match_method = instanceKlass::cast(k)->lookup_method(name, signature); - if (match_method == NULL) { + super_method = instanceKlass::cast(k)->lookup_method(name, signature); + if (super_method == NULL) { break; // we still have to search for a matching miranda method } // get the class holding the matching method - holder = instanceKlass::cast(match_method->method_holder()); - - if (!match_method->is_static()) { // we want only instance method matches - if ((target_method->is_public() || target_method->is_protected()) && - (match_method->is_public() || match_method->is_protected())) { - // target and match are public/protected; we do not need a new entry - return false; - } - - if (target_method->is_package_private() && - match_method->is_package_private() && - holder->is_same_class_package(classloader, classname)) { - // target and match are P private; we do not need a new entry + // make sure you use that class for is_override + instanceKlass* superk = instanceKlass::cast(super_method->method_holder()); + // we want only instance method matches + // pretend private methods are not in the super vtable + // since we do override around them: e.g. a.m pub/b.m private/c.m pub, + // ignore private, c.m pub does override a.m pub + // For classes that were not javac'd together, we also do transitive overriding around + // methods that have less accessibility + if ((!super_method->is_static()) && + (!super_method->is_private())) { + if (superk->is_override(super_method, classloader, classname, THREAD)) { return false; + // else keep looking for transitive overrides } } - k = holder->super(); // haven't found a match yet; continue to look + // Start with lookup result and continue to search up + k = superk->super(); // haven't found an override match yet; continue to look } // if the target method is public or protected it may have a matching // miranda method in the super, whose entry it should re-use. - if (target_method->is_public() || target_method->is_protected()) { - instanceKlass *sk = instanceKlass::cast(super); - if (sk->has_miranda_methods()) { - if (sk->lookup_method_in_all_interfaces(name, signature) != NULL) { - return false; // found a matching miranda; we do not need a new entry - } + // Actually, to handle cases that javac would not generate, we need + // this check for all access permissions. + instanceKlass *sk = instanceKlass::cast(super); + if (sk->has_miranda_methods()) { + if (sk->lookup_method_in_all_interfaces(name, signature) != NULL) { + return false; // found a matching miranda; we do not need a new entry } } - return true; // found no match; we need a new entry } @@ -884,7 +878,7 @@ void klassItable::initialize_itable(bool checkconstraints, TRAPS) { _klass->name()->as_C_string()); - // Interate through all interfaces + // Iterate through all interfaces int i; for(i = 0; i < num_interfaces; i++) { itableOffsetEntry* ioe = offset_entry(i); @@ -1012,6 +1006,7 @@ void klassItable::adjust_method_entries(methodOop* old_methods, methodOop* new_m new_method->name()->as_C_string(), new_method->signature()->as_C_string())); } + break; } ime++; } diff --git a/hotspot/src/share/vm/oops/klassVtable.hpp b/hotspot/src/share/vm/oops/klassVtable.hpp index 2ef1848f59e..889d9733646 100644 --- a/hotspot/src/share/vm/oops/klassVtable.hpp +++ b/hotspot/src/share/vm/oops/klassVtable.hpp @@ -70,8 +70,9 @@ class klassVtable : public ResourceObj { // conputes vtable length (in words) and the number of miranda methods static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods, klassOop super, objArrayOop methods, - AccessFlags class_flags, oop classloader, - symbolOop classname, objArrayOop local_interfaces); + AccessFlags class_flags, Handle classloader, + symbolHandle classname, objArrayOop local_interfaces, + TRAPS); // RedefineClasses() API support: // If any entry of this vtable points to any of old_methods, @@ -111,14 +112,16 @@ class klassVtable : public ResourceObj { protected: friend class vtableEntry; private: + enum { VTABLE_TRANSITIVE_OVERRIDE_VERSION = 51 } ; void copy_vtable_to(vtableEntry* start); int initialize_from_super(KlassHandle super); int index_of(methodOop m, int len) const; // same as index_of, but search only up to len void put_method_at(methodOop m, int index); - static bool needs_new_vtable_entry(methodOop m, klassOop super, oop classloader, symbolOop classname, AccessFlags access_flags); - AccessType vtable_accessibility_at(int i); + static bool needs_new_vtable_entry(methodHandle m, klassOop super, Handle classloader, symbolHandle classname, AccessFlags access_flags, TRAPS); - bool update_super_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS); + bool update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS); + instanceKlass* find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, int vtable_index, + Handle target_loader, symbolHandle target_classname, Thread* THREAD); // support for miranda methods bool is_miranda_entry_at(int i); diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 7a184f3a638..eb74793bd24 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -148,10 +148,11 @@ inline bool oopDesc::is_null(narrowOop obj) { return obj == 0; } inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) { assert(!is_null(v), "oop value can never be zero"); - address heap_base = Universe::heap_base(); - uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)heap_base, 1)); + address base = Universe::narrow_oop_base(); + int shift = Universe::narrow_oop_shift(); + uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); - uint64_t result = pd >> LogMinObjAlignmentInBytes; + uint64_t result = pd >> shift; assert((result & CONST64(0xffffffff00000000)) == 0, "narrow oop overflow"); return (narrowOop)result; } @@ -162,8 +163,9 @@ inline narrowOop oopDesc::encode_heap_oop(oop v) { inline oop oopDesc::decode_heap_oop_not_null(narrowOop v) { assert(!is_null(v), "narrow oop value can never be zero"); - address heap_base = Universe::heap_base(); - return (oop)(void*)((uintptr_t)heap_base + ((uintptr_t)v << LogMinObjAlignmentInBytes)); + address base = Universe::narrow_oop_base(); + int shift = Universe::narrow_oop_shift(); + return (oop)(void*)((uintptr_t)base + ((uintptr_t)v << shift)); } inline oop oopDesc::decode_heap_oop(narrowOop v) { diff --git a/hotspot/src/share/vm/opto/addnode.cpp b/hotspot/src/share/vm/opto/addnode.cpp index 2ff10cd083d..63932df349d 100644 --- a/hotspot/src/share/vm/opto/addnode.cpp +++ b/hotspot/src/share/vm/opto/addnode.cpp @@ -756,7 +756,13 @@ const Type *AddPNode::mach_bottom_type( const MachNode* n) { if ( eti == NULL ) { // there must be one pointer among the operands guarantee(tptr == NULL, "must be only one pointer operand"); - tptr = et->isa_oopptr(); + if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { + // 32-bits narrow oop can be the base of address expressions + tptr = et->make_ptr()->isa_oopptr(); + } else { + // only regular oops are expected here + tptr = et->isa_oopptr(); + } guarantee(tptr != NULL, "non-int operand must be pointer"); if (tptr->higher_equal(tp->add_offset(tptr->offset()))) tp = tptr; // Set more precise type for bailout diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index d527f5ea475..87adb737cb7 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -184,6 +184,8 @@ macro(PCTable) macro(Parm) macro(PartialSubtypeCheck) macro(Phi) +macro(PopCountI) +macro(PopCountL) macro(PowD) macro(PrefetchRead) macro(PrefetchWrite) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index d1b9332a9cd..f3197152194 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -2081,7 +2081,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { #ifdef _LP64 case Op_CastPP: - if (n->in(1)->is_DecodeN() && UseImplicitNullCheckForNarrowOop) { + if (n->in(1)->is_DecodeN() && Universe::narrow_oop_use_implicit_null_checks()) { Compile* C = Compile::current(); Node* in1 = n->in(1); const Type* t = n->bottom_type(); @@ -2136,7 +2136,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { new_in2 = in2->in(1); } else if (in2->Opcode() == Op_ConP) { const Type* t = in2->bottom_type(); - if (t == TypePtr::NULL_PTR && UseImplicitNullCheckForNarrowOop) { + if (t == TypePtr::NULL_PTR && Universe::narrow_oop_use_implicit_null_checks()) { new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); // // This transformation together with CastPP transformation above diff --git a/hotspot/src/share/vm/opto/connode.cpp b/hotspot/src/share/vm/opto/connode.cpp index d46b6d4e952..46f13c652b6 100644 --- a/hotspot/src/share/vm/opto/connode.cpp +++ b/hotspot/src/share/vm/opto/connode.cpp @@ -433,7 +433,7 @@ Node *ConstraintCastNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { // If not converting int->oop, throw away cast after constant propagation Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { const Type *t = ccp->type(in(1)); - if (!t->isa_oop_ptr() || in(1)->is_DecodeN()) { + if (!t->isa_oop_ptr() || (in(1)->is_DecodeN() && Universe::narrow_oop_use_implicit_null_checks())) { return NULL; // do not transform raw pointers or narrow oops } return ConstraintCastNode::Ideal_DU_postCCP(ccp); diff --git a/hotspot/src/share/vm/opto/connode.hpp b/hotspot/src/share/vm/opto/connode.hpp index a16d7f2ee84..4c078d1b091 100644 --- a/hotspot/src/share/vm/opto/connode.hpp +++ b/hotspot/src/share/vm/opto/connode.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -635,3 +635,23 @@ class MoveD2LNode : public Node { virtual uint ideal_reg() const { return Op_RegL; } virtual const Type* Value( PhaseTransform *phase ) const; }; + +//---------- PopCountINode ----------------------------------------------------- +// Population count (bit count) of an integer. +class PopCountINode : public Node { +public: + PopCountINode(Node* in1) : Node(0, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::INT; } + virtual uint ideal_reg() const { return Op_RegI; } +}; + +//---------- PopCountLNode ----------------------------------------------------- +// Population count (bit count) of a long. +class PopCountLNode : public Node { +public: + PopCountLNode(Node* in1) : Node(0, in1) {} + virtual int Opcode() const; + const Type* bottom_type() const { return TypeInt::INT; } + virtual uint ideal_reg() const { return Op_RegI; } +}; diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 9313ae4f8ce..e28730d27f1 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -2277,7 +2277,7 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { r_not_subtype->init_req(1, _gvn.transform( new (C, 1) IfTrueNode (iff2) ) ); set_control( _gvn.transform( new (C, 1) IfFalseNode(iff2) ) ); - // Check for self. Very rare to get here, but its taken 1/3 the time. + // Check for self. Very rare to get here, but it is taken 1/3 the time. // No performance impact (too rare) but allows sharing of secondary arrays // which has some footprint reduction. Node *cmp3 = _gvn.transform( new (C, 3) CmpPNode( subklass, superklass ) ); @@ -2286,11 +2286,27 @@ Node* GraphKit::gen_subtype_check(Node* subklass, Node* superklass) { r_ok_subtype->init_req(2, _gvn.transform( new (C, 1) IfTrueNode ( iff3 ) ) ); set_control( _gvn.transform( new (C, 1) IfFalseNode( iff3 ) ) ); + // -- Roads not taken here: -- + // We could also have chosen to perform the self-check at the beginning + // of this code sequence, as the assembler does. This would not pay off + // the same way, since the optimizer, unlike the assembler, can perform + // static type analysis to fold away many successful self-checks. + // Non-foldable self checks work better here in second position, because + // the initial primary superclass check subsumes a self-check for most + // types. An exception would be a secondary type like array-of-interface, + // which does not appear in its own primary supertype display. + // Finally, we could have chosen to move the self-check into the + // PartialSubtypeCheckNode, and from there out-of-line in a platform + // dependent manner. But it is worthwhile to have the check here, + // where it can be perhaps be optimized. The cost in code space is + // small (register compare, branch). + // Now do a linear scan of the secondary super-klass array. Again, no real // performance impact (too rare) but it's gotta be done. - // (The stub also contains the self-check of subklass == superklass. // Since the code is rarely used, there is no penalty for moving it - // out of line, and it can only improve I-cache density.) + // out of line, and it can only improve I-cache density. + // The decision to inline or out-of-line this final check is platform + // dependent, and is found in the AD file definition of PartialSubtypeCheck. Node* psc = _gvn.transform( new (C, 3) PartialSubtypeCheckNode(control(), subklass, superklass) ); diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index eedfa6928f9..4c83f0af66d 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -158,7 +158,14 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe continue; // Give up if offset is beyond page size // cannot reason about it; is probably not implicit null exception } else { - const TypePtr* tptr = base->bottom_type()->is_ptr(); + const TypePtr* tptr; + if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { + // 32-bits narrow oop can be the base of address expressions + tptr = base->bottom_type()->make_ptr(); + } else { + // only regular oops are expected here + tptr = base->bottom_type()->is_ptr(); + } // Give up if offset is not a compile-time constant if( offset == Type::OffsetBot || tptr->_offset == Type::OffsetBot ) continue; diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 6cbcee84b51..b5b7136a375 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -221,6 +221,7 @@ class LibraryCallKit : public GraphKit { bool inline_unsafe_CAS(BasicType type); bool inline_unsafe_ordered_store(BasicType type); bool inline_fp_conversions(vmIntrinsics::ID id); + bool inline_bitCount(vmIntrinsics::ID id); bool inline_reverseBytes(vmIntrinsics::ID id); }; @@ -314,6 +315,11 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { if (!JDK_Version::is_gte_jdk14x_version()) return NULL; break; + case vmIntrinsics::_bitCount_i: + case vmIntrinsics::_bitCount_l: + if (!UsePopCountInstruction) return NULL; + break; + default: break; } @@ -617,6 +623,10 @@ bool LibraryCallKit::try_to_inline() { case vmIntrinsics::_longBitsToDouble: return inline_fp_conversions(intrinsic_id()); + case vmIntrinsics::_bitCount_i: + case vmIntrinsics::_bitCount_l: + return inline_bitCount(intrinsic_id()); + case vmIntrinsics::_reverseBytes_i: case vmIntrinsics::_reverseBytes_l: return inline_reverseBytes((vmIntrinsics::ID) intrinsic_id()); @@ -1714,6 +1724,27 @@ inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) { } } +//----------------------------inline_bitCount_int/long----------------------- +// inline int Integer.bitCount(int) +// inline int Long.bitCount(long) +bool LibraryCallKit::inline_bitCount(vmIntrinsics::ID id) { + assert(id == vmIntrinsics::_bitCount_i || id == vmIntrinsics::_bitCount_l, "not bitCount"); + if (id == vmIntrinsics::_bitCount_i && !Matcher::has_match_rule(Op_PopCountI)) return false; + if (id == vmIntrinsics::_bitCount_l && !Matcher::has_match_rule(Op_PopCountL)) return false; + _sp += arg_size(); // restore stack pointer + switch (id) { + case vmIntrinsics::_bitCount_i: + push(_gvn.transform(new (C, 2) PopCountINode(pop()))); + break; + case vmIntrinsics::_bitCount_l: + push(_gvn.transform(new (C, 2) PopCountLNode(pop_pair()))); + break; + default: + ShouldNotReachHere(); + } + return true; +} + //----------------------------inline_reverseBytes_int/long------------------- // inline Integer.reverseBytes(int) // inline Long.reverseBytes(long) diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 6131535561e..100f79fd9e1 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -1481,8 +1481,13 @@ MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) { const Type* mach_at = mach->adr_type(); // DecodeN node consumed by an address may have different type // then its input. Don't compare types for such case. - if (m->adr_type() != mach_at && m->in(MemNode::Address)->is_AddP() && - m->in(MemNode::Address)->in(AddPNode::Address)->is_DecodeN()) { + if (m->adr_type() != mach_at && + (m->in(MemNode::Address)->is_DecodeN() || + m->in(MemNode::Address)->is_AddP() && + m->in(MemNode::Address)->in(AddPNode::Address)->is_DecodeN() || + m->in(MemNode::Address)->is_AddP() && + m->in(MemNode::Address)->in(AddPNode::Address)->is_AddP() && + m->in(MemNode::Address)->in(AddPNode::Address)->in(AddPNode::Address)->is_DecodeN())) { mach_at = m->adr_type(); } if (m->adr_type() != mach_at) { diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index bd4f1ec3223..bde5dba7771 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -301,6 +301,10 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader, Handle(), &st, CHECK_NULL); + if (TraceClassResolution && k != NULL) { + trace_class_resolution(k); + } + cls = (jclass)JNIHandles::make_local( env, Klass::cast(k)->java_mirror()); return cls; @@ -365,6 +369,10 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, thread); + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); + } + // If we were the first invocation of jni_FindClass, we enable compilation again // rather than just allowing invocation counter to overflow and decay. // Controlled by flag DelayCompilationDuringStartup. @@ -2646,7 +2654,12 @@ static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) { Handle protection_domain; // null protection domain symbolHandle sym = oopFactory::new_symbol_handle(name, CHECK_NULL); - return find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL); + jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL); + + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); + } + return result; } // These lookups are done with the NULL (bootstrap) ClassLoader to diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index cf866df9f61..5d341330506 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -64,6 +64,7 @@ static void trace_class_resolution_impl(klassOop to_class, TRAPS) { ResourceMark rm; int line_number = -1; const char * source_file = NULL; + const char * trace = "explicit"; klassOop caller = NULL; JavaThread* jthread = JavaThread::current(); if (jthread->has_last_Java_frame()) { @@ -107,12 +108,21 @@ static void trace_class_resolution_impl(klassOop to_class, TRAPS) { (last_caller->name() == vmSymbols::loadClassInternal_name() || last_caller->name() == vmSymbols::loadClass_name())) { found_it = true; + } else if (!vfst.at_end()) { + if (vfst.method()->is_native()) { + // JNI call + found_it = true; + } } if (found_it && !vfst.at_end()) { // found the caller caller = vfst.method()->method_holder(); line_number = vfst.method()->line_number_from_bci(vfst.bci()); - symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name(); + if (line_number == -1) { + // show method name if it's a native method + trace = vfst.method()->name_and_sig_as_C_string(); + } + symbolOop s = instanceKlass::cast(caller)->source_file_name(); if (s != NULL) { source_file = s->as_C_string(); } @@ -124,15 +134,15 @@ static void trace_class_resolution_impl(klassOop to_class, TRAPS) { const char * to = Klass::cast(to_class)->external_name(); // print in a single call to reduce interleaving between threads if (source_file != NULL) { - tty->print("RESOLVE %s %s %s:%d (explicit)\n", from, to, source_file, line_number); + tty->print("RESOLVE %s %s %s:%d (%s)\n", from, to, source_file, line_number, trace); } else { - tty->print("RESOLVE %s %s (explicit)\n", from, to); + tty->print("RESOLVE %s %s (%s)\n", from, to, trace); } } } } -static void trace_class_resolution(klassOop to_class) { +void trace_class_resolution(klassOop to_class) { EXCEPTION_MARK; trace_class_resolution_impl(to_class, THREAD); if (HAS_PENDING_EXCEPTION) { @@ -3213,8 +3223,12 @@ JVM_ENTRY(jclass, JVM_LoadClass0(JNIEnv *env, jobject receiver, } Handle h_loader(THREAD, loader); Handle h_prot (THREAD, protection_domain); - return find_class_from_class_loader(env, name, true, h_loader, h_prot, - false, thread); + jclass result = find_class_from_class_loader(env, name, true, h_loader, h_prot, + false, thread); + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); + } + return result; JVM_END diff --git a/hotspot/src/share/vm/prims/jvm_misc.hpp b/hotspot/src/share/vm/prims/jvm_misc.hpp index 7af47518c0f..50644842bbd 100644 --- a/hotspot/src/share/vm/prims/jvm_misc.hpp +++ b/hotspot/src/share/vm/prims/jvm_misc.hpp @@ -27,6 +27,7 @@ jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS); +void trace_class_resolution(klassOop to_class); /* * Support for Serialization and RMI. Currently used by HotSpot only. diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 1930dc4113c..05a84d581e9 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1211,7 +1211,9 @@ void Arguments::set_ergonomics_flags() { if (UseLargePages && UseCompressedOops) { // Cannot allocate guard pages for implicit checks in indexed addressing // mode, when large pages are specified on windows. - FLAG_SET_DEFAULT(UseImplicitNullCheckForNarrowOop, false); + // This flag could be switched ON if narrow oop base address is set to 0, + // see code in Universe::initialize_heap(). + Universe::set_narrow_oop_use_implicit_null_checks(false); } #endif // _WIN64 } else { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 8ea28902c7e..2d33287fcd4 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -303,11 +303,14 @@ class CommandLineFlags { "Use 32-bit object references in 64-bit VM. " \ "lp64_product means flag is always constant in 32 bit VM") \ \ - lp64_product(bool, CheckCompressedOops, trueInDebug, \ - "generate checks in encoding/decoding code") \ + notproduct(bool, CheckCompressedOops, true, \ + "generate checks in encoding/decoding code in debug VM") \ \ - product(bool, UseImplicitNullCheckForNarrowOop, true, \ - "generate implicit null check in indexed addressing mode.") \ + product_pd(uintx, HeapBaseMinAddress, \ + "OS specific low limit for heap base address") \ + \ + diagnostic(bool, PrintCompressedOopsMode, false, \ + "Print compressed oops base address and encoding mode") \ \ /* UseMembar is theoretically a temp flag used for memory barrier \ * removal testing. It was supposed to be removed before FCS but has \ @@ -2169,6 +2172,9 @@ class CommandLineFlags { diagnostic(bool, PrintIntrinsics, false, \ "prints attempted and successful inlining of intrinsics") \ \ + product(bool, UsePopCountInstruction, false, \ + "Use population count instruction") \ + \ diagnostic(ccstrlist, DisableIntrinsic, "", \ "do not expand intrinsics whose (internal) names appear here") \ \ diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 2a573fb8ca9..e655d3e34b0 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -202,8 +202,10 @@ class os: AllStatic { static char* attempt_reserve_memory_at(size_t bytes, char* addr); static void split_reserved_memory(char *base, size_t size, size_t split, bool realloc); - static bool commit_memory(char* addr, size_t bytes); - static bool commit_memory(char* addr, size_t size, size_t alignment_hint); + static bool commit_memory(char* addr, size_t bytes, + bool executable = false); + static bool commit_memory(char* addr, size_t size, size_t alignment_hint, + bool executable = false); static bool uncommit_memory(char* addr, size_t bytes); static bool release_memory(char* addr, size_t bytes); @@ -243,7 +245,8 @@ class os: AllStatic { static char* non_memory_address_word(); // reserve, commit and pin the entire memory region - static char* reserve_memory_special(size_t size); + static char* reserve_memory_special(size_t size, char* addr = NULL, + bool executable = false); static bool release_memory_special(char* addr, size_t bytes); static bool large_page_init(); static size_t large_page_size(); diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp index 5cd996194d9..e6e4b55a690 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.cpp +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp @@ -28,7 +28,7 @@ // ReservedSpace ReservedSpace::ReservedSpace(size_t size) { - initialize(size, 0, false, NULL, 0); + initialize(size, 0, false, NULL, 0, false); } ReservedSpace::ReservedSpace(size_t size, size_t alignment, @@ -36,7 +36,13 @@ ReservedSpace::ReservedSpace(size_t size, size_t alignment, char* requested_address, const size_t noaccess_prefix) { initialize(size+noaccess_prefix, alignment, large, requested_address, - noaccess_prefix); + noaccess_prefix, false); +} + +ReservedSpace::ReservedSpace(size_t size, size_t alignment, + bool large, + bool executable) { + initialize(size, alignment, large, NULL, 0, executable); } char * @@ -109,6 +115,7 @@ ReservedSpace::ReservedSpace(const size_t prefix_size, const size_t prefix_align, const size_t suffix_size, const size_t suffix_align, + char* requested_address, const size_t noaccess_prefix) { assert(prefix_size != 0, "sanity"); @@ -131,7 +138,8 @@ ReservedSpace::ReservedSpace(const size_t prefix_size, const bool try_reserve_special = UseLargePages && prefix_align == os::large_page_size(); if (!os::can_commit_large_page_memory() && try_reserve_special) { - initialize(size, prefix_align, true, NULL, noaccess_prefix); + initialize(size, prefix_align, true, requested_address, noaccess_prefix, + false); return; } @@ -140,13 +148,20 @@ ReservedSpace::ReservedSpace(const size_t prefix_size, _alignment = 0; _special = false; _noaccess_prefix = 0; + _executable = false; // Assert that if noaccess_prefix is used, it is the same as prefix_align. assert(noaccess_prefix == 0 || noaccess_prefix == prefix_align, "noaccess prefix wrong"); // Optimistically try to reserve the exact size needed. - char* addr = os::reserve_memory(size, NULL, prefix_align); + char* addr; + if (requested_address != 0) { + addr = os::attempt_reserve_memory_at(size, + requested_address-noaccess_prefix); + } else { + addr = os::reserve_memory(size, NULL, prefix_align); + } if (addr == NULL) return; // Check whether the result has the needed alignment (unlikely unless @@ -182,7 +197,8 @@ ReservedSpace::ReservedSpace(const size_t prefix_size, void ReservedSpace::initialize(size_t size, size_t alignment, bool large, char* requested_address, - const size_t noaccess_prefix) { + const size_t noaccess_prefix, + bool executable) { const size_t granularity = os::vm_allocation_granularity(); assert((size & granularity - 1) == 0, "size not aligned to os::vm_allocation_granularity()"); @@ -194,6 +210,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, _base = NULL; _size = 0; _special = false; + _executable = executable; _alignment = 0; _noaccess_prefix = 0; if (size == 0) { @@ -206,12 +223,8 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, char* base = NULL; if (special) { - // It's not hard to implement reserve_memory_special() such that it can - // allocate at fixed address, but there seems no use of this feature - // for now, so it's not implemented. - assert(requested_address == NULL, "not implemented"); - base = os::reserve_memory_special(size); + base = os::reserve_memory_special(size, requested_address, executable); if (base != NULL) { // Check alignment constraints @@ -281,7 +294,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment, - bool special) { + bool special, bool executable) { assert((size % os::vm_allocation_granularity()) == 0, "size not allocation aligned"); _base = base; @@ -289,6 +302,7 @@ ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment, _alignment = alignment; _noaccess_prefix = 0; _special = special; + _executable = executable; } @@ -296,9 +310,10 @@ ReservedSpace ReservedSpace::first_part(size_t partition_size, size_t alignment, bool split, bool realloc) { assert(partition_size <= size(), "partition failed"); if (split) { - os::split_reserved_memory(_base, _size, partition_size, realloc); + os::split_reserved_memory(base(), size(), partition_size, realloc); } - ReservedSpace result(base(), partition_size, alignment, special()); + ReservedSpace result(base(), partition_size, alignment, special(), + executable()); return result; } @@ -307,7 +322,7 @@ ReservedSpace ReservedSpace::last_part(size_t partition_size, size_t alignment) { assert(partition_size <= size(), "partition failed"); ReservedSpace result(base() + partition_size, size() - partition_size, - alignment, special()); + alignment, special(), executable()); return result; } @@ -345,6 +360,7 @@ void ReservedSpace::release() { _size = 0; _noaccess_prefix = 0; _special = false; + _executable = false; } } @@ -372,7 +388,8 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, bool large, char* requested_address) : ReservedSpace(size, alignment, large, requested_address, - UseCompressedOops && UseImplicitNullCheckForNarrowOop ? + (UseCompressedOops && (Universe::narrow_oop_base() != NULL) && + Universe::narrow_oop_use_implicit_null_checks()) ? lcm(os::vm_page_size(), alignment) : 0) { // Only reserved space for the java heap should have a noaccess_prefix // if using compressed oops. @@ -382,13 +399,24 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, ReservedHeapSpace::ReservedHeapSpace(const size_t prefix_size, const size_t prefix_align, const size_t suffix_size, - const size_t suffix_align) : + const size_t suffix_align, + char* requested_address) : ReservedSpace(prefix_size, prefix_align, suffix_size, suffix_align, - UseCompressedOops && UseImplicitNullCheckForNarrowOop ? + requested_address, + (UseCompressedOops && (Universe::narrow_oop_base() != NULL) && + Universe::narrow_oop_use_implicit_null_checks()) ? lcm(os::vm_page_size(), prefix_align) : 0) { protect_noaccess_prefix(prefix_size+suffix_size); } +// Reserve space for code segment. Same as Java heap only we mark this as +// executable. +ReservedCodeSpace::ReservedCodeSpace(size_t r_size, + size_t rs_align, + bool large) : + ReservedSpace(r_size, rs_align, large, /*executable*/ true) { +} + // VirtualSpace VirtualSpace::VirtualSpace() { @@ -406,6 +434,7 @@ VirtualSpace::VirtualSpace() { _middle_alignment = 0; _upper_alignment = 0; _special = false; + _executable = false; } @@ -419,6 +448,7 @@ bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) { _high = low(); _special = rs.special(); + _executable = rs.executable(); // When a VirtualSpace begins life at a large size, make all future expansion // and shrinking occur aligned to a granularity of large pages. This avoids @@ -476,6 +506,7 @@ void VirtualSpace::release() { _middle_alignment = 0; _upper_alignment = 0; _special = false; + _executable = false; } @@ -585,7 +616,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { assert(low_boundary() <= lower_high() && lower_high() + lower_needs <= lower_high_boundary(), "must not expand beyond region"); - if (!os::commit_memory(lower_high(), lower_needs)) { + if (!os::commit_memory(lower_high(), lower_needs, _executable)) { debug_only(warning("os::commit_memory failed")); return false; } else { @@ -596,7 +627,8 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { assert(lower_high_boundary() <= middle_high() && middle_high() + middle_needs <= middle_high_boundary(), "must not expand beyond region"); - if (!os::commit_memory(middle_high(), middle_needs, middle_alignment())) { + if (!os::commit_memory(middle_high(), middle_needs, middle_alignment(), + _executable)) { debug_only(warning("os::commit_memory failed")); return false; } @@ -606,7 +638,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { assert(middle_high_boundary() <= upper_high() && upper_high() + upper_needs <= upper_high_boundary(), "must not expand beyond region"); - if (!os::commit_memory(upper_high(), upper_needs)) { + if (!os::commit_memory(upper_high(), upper_needs, _executable)) { debug_only(warning("os::commit_memory failed")); return false; } else { diff --git a/hotspot/src/share/vm/runtime/virtualspace.hpp b/hotspot/src/share/vm/runtime/virtualspace.hpp index fa65035fde0..f412d11ad55 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.hpp +++ b/hotspot/src/share/vm/runtime/virtualspace.hpp @@ -32,12 +32,15 @@ class ReservedSpace VALUE_OBJ_CLASS_SPEC { size_t _noaccess_prefix; size_t _alignment; bool _special; + bool _executable; // ReservedSpace - ReservedSpace(char* base, size_t size, size_t alignment, bool special); + ReservedSpace(char* base, size_t size, size_t alignment, bool special, + bool executable); void initialize(size_t size, size_t alignment, bool large, char* requested_address, - const size_t noaccess_prefix); + const size_t noaccess_prefix, + bool executable); // Release parts of an already-reserved memory region [addr, addr + len) to // get a new region that has "compound alignment." Return the start of the @@ -73,17 +76,18 @@ class ReservedSpace VALUE_OBJ_CLASS_SPEC { const size_t noaccess_prefix = 0); ReservedSpace(const size_t prefix_size, const size_t prefix_align, const size_t suffix_size, const size_t suffix_align, - const size_t noaccess_prefix); + char* requested_address, + const size_t noaccess_prefix = 0); + ReservedSpace(size_t size, size_t alignment, bool large, bool executable); // Accessors - char* base() const { return _base; } - size_t size() const { return _size; } - size_t alignment() const { return _alignment; } - bool special() const { return _special; } - - size_t noaccess_prefix() const { return _noaccess_prefix; } - - bool is_reserved() const { return _base != NULL; } + char* base() const { return _base; } + size_t size() const { return _size; } + size_t alignment() const { return _alignment; } + bool special() const { return _special; } + bool executable() const { return _executable; } + size_t noaccess_prefix() const { return _noaccess_prefix; } + bool is_reserved() const { return _base != NULL; } void release(); // Splitting @@ -121,7 +125,15 @@ public: ReservedHeapSpace(size_t size, size_t forced_base_alignment, bool large, char* requested_address); ReservedHeapSpace(const size_t prefix_size, const size_t prefix_align, - const size_t suffix_size, const size_t suffix_align); + const size_t suffix_size, const size_t suffix_align, + char* requested_address); +}; + +// Class encapsulating behavior specific memory space for Code +class ReservedCodeSpace : public ReservedSpace { + public: + // Constructor + ReservedCodeSpace(size_t r_size, size_t rs_align, bool large); }; // VirtualSpace is data structure for committing a previously reserved address range in smaller chunks. @@ -141,6 +153,9 @@ class VirtualSpace VALUE_OBJ_CLASS_SPEC { // os::commit_memory() or os::uncommit_memory(). bool _special; + // Need to know if commit should be executable. + bool _executable; + // MPSS Support // Each virtualspace region has a lower, middle, and upper region. // Each region has an end boundary and a high pointer which is the diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index bc8ea34d52e..2de7bbdf56f 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -263,7 +263,9 @@ static inline uint64_t cast_uint64_t(size_t x) static_field(Universe, _bootstrapping, bool) \ static_field(Universe, _fully_initialized, bool) \ static_field(Universe, _verify_count, int) \ - static_field(Universe, _heap_base, address) \ + static_field(Universe, _narrow_oop._base, address) \ + static_field(Universe, _narrow_oop._shift, int) \ + static_field(Universe, _narrow_oop._use_implicit_null_checks, bool) \ \ /**********************************************************************************/ \ /* Generation and Space hierarchies */ \ diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index 653309db0ac..3e7a7e6e0fe 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -163,9 +163,11 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #elif _MSC_VER == 1200 #define HOTSPOT_BUILD_COMPILER "MS VC++ 6.0" #elif _MSC_VER == 1310 - #define HOTSPOT_BUILD_COMPILER "MS VC++ 7.1" + #define HOTSPOT_BUILD_COMPILER "MS VC++ 7.1 (VS2003)" #elif _MSC_VER == 1400 - #define HOTSPOT_BUILD_COMPILER "MS VC++ 8.0" + #define HOTSPOT_BUILD_COMPILER "MS VC++ 8.0 (VS2005)" + #elif _MSC_VER == 1500 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 9.0 (VS2008)" #else #define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER) #endif diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp index 6b4804ec565..2b64dfc4662 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp @@ -153,16 +153,8 @@ const jlong max_jlong = CONST64(0x7fffffffffffffff); //---------------------------------------------------------------------------------------------------- // Miscellaneous -inline int vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) { - // If number of characters written == count, Windows doesn't write a - // terminating NULL, so we do it ourselves. - int ret = _vsnprintf(buf, count, fmt, argptr); - if (count > 0) buf[count-1] = '\0'; - return ret; -} - // Visual Studio 2005 deprecates POSIX names - use ISO C++ names instead -#if _MSC_VER >= 1400 && !defined(_WIN64) +#if _MSC_VER >= 1400 #define open _open #define close _close #define read _read @@ -180,6 +172,17 @@ inline int vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) { #pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union (needed in windows.h) #pragma warning( disable : 4511 ) // copy constructor could not be generated #pragma warning( disable : 4291 ) // no matching operator delete found; memory will not be freed if initialization thows an exception +#if _MSC_VER >= 1400 +#pragma warning( disable : 4996 ) // unsafe string functions. Same as define _CRT_SECURE_NO_WARNINGS/_CRT_SECURE_NO_DEPRICATE +#endif + +inline int vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr) { + // If number of characters written == count, Windows doesn't write a + // terminating NULL, so we do it ourselves. + int ret = _vsnprintf(buf, count, fmt, argptr); + if (count > 0) buf[count-1] = '\0'; + return ret; +} // Portability macros #define PRAGMA_INTERFACE diff --git a/hotspot/test/compiler/6378821/Test6378821.java b/hotspot/test/compiler/6378821/Test6378821.java new file mode 100644 index 00000000000..83c52decb41 --- /dev/null +++ b/hotspot/test/compiler/6378821/Test6378821.java @@ -0,0 +1,75 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6378821 + * @summary where available, bitCount() should use POPC on SPARC processors and AMD+10h + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test6378821.fcomp Test6378821 + */ + +public class Test6378821 { + static final int[] ia = new int[] { 0x12345678 }; + static final long[] la = new long[] { 0x12345678abcdefL }; + + public static void main(String [] args) { + // Resolve the class and the method. + Integer.bitCount(1); + Long.bitCount(1); + + sub(ia[0]); + sub(la[0]); + sub(ia); + sub(la); + } + + static void check(int i, int expected, int result) { + if (result != expected) { + throw new InternalError("Wrong population count for " + i + ": " + result + " != " + expected); + } + } + + static void check(long l, int expected, int result) { + if (result != expected) { + throw new InternalError("Wrong population count for " + l + ": " + result + " != " + expected); + } + } + + static void sub(int i) { check(i, fint(i), fcomp(i) ); } + static void sub(int[] ia) { check(ia[0], fint(ia), fcomp(ia)); } + static void sub(long l) { check(l, fint(l), fcomp(l) ); } + static void sub(long[] la) { check(la[0], fint(la), fcomp(la)); } + + static int fint (int i) { return Integer.bitCount(i); } + static int fcomp(int i) { return Integer.bitCount(i); } + + static int fint (int[] ia) { return Integer.bitCount(ia[0]); } + static int fcomp(int[] ia) { return Integer.bitCount(ia[0]); } + + static int fint (long l) { return Long.bitCount(l); } + static int fcomp(long l) { return Long.bitCount(l); } + + static int fint (long[] la) { return Long.bitCount(la[0]); } + static int fcomp(long[] la) { return Long.bitCount(la[0]); } +} diff --git a/jaxp/.hgtags b/jaxp/.hgtags index b479a50ab7b..8951b3d1ac5 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -26,3 +26,4 @@ d711ad1954b294957737ea386cfd4d3c05028a36 jdk7-b47 5c1f24531903573c1830775432276da567243f9c jdk7-b49 e8514e2be76d90889ebdb90d627aca2db5c150c6 jdk7-b50 ae890d80d5dffcd4dc77a1f17d768e192d1852c7 jdk7-b51 +69ad87dc25cbcaaaded4727199395ad0c78bc427 jdk7-b52 diff --git a/jaxp/make/jprt.config b/jaxp/make/jprt.config deleted file mode 100644 index 90200b1bc41..00000000000 --- a/jaxp/make/jprt.config +++ /dev/null @@ -1,241 +0,0 @@ -#!echo "This is not a shell script" -############################################################################# -# -# Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# -############################################################################# -# -# JPRT shell configuration for building. -# -# Input environment variables: -# ALT_BOOTDIR -# ALT_SLASH_JAVA -# ALT_JDK_IMPORT_PATH -# Windows Only: -# PATH -# PROCESSOR_IDENTIFIER -# ROOTDIR -# -# Output variable settings: -# make Full path to GNU make -# -# Output environment variables: -# PATH -# Windows Only: -# ALT_DEVTOOLS_PATH (To avoid the C:/UTILS default) -# -# After JDK6, most settings will be found via ALT_SLASH_JAVA or -# by way of other system environment variables. If this was JDK5 -# or an older JDK, you might need to export more ALT_* variables. -# -############################################################################# - -############################################################################# -# Error -error() # message -{ - echo "ERROR: $1" - exit 6 -} -# Directory must exist -dirMustExist() # dir name -{ - if [ ! -d "$1" ] ; then - error "Directory for $2 does not exist: $1" - fi -} -# File must exist -fileMustExist() # dir name -{ - if [ ! -f "$1" ] ; then - error "File for $2 does not exist: $1" - fi -} -############################################################################# - -# Should be set by JPRT as the 3 basic inputs -bootdir="${ALT_BOOTDIR}" -slashjava="${ALT_SLASH_JAVA}" -jdk_import="${ALT_JDK_IMPORT_PATH}" - -# Check input -dirMustExist "${bootdir}" ALT_BOOTDIR -dirMustExist "${slashjava}" ALT_SLASH_JAVA -dirMustExist "${jdk_import}" ALT_JDK_IMPORT_PATH - -# Uses 'uname -s', but only expect SunOS or Linux, assume Windows otherwise. -osname=`uname -s` -if [ "${osname}" = SunOS ] ; then - - # SOLARIS: Sparc or X86 - osarch=`uname -p` - if [ "${osarch}" = sparc ] ; then - solaris_arch=sparc - else - solaris_arch=i386 - fi - - # Add basic solaris system paths - path4sdk=/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk=${antbindir}:${path4sdk} - - # Find GNU make - make=/usr/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=/opt/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=${slashjava}/devtools/${solaris_arch}/bin/gnumake - fi - fi - fileMustExist "${make}" make - - # File creation mask - umask 002 - -elif [ "${osname}" = Linux ] ; then - - # LINUX: X86, AMD64 - osarch=`uname -m` - if [ "${osarch}" = i686 ] ; then - linux_arch=i586 - elif [ "${osarch}" = x86_64 ] ; then - linux_arch=amd64 - fi - - # Add basic paths - path4sdk=/usr/bin:/bin:/usr/sbin:/sbin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk=${antbindir}:${path4sdk} - - # Find GNU make - make=/usr/bin/make - fileMustExist "${make}" make - - umask 002 - -else - - # Windows: Differs on CYGWIN vs. MKS. - # Also, blanks in pathnames gives GNU make headaches, so anything placed - # in any ALT_* variable should be the short windows dosname. - - # WINDOWS: Install and use MKS or CYGWIN (should have already been done) - # Assumption here is that you are in a shell window via MKS or cygwin. - # MKS install should have defined the environment variable ROOTDIR. - # We also need to figure out which one we have: X86, AMD64 - if [ "`echo ${PROCESSOR_IDENTIFIER} | fgrep AMD64`" != "" ] ; then - windows_arch=amd64 - else - windows_arch=i586 - fi - - # We need to determine if we are running a CYGWIN shell or an MKS shell - # (if uname isn't available, then it will be unix_toolset=unknown) - unix_toolset=unknown - if [ "`uname -a | fgrep Cygwin`" = "" -a -d "${ROOTDIR}" ] ; then - # We kind of assume ROOTDIR is where MKS is and it's ok - unix_toolset=MKS - mkshome=`dosname -s "${ROOTDIR}"` - # Utility to convert to short pathnames without spaces - dosname="${mkshome}/mksnt/dosname -s" - # Most unix utilities are in the mksnt directory of ROOTDIR - unixcommand_path="${mkshome}/mksnt" - path4sdk="${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - devtools_path="${slashjava}/devtools/win32/bin" - path4sdk="${devtools_path};${path4sdk}" - # Normally this need not be set, but on Windows it's default is C:/UTILS - ALT_DEVTOOLS_PATH="${devtools_path}" - export ALT_DEVTOOLS_PATH - dirMustExist "${devtools_path}" ALT_DEVTOOLS_PATH - # Find GNU make - make="${devtools_path}/gnumake.exe" - fileMustExist "${make}" make - elif [ "`uname -a | fgrep Cygwin`" != "" -a -f /bin/cygpath ] ; then - # For CYGWIN, uname will have "Cygwin" in it, and /bin/cygpath should exist - unix_toolset=CYGWIN - # Utility to convert to short pathnames without spaces - dosname="/usr/bin/cygpath -a -m -s" - # Most unix utilities are in the /usr/bin - unixcommand_path="/usr/bin" - path4sdk="${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - # Find GNU make - make="${unixcommand_path}/make.exe" - fileMustExist "${make}" make - else - echo "WARNING: Cannot figure out if this is MKS or CYGWIN" - fi - - # WINDOWS: Get the previous JDK to be used to bootstrap the build - path4sdk="${bootdir}/bin;${path4sdk}" - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk="${antbindir};${path4sdk}" - - # Turn all \\ into /, remove duplicates and trailing / - slash_path="`echo ${path4sdk} | sed -e 's@\\\\@/@g' -e 's@//@/@g' -e 's@/$@@' -e 's@/;@;@g'`" - - # For windows, it's hard to know where the system is, so we just add this - # to PATH. - path4sdk="${slash_path};${PATH}" - - # Convert path4sdk to cygwin style - if [ "${unix_toolset}" = CYGWIN ] ; then - path4sdk="`/usr/bin/cygpath -p ${path4sdk}`" - fi - -fi - -# Export PATH setting -PATH="${path4sdk}" -export PATH - -# Things we need to unset -unset LD_LIBRARY_PATH -unset LD_LIBRARY_PATH_32 -unset LD_LIBRARY_PATH_64 -unset JAVA_HOME - diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 2869a6be543..62bf7fdbd4d 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -26,3 +26,4 @@ af4a3eeb7812a5d09a241c50b51b3c648a9d45c1 jdk7-b46 18ca864890f3d4ed942ecbffb78c936a57759921 jdk7-b49 5be52db581f1ea91ab6e0eb34ba7f439125bfb16 jdk7-b50 41a66a42791ba90bff489af72cbfea71be9b40a5 jdk7-b51 +e646890d18b770f625f14ed4ad5c50554d8d3d8b jdk7-b52 diff --git a/jaxws/make/jprt.config b/jaxws/make/jprt.config deleted file mode 100644 index 90200b1bc41..00000000000 --- a/jaxws/make/jprt.config +++ /dev/null @@ -1,241 +0,0 @@ -#!echo "This is not a shell script" -############################################################################# -# -# Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# -############################################################################# -# -# JPRT shell configuration for building. -# -# Input environment variables: -# ALT_BOOTDIR -# ALT_SLASH_JAVA -# ALT_JDK_IMPORT_PATH -# Windows Only: -# PATH -# PROCESSOR_IDENTIFIER -# ROOTDIR -# -# Output variable settings: -# make Full path to GNU make -# -# Output environment variables: -# PATH -# Windows Only: -# ALT_DEVTOOLS_PATH (To avoid the C:/UTILS default) -# -# After JDK6, most settings will be found via ALT_SLASH_JAVA or -# by way of other system environment variables. If this was JDK5 -# or an older JDK, you might need to export more ALT_* variables. -# -############################################################################# - -############################################################################# -# Error -error() # message -{ - echo "ERROR: $1" - exit 6 -} -# Directory must exist -dirMustExist() # dir name -{ - if [ ! -d "$1" ] ; then - error "Directory for $2 does not exist: $1" - fi -} -# File must exist -fileMustExist() # dir name -{ - if [ ! -f "$1" ] ; then - error "File for $2 does not exist: $1" - fi -} -############################################################################# - -# Should be set by JPRT as the 3 basic inputs -bootdir="${ALT_BOOTDIR}" -slashjava="${ALT_SLASH_JAVA}" -jdk_import="${ALT_JDK_IMPORT_PATH}" - -# Check input -dirMustExist "${bootdir}" ALT_BOOTDIR -dirMustExist "${slashjava}" ALT_SLASH_JAVA -dirMustExist "${jdk_import}" ALT_JDK_IMPORT_PATH - -# Uses 'uname -s', but only expect SunOS or Linux, assume Windows otherwise. -osname=`uname -s` -if [ "${osname}" = SunOS ] ; then - - # SOLARIS: Sparc or X86 - osarch=`uname -p` - if [ "${osarch}" = sparc ] ; then - solaris_arch=sparc - else - solaris_arch=i386 - fi - - # Add basic solaris system paths - path4sdk=/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk=${antbindir}:${path4sdk} - - # Find GNU make - make=/usr/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=/opt/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=${slashjava}/devtools/${solaris_arch}/bin/gnumake - fi - fi - fileMustExist "${make}" make - - # File creation mask - umask 002 - -elif [ "${osname}" = Linux ] ; then - - # LINUX: X86, AMD64 - osarch=`uname -m` - if [ "${osarch}" = i686 ] ; then - linux_arch=i586 - elif [ "${osarch}" = x86_64 ] ; then - linux_arch=amd64 - fi - - # Add basic paths - path4sdk=/usr/bin:/bin:/usr/sbin:/sbin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk=${antbindir}:${path4sdk} - - # Find GNU make - make=/usr/bin/make - fileMustExist "${make}" make - - umask 002 - -else - - # Windows: Differs on CYGWIN vs. MKS. - # Also, blanks in pathnames gives GNU make headaches, so anything placed - # in any ALT_* variable should be the short windows dosname. - - # WINDOWS: Install and use MKS or CYGWIN (should have already been done) - # Assumption here is that you are in a shell window via MKS or cygwin. - # MKS install should have defined the environment variable ROOTDIR. - # We also need to figure out which one we have: X86, AMD64 - if [ "`echo ${PROCESSOR_IDENTIFIER} | fgrep AMD64`" != "" ] ; then - windows_arch=amd64 - else - windows_arch=i586 - fi - - # We need to determine if we are running a CYGWIN shell or an MKS shell - # (if uname isn't available, then it will be unix_toolset=unknown) - unix_toolset=unknown - if [ "`uname -a | fgrep Cygwin`" = "" -a -d "${ROOTDIR}" ] ; then - # We kind of assume ROOTDIR is where MKS is and it's ok - unix_toolset=MKS - mkshome=`dosname -s "${ROOTDIR}"` - # Utility to convert to short pathnames without spaces - dosname="${mkshome}/mksnt/dosname -s" - # Most unix utilities are in the mksnt directory of ROOTDIR - unixcommand_path="${mkshome}/mksnt" - path4sdk="${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - devtools_path="${slashjava}/devtools/win32/bin" - path4sdk="${devtools_path};${path4sdk}" - # Normally this need not be set, but on Windows it's default is C:/UTILS - ALT_DEVTOOLS_PATH="${devtools_path}" - export ALT_DEVTOOLS_PATH - dirMustExist "${devtools_path}" ALT_DEVTOOLS_PATH - # Find GNU make - make="${devtools_path}/gnumake.exe" - fileMustExist "${make}" make - elif [ "`uname -a | fgrep Cygwin`" != "" -a -f /bin/cygpath ] ; then - # For CYGWIN, uname will have "Cygwin" in it, and /bin/cygpath should exist - unix_toolset=CYGWIN - # Utility to convert to short pathnames without spaces - dosname="/usr/bin/cygpath -a -m -s" - # Most unix utilities are in the /usr/bin - unixcommand_path="/usr/bin" - path4sdk="${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - # Find GNU make - make="${unixcommand_path}/make.exe" - fileMustExist "${make}" make - else - echo "WARNING: Cannot figure out if this is MKS or CYGWIN" - fi - - # WINDOWS: Get the previous JDK to be used to bootstrap the build - path4sdk="${bootdir}/bin;${path4sdk}" - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk="${antbindir};${path4sdk}" - - # Turn all \\ into /, remove duplicates and trailing / - slash_path="`echo ${path4sdk} | sed -e 's@\\\\@/@g' -e 's@//@/@g' -e 's@/$@@' -e 's@/;@;@g'`" - - # For windows, it's hard to know where the system is, so we just add this - # to PATH. - path4sdk="${slash_path};${PATH}" - - # Convert path4sdk to cygwin style - if [ "${unix_toolset}" = CYGWIN ] ; then - path4sdk="`/usr/bin/cygpath -p ${path4sdk}`" - fi - -fi - -# Export PATH setting -PATH="${path4sdk}" -export PATH - -# Things we need to unset -unset LD_LIBRARY_PATH -unset LD_LIBRARY_PATH_32 -unset LD_LIBRARY_PATH_64 -unset JAVA_HOME - diff --git a/jdk/.hgtags b/jdk/.hgtags index 4790ae52876..a611fd31d77 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -26,3 +26,5 @@ b4ac413b1f129eeef0acab3f31081c1b7dfe3b27 jdk7-b47 8311105ea7a3db7bcbcb2b696459127c7f2297a4 jdk7-b49 58ba2cd5a25053684ec53205d95edeeaa0006f13 jdk7-b50 fea0898259ae41c73620b1815aa48f036216155c jdk7-b51 +bcbeadb4a5d759b29e876ee2c83401e91ff22f60 jdk7-b52 +a2033addca678f9e4c0d92ffa1e389171cc9321d jdk7-b53 diff --git a/jdk/make/common/Defs.gmk b/jdk/make/common/Defs.gmk index 33eedad16a4..d959123fdae 100644 --- a/jdk/make/common/Defs.gmk +++ b/jdk/make/common/Defs.gmk @@ -145,6 +145,11 @@ endif # 2. ALT_BINARY_PLUGS_PATH overrides all locations of classes and libraries # 3. ALT_BUILD_BINARY_PLUGS_PATH is used to find a ALT_BINARY_PLUGS_PATH # 4. ALT_CLOSED_JDK_IMPORT_PATH is used to locate classes and libraries +# Note: If any of the ALT_ variables are modified here, it is assumed +# that the build should be done with IMPORT_BINARY_PLUGS=true as +# well. Otherwise the default will be IMPORT_BINARY_PLUGS=false. +# Lastly, setting IMPORT_BINARY_PLUGS=false on the command line +# will override this logic, and plugs will not be imported. # # Always needed, defines the name of the imported/exported jarfile @@ -155,9 +160,11 @@ ifdef OPENJDK CLOSED_JDK_IMPORT_PATH = $(ALT_CLOSED_JDK_IMPORT_PATH) BINARY_PLUGS_PATH = $(CLOSED_JDK_IMPORT_PATH) BINARY_PLUGS_JARFILE = $(CLOSED_JDK_IMPORT_PATH)/jre/lib/rt.jar + IMPORT_BINARY_PLUGS=true endif ifdef ALT_BUILD_BINARY_PLUGS_PATH BUILD_BINARY_PLUGS_PATH = $(ALT_BUILD_BINARY_PLUGS_PATH) + IMPORT_BINARY_PLUGS=true else BUILD_BINARY_PLUGS_PATH = $(SLASH_JAVA)/re/jdk/$(JDK_VERSION)/promoted/latest/openjdk/binaryplugs endif @@ -166,9 +173,11 @@ ifdef OPENJDK ifdef ALT_BINARY_PLUGS_PATH BINARY_PLUGS_PATH = $(ALT_BINARY_PLUGS_PATH) BINARY_PLUGS_JARFILE = $(BINARY_PLUGS_PATH)/jre/lib/$(BINARY_PLUGS_JARNAME) + IMPORT_BINARY_PLUGS=true endif ifdef ALT_BINARY_PLUGS_JARFILE BINARY_PLUGS_JARFILE = $(ALT_BINARY_PLUGS_JARFILE) + IMPORT_BINARY_PLUGS=true endif endif # OPENJDK diff --git a/jdk/make/common/shared/Platform.gmk b/jdk/make/common/shared/Platform.gmk index d343cdea1c3..e07de2499fb 100644 --- a/jdk/make/common/shared/Platform.gmk +++ b/jdk/make/common/shared/Platform.gmk @@ -229,11 +229,19 @@ ifeq ($(PLATFORM), windows) TEMP_DISK=C:/temp # GNU Make or MKS overrides $(PROCESSOR_ARCHITECTURE) to always # return "x86". Use the first word of $(PROCESSOR_IDENTIFIER) instead. + PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER)) + PROC_ARCH:=$(subst x86,X86,$(PROC_ARCH)) + PROC_ARCH:=$(subst Intel64,X64,$(PROC_ARCH)) + PROC_ARCH:=$(subst em64t,X64,$(PROC_ARCH)) + PROC_ARCH:=$(subst EM64T,X64,$(PROC_ARCH)) + PROC_ARCH:=$(subst amd64,X64,$(PROC_ARCH)) + PROC_ARCH:=$(subst AMD64,X64,$(PROC_ARCH)) + PROC_ARCH:=$(subst ia64,IA64,$(PROC_ARCH)) ifndef ARCH_DATA_MODEL - ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64) + ifeq ($(PROC_ARCH),IA64) ARCH_DATA_MODEL=64 else - ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),AMD64) + ifeq ($(PROC_ARCH),X64) ARCH_DATA_MODEL=64 else ARCH_DATA_MODEL=32 @@ -245,10 +253,12 @@ ifeq ($(PLATFORM), windows) # If the user wants to perform a cross compile build then they must # - set ARCH_DATA_MODEL=64 and either # + set ARCH to ia64 or amd64, or - ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)), AMD64) + ifeq ($(PROC_ARCH),X64) ARCH=amd64 else - ARCH=ia64 + ifeq ($(PROC_ARCH),IA64) + ARCH=ia64 + endif endif LIBARCH=$(ARCH) # Value of Java os.arch property diff --git a/jdk/make/common/shared/Sanity-Settings.gmk b/jdk/make/common/shared/Sanity-Settings.gmk index 987ba93489a..b64e3b52a13 100644 --- a/jdk/make/common/shared/Sanity-Settings.gmk +++ b/jdk/make/common/shared/Sanity-Settings.gmk @@ -245,6 +245,7 @@ ifdef OPENJDK ALL_SETTINGS+=$(call addAltSetting,FREETYPE_HEADERS_PATH) ALL_SETTINGS+=$(call addAltSetting,FREETYPE_LIB_PATH) ALL_SETTINGS+=$(call addHeading,OPENJDK Import Binary Plug Settings) + ALL_SETTINGS+=$(call addOptionalSetting,IMPORT_BINARY_PLUGS) ALL_SETTINGS+=$(call addAltSetting,BINARY_PLUGS_JARFILE) ALL_SETTINGS+=$(call addAltSetting,BINARY_PLUGS_PATH) ALL_SETTINGS+=$(call addAltSetting,BUILD_BINARY_PLUGS_PATH) diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index 23e3818353b..180e52196a9 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -502,13 +502,15 @@ endif ###################################################### ifdef OPENJDK sane-binary-plugs: + ifeq ($(IMPORT_BINARY_PLUGS),true) @if [ ! -d "$(BINARY_PLUGS_PATH)" ]; then \ - $(ECHO) "ERROR: Can't locate pre-built libraries. \n" \ + $(ECHO) "WARNING: Can't locate pre-built libraries. \n" \ " Please check your access to \n" \ " $(BINARY_PLUGS_PATH) \n" \ " and/or check your value of ALT_BINARY_PLUGS_PATH. \n" \ - "" >> $(ERROR_FILE); \ + "" >> $(WARNING_FILE); \ fi + endif endif ###################################################### diff --git a/jdk/make/java/redist/Makefile b/jdk/make/java/redist/Makefile index 159c247b3f3..9ab884dd247 100644 --- a/jdk/make/java/redist/Makefile +++ b/jdk/make/java/redist/Makefile @@ -251,9 +251,11 @@ endif # INCLUDE_SA # ifdef OPENJDK -include $(BUILDDIR)/common/internal/BinaryPlugs.gmk + ifeq ($(IMPORT_BINARY_PLUGS),true) + include $(BUILDDIR)/common/internal/BinaryPlugs.gmk -build: import-binary-plugs + build: import-binary-plugs + endif else # !OPENJDK diff --git a/jdk/make/jdk_generic_profile.sh b/jdk/make/jdk_generic_profile.sh index 32dd86197ef..125198301ca 100644 --- a/jdk/make/jdk_generic_profile.sh +++ b/jdk/make/jdk_generic_profile.sh @@ -174,7 +174,8 @@ else # Check CYGWIN (should have already been done) # Assumption here is that you are in a shell window via cygwin. - if [ "$(echo ${PROCESSOR_IDENTIFIER} | fgrep AMD64)" != "" ] ; then + proc_arch=`echo "$(PROCESSOR_IDENTIFIER)" | expand | cut -d' ' -f1 | sed -e 's@x86@X86@g' -e 's@Intel64@X64@g' -e 's@em64t@X64@g' -e 's@EM64T@X64@g' -e 's@amd64@X64@g' -e 's@AMD64@X64@g' -e 's@ia64@IA64@g'` + if [ "${proc_arch}" = "X64" ] ; then windows_arch=amd64 else windows_arch=i586 diff --git a/jdk/make/jprt.config b/jdk/make/jprt.config deleted file mode 100644 index d720475cecd..00000000000 --- a/jdk/make/jprt.config +++ /dev/null @@ -1,363 +0,0 @@ -#!echo "This is not a shell script" -############################################################################# -# -# Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# -############################################################################# -# -# JPRT shell configuration for building. -# -# Input environment variables: -# ALT_BOOTDIR -# ALT_SLASH_JAVA -# ALT_JDK_IMPORT_PATH -# OPENJDK -# Windows Only: -# PATH -# VS71COMNTOOLS -# PROCESSOR_IDENTIFIER -# ROOTDIR -# -# Output variable settings: -# make Full path to GNU make -# compiler_path Path to compiler bin directory -# compiler_name Unique name of this compiler -# -# Output environment variables: -# PATH -# ALT_COMPILER_PATH -# OPENJDK only: -# ALT_CLOSED_JDK_IMPORT_PATH -# ALT_JDK_DEVTOOLS_DIR -# Windows Only: -# ALT_MSDEVTOOLS_PATH -# ALT_DEVTOOLS_PATH (To avoid the C:/UTILS default) -# LIB -# INCLUDE -# -# After JDK6, most settings will be found via ALT_SLASH_JAVA or -# by way of other system environment variables. If this was JDK5 -# or an older JDK, you might need to export more ALT_* variables. -# -# On Windows AMD64, if MSSDK is not set, assumes Platform SDK is installed at: -# C:/Program Files/Microsoft Platform SDK -# -############################################################################# - -############################################################################# -# Error -error() # message -{ - echo "ERROR: $1" - exit 6 -} -# Directory must exist -dirMustExist() # dir name -{ - if [ ! -d "$1" ] ; then - error "Directory for $2 does not exist: $1" - fi -} -# File must exist -fileMustExist() # dir name -{ - if [ ! -f "$1" ] ; then - error "File for $2 does not exist: $1" - fi -} -############################################################################# - -# Should be set by JPRT as the 3 basic inputs -bootdir="${ALT_BOOTDIR}" -slashjava="${ALT_SLASH_JAVA}" -jdk_import="${ALT_JDK_IMPORT_PATH}" - -# The /java/devtools items -jdk_devtools="${slashjava}/devtools" -share="${jdk_devtools}/share" - -# Needed for langtools, maybe other parts of the build -ANT_HOME="${share}/ant/latest" -export ANT_HOME - -# The 3 bin directories in common to all platforms -sharebin="${share}/bin" -antbin="${ANT_HOME}/bin" - -# Check input -dirMustExist "${bootdir}" ALT_BOOTDIR -dirMustExist "${slashjava}" ALT_SLASH_JAVA -dirMustExist "${jdk_import}" ALT_JDK_IMPORT_PATH -dirMustExist "${ANT_HOME}" ANT_HOME - -# Use the JDK import for now (FIXME: use the binary plugs?) -if [ "${OPENJDK}" = true ] ; then - ALT_CLOSED_JDK_IMPORT_PATH="${jdk_import}" - export ALT_CLOSED_JDK_IMPORT_PATH -fi - -# Uses 'uname -s', but only expect SunOS or Linux, assume Windows otherwise. -osname=`uname -s` -if [ "${osname}" = SunOS ] ; then - - # SOLARIS: Sparc or X86 - osarch=`uname -p` - if [ "${osarch}" = sparc ] ; then - solaris_arch=sparc - else - solaris_arch=i386 - fi - - # Get the compilers into path (make sure it matches ALT setting) - if [ "${JPRT_SOLARIS_COMPILER_NAME}" != "" ] ; then - compiler_name=${JPRT_SOLARIS_COMPILER_NAME} - else - compiler_name=SS12 - fi - compiler_path=${jdk_devtools}/${solaris_arch}/SUNWspro/${compiler_name}/bin - ALT_COMPILER_PATH="${compiler_path}" - export ALT_COMPILER_PATH - dirMustExist "${compiler_path}" ALT_COMPILER_PATH - path4sdk=${compiler_path}:${sharebin}:${antbin} - - # Add basic solaris system paths - path4sdk=${path4sdk}:/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Find GNU make - make=/usr/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=/opt/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=${jdk_devtools}/${solaris_arch}/bin/gnumake - fi - fi - fileMustExist "${make}" make - - # File creation mask - umask 002 - -elif [ "${osname}" = Linux ] ; then - - # LINUX: X86, AMD64 - osarch=`uname -m` - if [ "${osarch}" = i686 ] ; then - linux_arch=i586 - elif [ "${osarch}" = x86_64 ] ; then - linux_arch=amd64 - fi - - # Get the compilers into path (make sure it matches ALT setting) - compiler_path=/usr/bin - compiler_name=usr_bin - ALT_COMPILER_PATH="${compiler_path}" - export ALT_COMPILER_PATH - dirMustExist "${compiler_path}" ALT_COMPILER_PATH - path4sdk=${compiler_path}:${sharebin}:${antbin} - - # Add basic paths - path4sdk=${path4sdk}:/usr/bin:/bin:/usr/sbin:/sbin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Find GNU make - make=/usr/bin/make - fileMustExist "${make}" make - - umask 002 - - # Linux platform may be old, use motif files from the devtools area - if [ "${OPENJDK}" = true ] ; then - ALT_JDK_DEVTOOLS_DIR="${jdk_devtools}" - export ALT_JDK_DEVTOOLS_DIR - fi - - -else - - # Windows: Differs on CYGWIN vs. MKS, and the compiler available. - # Also, blanks in pathnames gives GNU make headaches, so anything placed - # in any ALT_* variable should be the short windows dosname. - - # WINDOWS: Install and use MKS or CYGWIN (should have already been done) - # Assumption here is that you are in a shell window via MKS or cygwin. - # MKS install should have defined the environment variable ROOTDIR. - # We also need to figure out which one we have: X86, AMD64 - if [ "`echo ${PROCESSOR_IDENTIFIER} | fgrep AMD64`" != "" ] ; then - windows_arch=amd64 - else - windows_arch=i586 - fi - - # We need to determine if we are running a CYGWIN shell or an MKS shell - # (if uname isn't available, then it will be unix_toolset=unknown) - unix_toolset=unknown - if [ "`uname -a | fgrep Cygwin`" = "" -a -d "${ROOTDIR}" ] ; then - # We kind of assume ROOTDIR is where MKS is and it's ok - unix_toolset=MKS - mkshome=`dosname -s "${ROOTDIR}"` - # Utility to convert to short pathnames without spaces - dosname="${mkshome}/mksnt/dosname -s" - # Most unix utilities are in the mksnt directory of ROOTDIR - unixcommand_path="${mkshome}/mksnt" - path4sdk="${sharebin};${antbin};${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - devtools_path="${jdk_devtools}/win32/bin" - path4sdk="${devtools_path};${path4sdk}" - # Normally this need not be set, but on Windows it's default is C:/UTILS - ALT_DEVTOOLS_PATH="${devtools_path}" - export ALT_DEVTOOLS_PATH - dirMustExist "${devtools_path}" ALT_DEVTOOLS_PATH - # Find GNU make - make="${devtools_path}/gnumake.exe" - fileMustExist "${make}" make - elif [ "`uname -a | fgrep Cygwin`" != "" -a -f /bin/cygpath ] ; then - # For CYGWIN, uname will have "Cygwin" in it, and /bin/cygpath should exist - unix_toolset=CYGWIN - # Utility to convert to short pathnames without spaces - dosname="/usr/bin/cygpath -a -m -s" - # Most unix utilities are in the /usr/bin - unixcommand_path="/usr/bin" - path4sdk="${sharebin};${antbin};${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - # Find GNU make - make="${unixcommand_path}/make.exe" - fileMustExist "${make}" make - else - echo "WARNING: Cannot figure out if this is MKS or CYGWIN" - fi - - # WINDOWS: Compiler setup (nasty part) - # NOTE: You can use vcvars32.bat to set PATH, LIB, and INCLUDE. - # NOTE: CYGWIN has a link.exe too, make sure the compilers are first - if [ "${windows_arch}" = i586 ] ; then - # 32bit Windows compiler settings - # VisualStudio .NET 2003 VC++ 7.1 (VS71COMNTOOLS should be defined) - vs_root=`${dosname} "${VS71COMNTOOLS}/../.."` - # Fill in PATH, LIB, and INCLUDE (unset all others to make sure) - msdev_root="${vs_root}/Common7/Tools" - msdevtools_path="${msdev_root}/bin" - vc7_root="${vs_root}/Vc7" - compiler_path="${vc7_root}/bin" - compiler_name=VS2003 - platform_sdk="${vc7_root}/PlatformSDK" - # LIB and INCLUDE must use ; as a separator - include4sdk="${vc7_root}/atlmfc/include" - include4sdk="${include4sdk};${vc7_root}/include" - include4sdk="${include4sdk};${platform_sdk}/include/prerelease" - include4sdk="${include4sdk};${platform_sdk}/include" - include4sdk="${include4sdk};${vs_root}/SDK/v1.1/include" - lib4sdk="${vc7_root}/atlmfc/lib" - lib4sdk="${lib4sdk};${vc7_root}/lib" - lib4sdk="${lib4sdk};${platform_sdk}/lib/prerelease" - lib4sdk="${lib4sdk};${platform_sdk}/lib" - lib4sdk="${lib4sdk};${vs_root}/SDK/v1.1/lib" - # Search path and DLL locating path - # WARNING: CYGWIN has a link.exe too, make sure compilers are first - path4sdk="${vs_root}/Common7/Tools/bin;${path4sdk}" - path4sdk="${vs_root}/SDK/v1.1/bin;${path4sdk}" - path4sdk="${vs_root}/Common7/Tools;${path4sdk}" - path4sdk="${vs_root}/Common7/Tools/bin/prerelease;${path4sdk}" - path4sdk="${vs_root}/Common7/IDE;${path4sdk}" - path4sdk="${compiler_path};${path4sdk}" - elif [ "${windows_arch}" = amd64 ] ; then - # AMD64 64bit Windows compiler settings - if [ "${MSSDK}" != "" ] ; then - platform_sdk="${MSSDK}" - else - platform_sdk=`${dosname} "C:/Program Files/Microsoft Platform SDK/"` - fi - compiler_path="${platform_sdk}/Bin/win64/x86/AMD64" - compiler_name=VS2005_PSDK - msdevtools_path="${platform_sdk}/Bin" - # LIB and INCLUDE must use ; as a separator - include4sdk="${platform_sdk}/Include" - include4sdk="${include4sdk};${platform_sdk}/Include/crt/sys" - include4sdk="${include4sdk};${platform_sdk}/Include/mfc" - include4sdk="${include4sdk};${platform_sdk}/Include/atl" - include4sdk="${include4sdk};${platform_sdk}/Include/crt" - lib4sdk="${platform_sdk}/Lib/AMD64" - lib4sdk="${lib4sdk};${platform_sdk}/Lib/AMD64/atlmfc" - # Search path and DLL locating path - # WARNING: CYGWIN has a link.exe too, make sure compilers are first - path4sdk="${platform_sdk}/bin;${path4sdk}" - path4sdk="${compiler_path};${path4sdk}" - fi - # Export LIB and INCLUDE - unset lib - unset Lib - LIB="${lib4sdk}" - export LIB - unset include - unset Include - INCLUDE="${include4sdk}" - export INCLUDE - # Set the ALT variable - ALT_COMPILER_PATH=`${dosname} "${compiler_path}"` - export ALT_COMPILER_PATH - dirMustExist "${compiler_path}" ALT_COMPILER_PATH - ALT_MSDEVTOOLS_PATH=`${dosname} "${msdevtools_path}"` - export ALT_MSDEVTOOLS_PATH - dirMustExist "${msdevtools_path}" ALT_MSDEVTOOLS_PATH - - # WINDOWS: Get the previous JDK to be used to bootstrap the build - path4sdk="${bootdir}/bin;${path4sdk}" - - # Turn all \\ into /, remove duplicates and trailing / - slash_path="`echo ${path4sdk} | sed -e 's@\\\\@/@g' -e 's@//@/@g' -e 's@/$@@' -e 's@/;@;@g'`" - - # For windows, it's hard to know where the system is, so we just add this - # to PATH. - path4sdk="${slash_path};${PATH}" - - # Convert path4sdk to cygwin style - if [ "${unix_toolset}" = CYGWIN ] ; then - path4sdk="`/usr/bin/cygpath -p ${path4sdk}`" - fi - - # Set special windows ALT variables - ALT_ISHIELDDIR="C:/ishield802" - export ALT_ISHIELDDIR - - # Sponsors binaries - ALT_SPONSOR1DIR=C:/sponsor_binaries - export ALT_SPONSOR1DIR - ALT_SPONSOR2DIR=C:/sponsor_binaries - export ALT_SPONSOR2DIR - -fi - -# Export PATH setting -PATH="${path4sdk}" -export PATH - -# Things we need to unset -unset LD_LIBRARY_PATH -unset LD_LIBRARY_PATH_32 -unset LD_LIBRARY_PATH_64 -unset JAVA_HOME - diff --git a/jdk/src/share/classes/java/util/zip/ZipConstants64.java b/jdk/src/share/classes/java/util/zip/ZipConstants64.java new file mode 100644 index 00000000000..1bf3b1841b4 --- /dev/null +++ b/jdk/src/share/classes/java/util/zip/ZipConstants64.java @@ -0,0 +1,77 @@ +/* + * Copyright 1995-1996 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.util.zip; + +/* + * This class defines the constants that are used by the classes + * which manipulate Zip64 files. + */ + +class ZipConstants64 { + + /* + * ZIP64 constants + */ + static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006" + static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007" + static final int ZIP64_ENDHDR = 56; // ZIP64 end header size + static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size + static final int ZIP64_EXTHDR = 24; // EXT header size + static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID + + static final int ZIP64_MAGICCOUNT = 0xFFFF; + static final long ZIP64_MAGICVAL = 0xFFFFFFFFL; + + /* + * Zip64 End of central directory (END) header field offsets + */ + static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir + static final int ZIP64_ENDVEM = 12; // version made by + static final int ZIP64_ENDVER = 14; // version needed to extract + static final int ZIP64_ENDNMD = 16; // number of this disk + static final int ZIP64_ENDDSK = 20; // disk number of start + static final int ZIP64_ENDTOD = 24; // total number of entries on this disk + static final int ZIP64_ENDTOT = 32; // total number of entries + static final int ZIP64_ENDSIZ = 40; // central directory size in bytes + static final int ZIP64_ENDOFF = 48; // offset of first CEN header + static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector + + /* + * Zip64 End of central directory locator field offsets + */ + static final int ZIP64_LOCDSK = 4; // disk number start + static final int ZIP64_LOCOFF = 8; // offset of zip64 end + static final int ZIP64_LOCTOT = 16; // total number of disks + + /* + * Zip64 Extra local (EXT) header field offsets + */ + static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value + static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte + static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte + + private ZipConstants64() {} +} diff --git a/jdk/src/share/classes/java/util/zip/ZipEntry.java b/jdk/src/share/classes/java/util/zip/ZipEntry.java index bcc27e63a0f..6c16a9adb15 100644 --- a/jdk/src/share/classes/java/util/zip/ZipEntry.java +++ b/jdk/src/share/classes/java/util/zip/ZipEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,11 +144,13 @@ class ZipEntry implements ZipConstants, Cloneable { * Sets the uncompressed size of the entry data. * @param size the uncompressed size in bytes * @exception IllegalArgumentException if the specified size is less - * than 0 or greater than 0xFFFFFFFF bytes + * than 0, is greater than 0xFFFFFFFF when + * ZIP64 format is not supported, + * or is less than 0 when ZIP64 is supported * @see #getSize() */ public void setSize(long size) { - if (size < 0 || size > 0xFFFFFFFFL) { + if (size < 0) { throw new IllegalArgumentException("invalid entry size"); } this.size = size; diff --git a/jdk/src/share/classes/java/util/zip/ZipInputStream.java b/jdk/src/share/classes/java/util/zip/ZipInputStream.java index e8f0ebdc5d9..1b9b93415cb 100644 --- a/jdk/src/share/classes/java/util/zip/ZipInputStream.java +++ b/jdk/src/share/classes/java/util/zip/ZipInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.io.InputStream; import java.io.IOException; import java.io.EOFException; import java.io.PushbackInputStream; +import static java.util.zip.ZipConstants64.*; /** * This class implements an input stream filter for reading files in the @@ -285,6 +286,29 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants { byte[] bb = new byte[len]; readFully(bb, 0, len); e.setExtra(bb); + // extra fields are in "HeaderID(2)DataSize(2)Data... format + if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) { + int off = 0; + while (off + 4 < len) { + int sz = get16(bb, off + 2); + if (get16(bb, off) == ZIP64_EXTID) { + off += 4; + // LOC extra zip64 entry MUST include BOTH original and + // compressed file size fields + if (sz < 16 || (off + sz) > len ) { + // Invalid zip64 extra fields, simply skip. Even it's + // rare, it's possible the entry size happens to be + // the magic value and it "accidnetly" has some bytes + // in extra match the id. + return e; + } + e.size = get64(bb, off); + e.csize = get64(bb, off + 8); + break; + } + off += (sz + 4); + } + } } return e; } @@ -375,18 +399,36 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants { } if ((flag & 8) == 8) { /* "Data Descriptor" present */ - readFully(tmpbuf, 0, EXTHDR); - long sig = get32(tmpbuf, 0); - if (sig != EXTSIG) { // no EXTSIG present - e.crc = sig; - e.csize = get32(tmpbuf, EXTSIZ - EXTCRC); - e.size = get32(tmpbuf, EXTLEN - EXTCRC); - ((PushbackInputStream)in).unread( - tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC); + if (inf.getBytesWritten() > ZIP64_MAGICVAL || + inf.getBytesRead() > ZIP64_MAGICVAL) { + // ZIP64 format + readFully(tmpbuf, 0, ZIP64_EXTHDR); + long sig = get32(tmpbuf, 0); + if (sig != EXTSIG) { // no EXTSIG present + e.crc = sig; + e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC); + e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC); + ((PushbackInputStream)in).unread( + tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC); + } else { + e.crc = get32(tmpbuf, ZIP64_EXTCRC); + e.csize = get64(tmpbuf, ZIP64_EXTSIZ); + e.size = get64(tmpbuf, ZIP64_EXTLEN); + } } else { - e.crc = get32(tmpbuf, EXTCRC); - e.csize = get32(tmpbuf, EXTSIZ); - e.size = get32(tmpbuf, EXTLEN); + readFully(tmpbuf, 0, EXTHDR); + long sig = get32(tmpbuf, 0); + if (sig != EXTSIG) { // no EXTSIG present + e.crc = sig; + e.csize = get32(tmpbuf, EXTSIZ - EXTCRC); + e.size = get32(tmpbuf, EXTLEN - EXTCRC); + ((PushbackInputStream)in).unread( + tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC); + } else { + e.crc = get32(tmpbuf, EXTCRC); + e.csize = get32(tmpbuf, EXTSIZ); + e.size = get32(tmpbuf, EXTLEN); + } } } if (e.size != inf.getBytesWritten()) { @@ -433,6 +475,14 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants { * The bytes are assumed to be in Intel (little-endian) byte order. */ private static final long get32(byte b[], int off) { - return get16(b, off) | ((long)get16(b, off+2) << 16); + return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL; + } + + /* + * Fetches signed 64-bit value from byte array at specified offset. + * The bytes are assumed to be in Intel (little-endian) byte order. + */ + private static final long get64(byte b[], int off) { + return get32(b, off) | (get32(b, off+4) << 32); } } diff --git a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java index 797a37392fe..bd44d3213cf 100644 --- a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java +++ b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.io.OutputStream; import java.io.IOException; import java.util.Vector; import java.util.HashSet; +import static java.util.zip.ZipConstants64.*; /** * This class implements an output stream filter for writing files in the @@ -343,26 +344,52 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { private void writeLOC(XEntry xentry) throws IOException { ZipEntry e = xentry.entry; int flag = xentry.flag; + int elen = (e.extra != null) ? e.extra.length : 0; + boolean hasZip64 = false; + writeInt(LOCSIG); // LOC header signature - writeShort(version(e)); // version needed to extract - writeShort(flag); // general purpose bit flag - writeShort(e.method); // compression method - writeInt(e.time); // last modification time + if ((flag & 8) == 8) { + writeShort(version(e)); // version needed to extract + writeShort(flag); // general purpose bit flag + writeShort(e.method); // compression method + writeInt(e.time); // last modification time + // store size, uncompressed size, and crc-32 in data descriptor // immediately following compressed entry data writeInt(0); writeInt(0); writeInt(0); } else { - writeInt(e.crc); // crc-32 - writeInt(e.csize); // compressed size - writeInt(e.size); // uncompressed size + if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) { + hasZip64 = true; + writeShort(45); // ver 4.5 for zip64 + } else { + writeShort(version(e)); // version needed to extract + } + writeShort(flag); // general purpose bit flag + writeShort(e.method); // compression method + writeInt(e.time); // last modification time + writeInt(e.crc); // crc-32 + if (hasZip64) { + writeInt(ZIP64_MAGICVAL); + writeInt(ZIP64_MAGICVAL); + elen += 20; //headid(2) + size(2) + size(8) + csize(8) + } else { + writeInt(e.csize); // compressed size + writeInt(e.size); // uncompressed size + } } byte[] nameBytes = getUTF8Bytes(e.name); writeShort(nameBytes.length); - writeShort(e.extra != null ? e.extra.length : 0); + writeShort(elen); writeBytes(nameBytes, 0, nameBytes.length); + if (hasZip64) { + writeShort(ZIP64_EXTID); + writeShort(16); + writeLong(e.size); + writeLong(e.csize); + } if (e.extra != null) { writeBytes(e.extra, 0, e.extra.length); } @@ -375,8 +402,13 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { private void writeEXT(ZipEntry e) throws IOException { writeInt(EXTSIG); // EXT header signature writeInt(e.crc); // crc-32 - writeInt(e.csize); // compressed size - writeInt(e.size); // uncompressed size + if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) { + writeLong(e.csize); + writeLong(e.size); + } else { + writeInt(e.csize); // compressed size + writeInt(e.size); // uncompressed size + } } /* @@ -387,18 +419,49 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { ZipEntry e = xentry.entry; int flag = xentry.flag; int version = version(e); + + long csize = e.csize; + long size = e.size; + long offset = xentry.offset; + int e64len = 0; + boolean hasZip64 = false; + if (e.csize >= ZIP64_MAGICVAL) { + csize = ZIP64_MAGICVAL; + e64len += 8; // csize(8) + hasZip64 = true; + } + if (e.size >= ZIP64_MAGICVAL) { + size = ZIP64_MAGICVAL; // size(8) + e64len += 8; + hasZip64 = true; + } + if (xentry.offset >= ZIP64_MAGICVAL) { + offset = ZIP64_MAGICVAL; + e64len += 8; // offset(8) + hasZip64 = true; + } writeInt(CENSIG); // CEN header signature - writeShort(version); // version made by - writeShort(version); // version needed to extract + if (hasZip64) { + writeShort(45); // ver 4.5 for zip64 + writeShort(45); + } else { + writeShort(version); // version made by + writeShort(version); // version needed to extract + } writeShort(flag); // general purpose bit flag writeShort(e.method); // compression method writeInt(e.time); // last modification time writeInt(e.crc); // crc-32 - writeInt(e.csize); // compressed size - writeInt(e.size); // uncompressed size + writeInt(csize); // compressed size + writeInt(size); // uncompressed size byte[] nameBytes = getUTF8Bytes(e.name); writeShort(nameBytes.length); - writeShort(e.extra != null ? e.extra.length : 0); + if (hasZip64) { + // + headid(2) + datasize(2) + writeShort(e64len + 4 + (e.extra != null ? e.extra.length : 0)); + } else { + writeShort(e.extra != null ? e.extra.length : 0); + } byte[] commentBytes; if (e.comment != null) { commentBytes = getUTF8Bytes(e.comment); @@ -410,8 +473,18 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { writeShort(0); // starting disk number writeShort(0); // internal file attributes (unused) writeInt(0); // external file attributes (unused) - writeInt(xentry.offset); // relative offset of local header + writeInt(offset); // relative offset of local header writeBytes(nameBytes, 0, nameBytes.length); + if (hasZip64) { + writeShort(ZIP64_EXTID);// Zip64 extra + writeShort(e64len); + if (size == ZIP64_MAGICVAL) + writeLong(e.size); + if (csize == ZIP64_MAGICVAL) + writeLong(e.csize); + if (offset == ZIP64_MAGICVAL) + writeLong(xentry.offset); + } if (e.extra != null) { writeBytes(e.extra, 0, e.extra.length); } @@ -424,15 +497,50 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { * Writes end of central directory (END) header. */ private void writeEND(long off, long len) throws IOException { + boolean hasZip64 = false; + long xlen = len; + long xoff = off; + if (xlen >= ZIP64_MAGICVAL) { + xlen = ZIP64_MAGICVAL; + hasZip64 = true; + } + if (xoff >= ZIP64_MAGICVAL) { + xoff = ZIP64_MAGICVAL; + hasZip64 = true; + } int count = xentries.size(); - writeInt(ENDSIG); // END record signature - writeShort(0); // number of this disk - writeShort(0); // central directory start disk - writeShort(count); // number of directory entries on disk - writeShort(count); // total number of directory entries - writeInt(len); // length of central directory - writeInt(off); // offset of central directory - if (comment != null) { // zip file comment + if (count >= ZIP64_MAGICCOUNT) { + count = ZIP64_MAGICCOUNT; + hasZip64 = true; + } + if (hasZip64) { + long off64 = written; + //zip64 end of central directory record + writeInt(ZIP64_ENDSIG); // zip64 END record signature + writeLong(ZIP64_ENDHDR - 12); // size of zip64 end + writeShort(45); // version made by + writeShort(45); // version needed to extract + writeInt(0); // number of this disk + writeInt(0); // central directory start disk + writeLong(xentries.size()); // number of directory entires on disk + writeLong(xentries.size()); // number of directory entires + writeLong(len); // length of central directory + writeLong(off); // offset of central directory + + //zip64 end of central directory locator + writeInt(ZIP64_LOCSIG); // zip64 END locator signature + writeInt(0); // zip64 END start disk + writeLong(off64); // offset of zip64 END + writeInt(1); // total number of disks (?) + } + writeInt(ENDSIG); // END record signature + writeShort(0); // number of this disk + writeShort(0); // central directory start disk + writeShort(count); // number of directory entries on disk + writeShort(count); // total number of directory entries + writeInt(xlen); // length of central directory + writeInt(xoff); // offset of central directory + if (comment != null) { // zip file comment byte[] b = getUTF8Bytes(comment); writeShort(b.length); writeBytes(b, 0, b.length); @@ -463,6 +571,22 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { written += 4; } + /* + * Writes a 64-bit int to the output stream in little-endian byte order. + */ + private void writeLong(long v) throws IOException { + OutputStream out = this.out; + out.write((int)((v >>> 0) & 0xff)); + out.write((int)((v >>> 8) & 0xff)); + out.write((int)((v >>> 16) & 0xff)); + out.write((int)((v >>> 24) & 0xff)); + out.write((int)((v >>> 32) & 0xff)); + out.write((int)((v >>> 40) & 0xff)); + out.write((int)((v >>> 48) & 0xff)); + out.write((int)((v >>> 56) & 0xff)); + written += 8; + } + /* * Writes an array of bytes to the output stream. */ diff --git a/jdk/src/share/classes/java/util/zip/package.html b/jdk/src/share/classes/java/util/zip/package.html index d32e0fa0f4a..d4b59263678 100644 --- a/jdk/src/share/classes/java/util/zip/package.html +++ b/jdk/src/share/classes/java/util/zip/package.html @@ -45,6 +45,13 @@ input streams. Info-ZIP Application Note 970311 - a detailed description of the Info-ZIP format upon which the java.util.zip classes are based. +

+ +

  • An implementation may optionally support the ZIP64(tm) format extensions + defined by the + + PKWARE ZIP File Format Specification. The ZIP64(tm) format extensions + are used to overcome the size limitations of the original ZIP format.

  • ZLIB Compressed Data Format Specification version 3.3 @@ -70,7 +77,6 @@ input streams.
  • CRC-32 checksum is described in RFC 1952 (above)

  • Adler-32 checksum is described in RFC 1950 (above) - diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index 1ce3ab21a02..9b4b16fa11d 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -2545,7 +2545,19 @@ public final class KeyTool { * Returns true if the certificate is self-signed, false otherwise. */ private boolean isSelfSigned(X509Certificate cert) { - return cert.getSubjectDN().equals(cert.getIssuerDN()); + return signedBy(cert, cert); + } + + private boolean signedBy(X509Certificate end, X509Certificate ca) { + if (!ca.getSubjectDN().equals(end.getIssuerDN())) { + return false; + } + try { + end.verify(ca.getPublicKey()); + return true; + } catch (Exception e) { + return false; + } } /** @@ -2869,20 +2881,18 @@ public final class KeyTool { Certificate tmpCert = replyCerts[0]; replyCerts[0] = replyCerts[i]; replyCerts[i] = tmpCert; - Principal issuer = ((X509Certificate)replyCerts[0]).getIssuerDN(); + + X509Certificate thisCert = (X509Certificate)replyCerts[0]; for (i=1; i < replyCerts.length-1; i++) { - // find a cert in the reply whose "subject" is the same as the - // given "issuer" + // find a cert in the reply who signs thisCert int j; for (j=i; j chain, Hashtable> certs) { - Principal subject = certToVerify.getSubjectDN(); Principal issuer = certToVerify.getIssuerDN(); - if (subject.equals(issuer)) { + if (isSelfSigned(certToVerify)) { // reached self-signed root cert; // no verification needed because it's trusted. chain.addElement(certToVerify); diff --git a/jdk/src/share/native/java/util/zip/zip_util.c b/jdk/src/share/native/java/util/zip/zip_util.c index f381629712c..89f52ae3bcc 100644 --- a/jdk/src/share/native/java/util/zip/zip_util.c +++ b/jdk/src/share/native/java/util/zip/zip_util.c @@ -312,6 +312,38 @@ findEND(jzfile *zip, void *endbuf) return -1; /* END header not found */ } +/* + * Searches for the ZIP64 end of central directory (END) header. The + * contents of the ZIP64 END header will be read and placed in end64buf. + * Returns the file position of the ZIP64 END header, otherwise returns + * -1 if the END header was not found or an error occurred. + * + * The ZIP format specifies the "position" of each related record as + * ... + * [central directory] + * [zip64 end of central directory record] + * [zip64 end of central directory locator] + * [end of central directory record] + * + * The offset of zip64 end locator can be calculated from endpos as + * "endpos - ZIP64_LOCHDR". + * The "offset" of zip64 end record is stored in zip64 end locator. + */ +static jlong +findEND64(jzfile *zip, void *end64buf, jlong endpos) +{ + char loc64[ZIP64_LOCHDR]; + jlong end64pos; + if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) { + return -1; // end64 locator not found + } + end64pos = ZIP64_LOCOFF(loc64); + if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR, end64pos) == -1) { + return -1; // end64 record not found + } + return end64pos; +} + /* * Returns a hash code value for a C-style NUL-terminated string. */ @@ -463,7 +495,7 @@ static jlong readCEN(jzfile *zip, jint knownTotal) { /* Following are unsigned 32-bit */ - jlong endpos, cenpos, cenlen; + jlong endpos, end64pos, cenpos, cenlen, cenoff; /* Following are unsigned 16-bit */ jint total, tablelen, i, j; unsigned char *cenbuf = NULL; @@ -474,6 +506,7 @@ readCEN(jzfile *zip, jint knownTotal) jlong offset; #endif unsigned char endbuf[ENDHDR]; + jint endhdrlen = ENDHDR; jzcell *entries; jint *table; @@ -490,13 +523,27 @@ readCEN(jzfile *zip, jint knownTotal) /* Get position and length of central directory */ cenlen = ENDSIZ(endbuf); + cenoff = ENDOFF(endbuf); + total = ENDTOT(endbuf); + if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL || + total == ZIP64_MAGICCOUNT) { + unsigned char end64buf[ZIP64_ENDHDR]; + if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) { + cenlen = ZIP64_ENDSIZ(end64buf); + cenoff = ZIP64_ENDOFF(end64buf); + total = (jint)ZIP64_ENDTOT(end64buf); + endpos = end64pos; + endhdrlen = ZIP64_ENDHDR; + } + } + if (cenlen > endpos) ZIP_FORMAT_ERROR("invalid END header (bad central directory size)"); cenpos = endpos - cenlen; /* Get position of first local file (LOC) header, taking into * account that there may be a stub prefixed to the zip file. */ - zip->locpos = cenpos - ENDOFF(endbuf); + zip->locpos = cenpos - cenoff; if (zip->locpos < 0) ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)"); @@ -527,7 +574,7 @@ readCEN(jzfile *zip, jint knownTotal) out the page size in order to make offset to be multiples of page size. */ - zip->mlen = cenpos - offset + cenlen + ENDHDR; + zip->mlen = cenpos - offset + cenlen + endhdrlen; zip->offset = offset; mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset); zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL : @@ -551,8 +598,13 @@ readCEN(jzfile *zip, jint knownTotal) * is a 2-byte field, but we (and other zip implementations) * support approx. 2**31 entries, we do not trust ENDTOT, but * treat it only as a strong hint. When we call ourselves - * recursively, knownTotal will have the "true" value. */ - total = (knownTotal != -1) ? knownTotal : ENDTOT(endbuf); + * recursively, knownTotal will have the "true" value. + * + * Keep this path alive even with the Zip64 END support added, just + * for zip files that have more than 0xffff entries but don't have + * the Zip64 enabled. + */ + total = (knownTotal != -1) ? knownTotal : total; entries = zip->entries = calloc(total, sizeof(entries[0])); tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions table = zip->table = malloc(tablelen * sizeof(table[0])); @@ -854,6 +906,7 @@ typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint; static jzentry * newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint) { + jlong locoff; jint nlen, elen, clen; jzentry *ze; char *cen; @@ -880,18 +933,55 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint) ze->size = CENLEN(cen); ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen); ze->crc = CENCRC(cen); - ze->pos = -(zip->locpos + CENOFF(cen)); + locoff = CENOFF(cen); + ze->pos = -(zip->locpos + locoff); if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch; memcpy(ze->name, cen + CENHDR, nlen); ze->name[nlen] = '\0'; if (elen > 0) { + char *extra = cen + CENHDR + nlen; + /* This entry has "extra" data */ if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch; ze->extra[0] = (unsigned char) elen; ze->extra[1] = (unsigned char) (elen >> 8); - memcpy(ze->extra+2, cen + CENHDR + nlen, elen); + memcpy(ze->extra+2, extra, elen); + if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL || + locoff == ZIP64_MAGICVAL) { + jint off = 0; + while ((off + 4) < elen) { // spec: HeaderID+DataSize+Data + jint sz = SH(extra, off + 2); + if (SH(extra, off) == ZIP64_EXTID) { + off += 4; + if (ze->size == ZIP64_MAGICVAL) { + // if invalid zip64 extra fields, just skip + if (sz < 8 || (off + 8) > elen) + break; + ze->size = LL(extra, off); + sz -= 8; + off += 8; + } + if (ze->csize == ZIP64_MAGICVAL) { + if (sz < 8 || (off + 8) > elen) + break; + ze->csize = LL(extra, off); + sz -= 8; + off += 8; + } + if (locoff == ZIP64_MAGICVAL) { + if (sz < 8 || (off + 8) > elen) + break; + ze->pos = -(zip->locpos + LL(extra, off)); + sz -= 8; + off += 8; + } + break; + } + off += (sz + 4); + } + } } if (clen > 0) { diff --git a/jdk/src/share/native/java/util/zip/zip_util.h b/jdk/src/share/native/java/util/zip/zip_util.h index 3814ad02d4f..7ad11715e5a 100644 --- a/jdk/src/share/native/java/util/zip/zip_util.h +++ b/jdk/src/share/native/java/util/zip/zip_util.h @@ -38,9 +38,13 @@ #define CENSIG 0x02014b50L /* "PK\001\002" */ #define ENDSIG 0x06054b50L /* "PK\005\006" */ +#define ZIP64_ENDSIG 0x06064b50L /* "PK\006\006" */ +#define ZIP64_LOCSIG 0x07064b50L /* "PK\006\007" */ + /* * Header sizes including signatures */ + #ifdef USE_MMAP #define SIGSIZ 4 #endif @@ -49,12 +53,22 @@ #define CENHDR 46 #define ENDHDR 22 +#define ZIP64_ENDHDR 56 // ZIP64 end header size +#define ZIP64_LOCHDR 20 // ZIP64 end loc header size +#define ZIP64_EXTHDR 24 // EXT header size +#define ZIP64_EXTID 1 // Extra field Zip64 header ID + +#define ZIP64_MAGICVAL 0xffffffffLL +#define ZIP64_MAGICCOUNT 0xffff + + /* * Header field access macros */ #define CH(b, n) (((unsigned char *)(b))[n]) #define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8)) -#define LG(b, n) (SH(b, n) | (SH(b, n+2) << 16)) +#define LG(b, n) ((SH(b, n) | (SH(b, n+2) << 16)) &0xffffffffUL) +#define LL(b, n) (((jlong)LG(b, n)) | (((jlong)LG(b, n+4)) << 32)) #define GETSIG(b) LG(b, 0) /* @@ -105,6 +119,26 @@ #define ENDOFF(b) LG(b, 16) /* central directory offset */ #define ENDCOM(b) SH(b, 20) /* size of zip file comment */ +/* + * Macros for getting Zip64 end of central directory header fields + */ +#define ZIP64_ENDLEN(b) LL(b, 4) /* size of zip64 end of central dir */ +#define ZIP64_ENDVEM(b) SH(b, 12) /* version made by */ +#define ZIP64_ENDVER(b) SH(b, 14) /* version needed to extract */ +#define ZIP64_ENDNMD(b) LG(b, 16) /* number of this disk */ +#define ZIP64_ENDDSK(b) LG(b, 20) /* disk number of start */ +#define ZIP64_ENDTOD(b) LL(b, 24) /* total number of entries on this disk */ +#define ZIP64_ENDTOT(b) LL(b, 32) /* total number of entries */ +#define ZIP64_ENDSIZ(b) LL(b, 40) /* central directory size in bytes */ +#define ZIP64_ENDOFF(b) LL(b, 48) /* offset of first CEN header */ + +/* + * Macros for getting Zip64 end of central directory locator fields + */ +#define ZIP64_LOCDSK(b) LG(b, 4) /* disk number start */ +#define ZIP64_LOCOFF(b) LL(b, 8) /* offset of zip64 end */ +#define ZIP64_LOCTOT(b) LG(b, 16) /* total number of disks */ + /* * Supported compression methods */ @@ -145,7 +179,7 @@ typedef struct jzentry { /* Zip file entry */ */ typedef struct jzcell { unsigned int hash; /* 32 bit hashcode on name */ - unsigned int cenpos; /* Offset of central directory file header */ + jlong cenpos; /* Offset of central directory file header */ unsigned int next; /* hash chain: index into jzfile->entries */ } jzcell; diff --git a/jdk/src/share/native/java/util/zip/zlib-1.1.3/zlib.h b/jdk/src/share/native/java/util/zip/zlib-1.1.3/zlib.h index 9576715b2fa..00fdf06007d 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.1.3/zlib.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.1.3/zlib.h @@ -106,11 +106,11 @@ struct internal_state; typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + long long total_in; /* total nb of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + long long total_out; /* total nb of bytes output so far */ char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ diff --git a/jdk/test/java/util/zip/LargeZip.java b/jdk/test/java/util/zip/LargeZip.java new file mode 100644 index 00000000000..e49950261b6 --- /dev/null +++ b/jdk/test/java/util/zip/LargeZip.java @@ -0,0 +1,193 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import java.nio.*; +import java.util.*; +import java.util.zip.*; + +public class LargeZip { + // If true, don't delete large ZIP file created for test. + static final boolean debug = System.getProperty("debug") != null; + + //static final int DATA_LEN = 1024 * 1024; + static final int DATA_LEN = 80 * 1024; + static final int DATA_SIZE = 8; + + static long fileSize = 6L * 1024L * 1024L * 1024L; // 6GB + + static boolean userFile = false; + + static byte[] data; + static File largeFile; + static String lastEntryName; + + /* args can be empty, in which case check a 3 GB file which is created for + * this test (and then deleted). Or it can be a number, in which case + * that designates the size of the file that's created for this test (and + * then deleted). Or it can be the name of a file to use for the test, in + * which case it is *not* deleted. Note that in this last case, the data + * comparison might fail. + */ + static void realMain (String[] args) throws Throwable { + if (args.length > 0) { + try { + fileSize = Long.parseLong(args[0]); + System.out.println("Testing with file of size " + fileSize); + } catch (NumberFormatException ex) { + largeFile = new File(args[0]); + if (!largeFile.exists()) { + throw new Exception("Specified file " + args[0] + " does not exist"); + } + userFile = true; + System.out.println("Testing with user-provided file " + largeFile); + } + } + File testDir = null; + if (largeFile == null) { + testDir = new File(System.getProperty("test.scratch", "."), + "LargeZip"); + if (testDir.exists()) { + if (!testDir.delete()) { + throw new Exception("Cannot delete already-existing test directory"); + } + } + check(!testDir.exists() && testDir.mkdirs()); + largeFile = new File(testDir, "largezip.zip"); + createLargeZip(); + } + + readLargeZip1(); + readLargeZip2(); + + if (!userFile && !debug) { + check(largeFile.delete()); + check(testDir.delete()); + } + } + + static void createLargeZip() throws Throwable { + int iterations = DATA_LEN / DATA_SIZE; + ByteBuffer bb = ByteBuffer.allocate(DATA_SIZE); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (int i = 0; i < iterations; i++) { + bb.putDouble(0, Math.random()); + baos.write(bb.array(), 0, DATA_SIZE); + } + data = baos.toByteArray(); + + ZipOutputStream zos = new ZipOutputStream( + new BufferedOutputStream(new FileOutputStream(largeFile))); + long length = 0; + while (length < fileSize) { + ZipEntry ze = new ZipEntry("entry-" + length); + lastEntryName = ze.getName(); + zos.putNextEntry(ze); + zos.write(data, 0, data.length); + zos.closeEntry(); + length = largeFile.length(); + } + System.out.println("Last entry written is " + lastEntryName); + zos.close(); + } + + static void readLargeZip1() throws Throwable { + ZipFile zipFile = new ZipFile(largeFile); + ZipEntry entry = null; + String entryName = null; + int count = 0; + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + entry = entries.nextElement(); + entryName = entry.getName(); + count++; + } + System.out.println("Number of entries read: " + count); + System.out.println("Last entry read is " + entryName); + check(!entry.isDirectory()); + if (check(entryName.equals(lastEntryName))) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + InputStream is = zipFile.getInputStream(entry); + byte buf[] = new byte[4096]; + int len; + while ((len = is.read(buf)) >= 0) { + baos.write(buf, 0, len); + } + baos.close(); + is.close(); + check(Arrays.equals(data, baos.toByteArray())); + } + } + + + static void readLargeZip2() throws Throwable { + ZipInputStream zis = new ZipInputStream( + new BufferedInputStream(new FileInputStream(largeFile))); + ZipEntry entry = null; + String entryName = null; + int count = 0; + while ((entry = zis.getNextEntry()) != null) { + entryName = entry.getName(); + if (entryName.equals(lastEntryName)) { + break; + } + count++; + } + System.out.println("Number of entries read: " + count); + System.out.println("Last entry read is " + entryName); + check(!entry.isDirectory()); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + byte buf[] = new byte[4096]; + int len; + while ((len = zis.read(buf)) >= 0) { + baos.write(buf, 0, len); + } + baos.close(); + check(Arrays.equals(data, baos.toByteArray())); + check(zis.getNextEntry() == null); + zis.close(); + } + + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void pass(String msg) {System.out.println(msg); passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void unexpected(Throwable t, String msg) { + System.out.println(msg); failed++; t.printStackTrace();} + static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.println("\nPassed = " + passed + " failed = " + failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/zip/ZipFile/LargeZipFile.java b/jdk/test/java/util/zip/ZipFile/LargeZipFile.java index 479bac48bef..d228a5f93e3 100644 --- a/jdk/test/java/util/zip/ZipFile/LargeZipFile.java +++ b/jdk/test/java/util/zip/ZipFile/LargeZipFile.java @@ -158,4 +158,3 @@ public class LargeZipFile { System.out.println("\nPassed = " + passed + " failed = " + failed); if (failed > 0) throw new AssertionError("Some tests failed");} } - diff --git a/jdk/test/sun/security/tools/keytool/selfissued.sh b/jdk/test/sun/security/tools/keytool/selfissued.sh new file mode 100644 index 00000000000..e6e06c040b3 --- /dev/null +++ b/jdk/test/sun/security/tools/keytool/selfissued.sh @@ -0,0 +1,69 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 6825352 +# @summary support self-issued certificate in keytool +# +# @run shell selfissued.sh +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + ;; + * ) + FS="/" + ;; +esac + +KS=selfsigned.jks +KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS" + +rm $KS + +$KT -alias ca -dname CN=CA -genkeypair +$KT -alias me -dname CN=CA -genkeypair +$KT -alias e1 -dname CN=E1 -genkeypair +$KT -alias e2 -dname CN=E2 -genkeypair + +# me signed by ca, self-issued +$KT -alias me -certreq | $KT -alias ca -gencert | $KT -alias me -importcert + +# Import e1 signed by me, should add me and ca +$KT -alias e1 -certreq | $KT -alias me -gencert | $KT -alias e1 -importcert +$KT -alias e1 -list -v | grep '\[3\]' || { echo Bad E1; exit 1; } + +# Import (e2 signed by me,ca,me), should reorder to (e2,me,ca) +( $KT -alias e2 -certreq | $KT -alias me -gencert; $KT -exportcert -alias ca; $KT -exportcert -alias me ) | $KT -alias e2 -importcert +$KT -alias e2 -list -v | grep '\[3\]' || { echo Bad E2; exit 1; } + +echo Good + diff --git a/langtools/.hgtags b/langtools/.hgtags index a260d94e956..0ea2c411d86 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -26,3 +26,4 @@ c53007f34195f69223bdd4125ec6c0740f7d6736 jdk7-b48 d17d927ad9bdfafae32451645d182acb7bed7be6 jdk7-b49 46f2f6ed96f13fc49fec3d1b6aa616686128cb57 jdk7-b50 8c55d5b0ed71ed3a749eb97e4eab79b4831649b8 jdk7-b51 +29329051d483d39f66073752ba4afbf29d893cfe jdk7-b52 diff --git a/langtools/make/jprt.config b/langtools/make/jprt.config deleted file mode 100644 index b112bcb1eda..00000000000 --- a/langtools/make/jprt.config +++ /dev/null @@ -1,241 +0,0 @@ -#!echo "This is not a shell script" -############################################################################# -# -# Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# -############################################################################# -# -# JPRT shell configuration for building. -# -# Input environment variables: -# ALT_BOOTDIR -# ALT_SLASH_JAVA -# ALT_JDK_IMPORT_PATH -# Windows Only: -# PATH -# PROCESSOR_IDENTIFIER -# ROOTDIR -# -# Output variable settings: -# make Full path to GNU make -# -# Output environment variables: -# PATH -# Windows Only: -# ALT_DEVTOOLS_PATH (To avoid the C:/UTILS default) -# -# After JDK6, most settings will be found via ALT_SLASH_JAVA or -# by way of other system environment variables. If this was JDK5 -# or an older JDK, you might need to export more ALT_* variables. -# -############################################################################# - -############################################################################# -# Error -error() # message -{ - echo "ERROR: $1" - exit 6 -} -# Directory must exist -dirMustExist() # dir name -{ - if [ ! -d "$1" ] ; then - error "Directory for $2 does not exist: $1" - fi -} -# File must exist -fileMustExist() # dir name -{ - if [ ! -f "$1" ] ; then - error "File for $2 does not exist: $1" - fi -} -############################################################################# - -# Should be set by JPRT as the 3 basic inputs -bootdir="${ALT_BOOTDIR}" -slashjava="${ALT_SLASH_JAVA}" -jdk_import="${ALT_JDK_IMPORT_PATH}" - -# Check input -dirMustExist "${bootdir}" ALT_BOOTDIR -dirMustExist "${slashjava}" ALT_SLASH_JAVA -dirMustExist "${jdk_import}" ALT_JDK_IMPORT_PATH - -# Uses 'uname -s', but only expect SunOS or Linux, assume Windows otherwise. -osname=`uname -s` -if [ "${osname}" = SunOS ] ; then - - # SOLARIS: Sparc or X86 - osarch=`uname -p` - if [ "${osarch}" = sparc ] ; then - solaris_arch=sparc - else - solaris_arch=i386 - fi - - # Add basic solaris system paths - path4sdk=/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk=${antbindir}:${path4sdk} - - # Find GNU make - make=/usr/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=/opt/sfw/bin/gmake - if [ ! -f ${make} ] ; then - make=${slashjava}/devtools/${solaris_arch}/bin/gnumake - fi - fi - fileMustExist "${make}" make - - # File creation mask - umask 002 - -elif [ "${osname}" = Linux ] ; then - - # LINUX: X86, AMD64 - osarch=`uname -m` - if [ "${osarch}" = i686 ] ; then - linux_arch=i586 - elif [ "${osarch}" = x86_64 ] ; then - linux_arch=amd64 - fi - - # Add basic paths - path4sdk=/usr/bin:/bin:/usr/sbin:/sbin - - # Get the previous JDK to be used to bootstrap the build - path4sdk=${bootdir}/bin:${path4sdk} - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk=${antbindir}:${path4sdk} - - # Find GNU make - make=/usr/bin/make - fileMustExist "${make}" make - - umask 002 - -else - - # Windows: Differs on CYGWIN vs. MKS - # Also, blanks in pathnames gives GNU make headaches, so anything placed - # in any ALT_* variable should be the short windows dosname. - - # WINDOWS: Install and use MKS or CYGWIN (should have already been done) - # Assumption here is that you are in a shell window via MKS or cygwin. - # MKS install should have defined the environment variable ROOTDIR. - # We also need to figure out which one we have: X86, AMD64 - if [ "`echo ${PROCESSOR_IDENTIFIER} | fgrep AMD64`" != "" ] ; then - windows_arch=amd64 - else - windows_arch=i586 - fi - - # We need to determine if we are running a CYGWIN shell or an MKS shell - # (if uname isn't available, then it will be unix_toolset=unknown) - unix_toolset=unknown - if [ "`uname -a | fgrep Cygwin`" = "" -a -d "${ROOTDIR}" ] ; then - # We kind of assume ROOTDIR is where MKS is and it's ok - unix_toolset=MKS - mkshome=`dosname -s "${ROOTDIR}"` - # Utility to convert to short pathnames without spaces - dosname="${mkshome}/mksnt/dosname -s" - # Most unix utilities are in the mksnt directory of ROOTDIR - unixcommand_path="${mkshome}/mksnt" - path4sdk="${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - devtools_path="${slashjava}/devtools/win32/bin" - path4sdk="${devtools_path};${path4sdk}" - # Normally this need not be set, but on Windows it's default is C:/UTILS - ALT_DEVTOOLS_PATH="${devtools_path}" - export ALT_DEVTOOLS_PATH - dirMustExist "${devtools_path}" ALT_DEVTOOLS_PATH - # Find GNU make - make="${devtools_path}/gnumake.exe" - fileMustExist "${make}" make - elif [ "`uname -a | fgrep Cygwin`" != "" -a -f /bin/cygpath ] ; then - # For CYGWIN, uname will have "Cygwin" in it, and /bin/cygpath should exist - unix_toolset=CYGWIN - # Utility to convert to short pathnames without spaces - dosname="/usr/bin/cygpath -a -m -s" - # Most unix utilities are in the /usr/bin - unixcommand_path="/usr/bin" - path4sdk="${unixcommand_path}" - dirMustExist "${unixcommand_path}" ALT_UNIXCOMMAND_PATH - # Find GNU make - make="${unixcommand_path}/make.exe" - fileMustExist "${make}" make - else - echo "WARNING: Cannot figure out if this is MKS or CYGWIN" - fi - - # WINDOWS: Get the previous JDK to be used to bootstrap the build - path4sdk="${bootdir}/bin;${path4sdk}" - - # Ant - ANT_HOME=${slashjava}/devtools/share/ant/1.7.0 - export ANT_HOME - antbindir=${ANT_HOME}/bin - fileMustExist "${antbindir}/ant" ant - path4sdk="${antbindir};${path4sdk}" - - # Turn all \\ into /, remove duplicates and trailing / - slash_path="`echo ${path4sdk} | sed -e 's@\\\\@/@g' -e 's@//@/@g' -e 's@/$@@' -e 's@/;@;@g'`" - - # For windows, it's hard to know where the system is, so we just add this - # to PATH. - path4sdk="${slash_path};${PATH}" - - # Convert path4sdk to cygwin style - if [ "${unix_toolset}" = CYGWIN ] ; then - path4sdk="`/usr/bin/cygpath -p ${path4sdk}`" - fi - -fi - -# Export PATH setting -PATH="${path4sdk}" -export PATH - -# Things we need to unset -unset LD_LIBRARY_PATH -unset LD_LIBRARY_PATH_32 -unset LD_LIBRARY_PATH_64 -unset JAVA_HOME - diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java index d6c298f13da..273b42558ed 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractMemberWriter.java @@ -60,7 +60,11 @@ public abstract class AbstractMemberWriter { /*** abstracts ***/ - public abstract void printSummaryLabel(ClassDoc cd); + public abstract void printSummaryLabel(); + + public abstract void printTableSummary(); + + public abstract void printSummaryTableHeader(ProgramElementDoc member); public abstract void printInheritedSummaryLabel(ClassDoc cd); @@ -342,12 +346,13 @@ public abstract class AbstractMemberWriter { * format for listing the API. Call methods from the sub-class to complete * the generation. */ - protected void printDeprecatedAPI(List deprmembers, String headingKey) { + protected void printDeprecatedAPI(List deprmembers, String headingKey, String tableSummary, String[] tableHeader) { if (deprmembers.size() > 0) { - writer.tableIndexSummary(); - writer.tableHeaderStart("#CCCCFF"); - writer.strongText(headingKey); - writer.tableHeaderEnd(); + writer.tableIndexSummary(tableSummary); + writer.tableCaptionStart(); + writer.printText(headingKey); + writer.tableCaptionEnd(); + writer.summaryTableHeader(tableHeader, "col"); for (int i = 0; i < deprmembers.size(); i++) { ProgramElementDoc member =(ProgramElementDoc)deprmembers.get(i); writer.trBgcolorStyle("white", "TableRowColor"); @@ -370,19 +375,26 @@ public abstract class AbstractMemberWriter { /** * Print use info. */ - protected void printUseInfo(List mems, String heading) { + protected void printUseInfo(List mems, String heading, String tableSummary) { if (mems == null) { return; } List members = mems; + boolean printedUseTableHeader = false; if (members.size() > 0) { - writer.tableIndexSummary(); - writer.tableUseInfoHeaderStart("#CCCCFF"); + writer.tableIndexSummary(tableSummary); + writer.tableSubCaptionStart(); writer.print(heading); - writer.tableHeaderEnd(); + writer.tableCaptionEnd(); for (Iterator it = members.iterator(); it.hasNext(); ) { ProgramElementDoc pgmdoc = it.next(); ClassDoc cd = pgmdoc.containingClass(); + if (!printedUseTableHeader) { + // Passing ProgramElementDoc helps decides printing + // interface or class header in case of nested classes. + this.printSummaryTableHeader(pgmdoc); + printedUseTableHeader = true; + } writer.printSummaryLinkType(this, pgmdoc); if (cd != null && !(pgmdoc instanceof ConstructorDoc) diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java index 36742cf7f95..b743aeacd2d 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java @@ -35,6 +35,7 @@ import java.util.*; * generate overview-frame.html as well as overview-summary.html. * * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { @@ -61,7 +62,7 @@ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { protected abstract void printOverviewHeader(); - protected abstract void printIndexHeader(String text); + protected abstract void printIndexHeader(String text, String tableSummary); protected abstract void printIndexRow(PackageDoc pkg); @@ -101,7 +102,10 @@ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { * Generate the frame or non-frame package index. */ protected void generateIndex() { - printIndexContents(packages, "doclet.Package_Summary"); + printIndexContents(packages, "doclet.Package_Summary", + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Package_Summary"), + configuration.getText("doclet.packages"))); } /** @@ -111,10 +115,10 @@ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { * @param packages Array of packages to be documented. * @param text String which will be used as the heading. */ - protected void printIndexContents(PackageDoc[] packages, String text) { + protected void printIndexContents(PackageDoc[] packages, String text, String tableSummary) { if (packages.length > 0) { Arrays.sort(packages); - printIndexHeader(text); + printIndexHeader(text, tableSummary); printAllClassesPackagesLink(); for(int i = 0; i < packages.length; i++) { if (packages[i] != null) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java index 1442e3ccf0c..5bf2f8e19fe 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java @@ -34,6 +34,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * Writes annotation type optional member documentation in HTML format. * * @author Jamie Ho + * @author Bhavesh Patel (Modified) */ public class AnnotationTypeOptionalMemberWriterImpl extends AnnotationTypeRequiredMemberWriterImpl @@ -89,8 +90,27 @@ public class AnnotationTypeOptionalMemberWriterImpl extends /** * {@inheritDoc} */ - public void printSummaryLabel(ClassDoc cd) { - writer.strongText("doclet.Annotation_Type_Optional_Member_Summary"); + public void printSummaryLabel() { + writer.printText("doclet.Annotation_Type_Optional_Member_Summary"); + } + + /** + * {@inheritDoc} + */ + public void printTableSummary() { + writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + configuration().getText("doclet.Annotation_Type_Optional_Member_Summary"), + configuration().getText("doclet.annotation_type_optional_members"))); + } + + public void printSummaryTableHeader(ProgramElementDoc member) { + String[] header = new String[] { + writer.getModifierTypeHeader(), + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Annotation_Type_Optional_Member"), + configuration().getText("doclet.Description")) + }; + writer.summaryTableHeader(header, "col"); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java index 01e517ce426..9b745c68187 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java @@ -34,6 +34,7 @@ import com.sun.tools.doclets.internal.toolkit.*; * Writes annotation type required member documentation in HTML format. * * @author Jamie Ho + * @author Bhavesh Patel (Modified) */ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter implements AnnotationTypeRequiredMemberWriter, MemberSummaryWriter { @@ -178,8 +179,27 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter /** * {@inheritDoc} */ - public void printSummaryLabel(ClassDoc cd) { - writer.strongText("doclet.Annotation_Type_Required_Member_Summary"); + public void printSummaryLabel() { + writer.printText("doclet.Annotation_Type_Required_Member_Summary"); + } + + /** + * {@inheritDoc} + */ + public void printTableSummary() { + writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + configuration().getText("doclet.Annotation_Type_Required_Member_Summary"), + configuration().getText("doclet.annotation_type_required_members"))); + } + + public void printSummaryTableHeader(ProgramElementDoc member) { + String[] header = new String[] { + writer.getModifierTypeHeader(), + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Annotation_Type_Required_Member"), + configuration().getText("doclet.Description")) + }; + writer.summaryTableHeader(header, "col"); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java index 73d957e3c4e..6baec7af9d8 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java @@ -34,6 +34,7 @@ import java.util.*; * Generate class usage information. * * @author Robert G. Field + * @author Bhavesh Patel (Modified) */ public class ClassUseWriter extends SubWriterHolderWriter { @@ -65,6 +66,13 @@ public class ClassUseWriter extends SubWriterHolderWriter { final ConstructorWriterImpl constrSubWriter; final FieldWriterImpl fieldSubWriter; final NestedClassWriterImpl classSubWriter; + // Summary for various use tables. + final String classUseTableSummary; + final String subclassUseTableSummary; + final String subinterfaceUseTableSummary; + final String fieldUseTableSummary; + final String methodUseTableSummary; + final String constructorUseTableSummary; /** @@ -116,6 +124,18 @@ public class ClassUseWriter extends SubWriterHolderWriter { constrSubWriter = new ConstructorWriterImpl(this); fieldSubWriter = new FieldWriterImpl(this); classSubWriter = new NestedClassWriterImpl(this); + classUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.classes")); + subclassUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.subclasses")); + subinterfaceUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.subinterfaces")); + fieldUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.fields")); + methodUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.methods")); + constructorUseTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.constructors")); } /** @@ -213,12 +233,13 @@ public class ClassUseWriter extends SubWriterHolderWriter { } protected void generatePackageList() throws IOException { - tableIndexSummary(); - tableHeaderStart("#CCCCFF"); + tableIndexSummary(useTableSummary); + tableCaptionStart(); printText("doclet.ClassUse_Packages.that.use.0", getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, false))); - tableHeaderEnd(); + tableCaptionEnd(); + summaryTableHeader(packageTableHeader, "col"); for (Iterator it = pkgSet.iterator(); it.hasNext();) { PackageDoc pkg = it.next(); @@ -234,12 +255,13 @@ public class ClassUseWriter extends SubWriterHolderWriter { pkgToPackageAnnotations == null || pkgToPackageAnnotations.size() == 0) return; - tableIndexSummary(); - tableHeaderStart("#CCCCFF"); + tableIndexSummary(useTableSummary); + tableCaptionStart(); printText("doclet.ClassUse_PackageAnnotation", getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, false))); - tableHeaderEnd(); + tableCaptionEnd(); + summaryTableHeader(packageTableHeader, "col"); for (Iterator it = pkgToPackageAnnotations.iterator(); it.hasNext();) { PackageDoc pkg = it.next(); trBgcolorStyle("white", "TableRowColor"); @@ -300,83 +322,68 @@ public class ClassUseWriter extends SubWriterHolderWriter { LinkInfoImpl.CONTEXT_CLASS_USE_HEADER, classdoc, false)); String pkgLink = getPackageLink(pkg, Util.getPackageName(pkg), false); classSubWriter.printUseInfo(pkgToClassAnnotations.get(pkg.name()), - configuration.getText("doclet.ClassUse_Annotation", classLink, - pkgLink)); - + configuration.getText("doclet.ClassUse_Annotation", classLink, + pkgLink), classUseTableSummary); classSubWriter.printUseInfo(pkgToClassTypeParameter.get(pkg.name()), - configuration.getText("doclet.ClassUse_TypeParameter", classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_TypeParameter", classLink, + pkgLink), classUseTableSummary); classSubWriter.printUseInfo(pkgToSubclass.get(pkg.name()), - configuration.getText("doclet.ClassUse_Subclass", classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_Subclass", classLink, + pkgLink), subclassUseTableSummary); classSubWriter.printUseInfo(pkgToSubinterface.get(pkg.name()), - configuration.getText("doclet.ClassUse_Subinterface", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_Subinterface", classLink, + pkgLink), subinterfaceUseTableSummary); classSubWriter.printUseInfo(pkgToImplementingClass.get(pkg.name()), - configuration.getText("doclet.ClassUse_ImplementingClass", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_ImplementingClass", classLink, + pkgLink), classUseTableSummary); fieldSubWriter.printUseInfo(pkgToField.get(pkg.name()), - configuration.getText("doclet.ClassUse_Field", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_Field", classLink, + pkgLink), fieldUseTableSummary); fieldSubWriter.printUseInfo(pkgToFieldAnnotations.get(pkg.name()), - configuration.getText("doclet.ClassUse_FieldAnnotations", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_FieldAnnotations", classLink, + pkgLink), fieldUseTableSummary); fieldSubWriter.printUseInfo(pkgToFieldTypeParameter.get(pkg.name()), - configuration.getText("doclet.ClassUse_FieldTypeParameter", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_FieldTypeParameter", classLink, + pkgLink), fieldUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodAnnotations.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodAnnotations", classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodAnnotations", classLink, + pkgLink), methodUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodParameterAnnotations.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodParameterAnnotations", classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodParameterAnnotations", classLink, + pkgLink), methodUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodTypeParameter.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodTypeParameter", classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodTypeParameter", classLink, + pkgLink), methodUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodReturn.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodReturn", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodReturn", classLink, + pkgLink), methodUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodReturnTypeParameter.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodReturnTypeParameter", classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodReturnTypeParameter", classLink, + pkgLink), methodUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodArgs.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodArgs", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodArgs", classLink, + pkgLink), methodUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodArgTypeParameter.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodArgsTypeParameters", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodArgsTypeParameters", classLink, + pkgLink), methodUseTableSummary); methodSubWriter.printUseInfo(pkgToMethodThrows.get(pkg.name()), - configuration.getText("doclet.ClassUse_MethodThrows", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_MethodThrows", classLink, + pkgLink), methodUseTableSummary); constrSubWriter.printUseInfo(pkgToConstructorAnnotations.get(pkg.name()), - configuration.getText("doclet.ClassUse_ConstructorAnnotations", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_ConstructorAnnotations", classLink, + pkgLink), constructorUseTableSummary); constrSubWriter.printUseInfo(pkgToConstructorParameterAnnotations.get(pkg.name()), - configuration.getText("doclet.ClassUse_ConstructorParameterAnnotations", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_ConstructorParameterAnnotations", classLink, + pkgLink), constructorUseTableSummary); constrSubWriter.printUseInfo(pkgToConstructorArgs.get(pkg.name()), - configuration.getText("doclet.ClassUse_ConstructorArgs", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_ConstructorArgs", classLink, + pkgLink), constructorUseTableSummary); constrSubWriter.printUseInfo(pkgToConstructorArgTypeParameter.get(pkg.name()), - configuration.getText("doclet.ClassUse_ConstructorArgsTypeParameters", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_ConstructorArgsTypeParameters", classLink, + pkgLink), constructorUseTableSummary); constrSubWriter.printUseInfo(pkgToConstructorThrows.get(pkg.name()), - configuration.getText("doclet.ClassUse_ConstructorThrows", - classLink, - pkgLink)); + configuration.getText("doclet.ClassUse_ConstructorThrows", classLink, + pkgLink), constructorUseTableSummary); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java index d64b2656d59..ddf51063a0a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -35,6 +35,7 @@ import java.util.*; * Write the Constants Summary Page in HTML format. * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.4 */ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter @@ -50,6 +51,10 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter */ private ClassDoc currentClassDoc; + private final String constantsTableSummary; + + private final String[] constantsTableHeader; + /** * Construct a ConstantsSummaryWriter. * @param configuration the configuration used in this run @@ -59,6 +64,13 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter throws IOException { super(configuration, ConfigurationImpl.CONSTANTS_FILE_NAME); this.configuration = configuration; + constantsTableSummary = configuration.getText("doclet.Constants_Table_Summary", + configuration.getText("doclet.Constants_Summary")); + constantsTableHeader = new String[] { + getModifierTypeHeader(), + configuration.getText("doclet.ConstantField"), + configuration.getText("doclet.Value") + }; } /** @@ -151,12 +163,11 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter * @param classStr the heading to print. */ protected void writeClassName(String classStr) { - table(1, 3, 0); - trBgcolorStyle("#EEEEFF", "TableSubHeadingColor"); - thAlignColspan("left", 3); + table(1, 3, 0, constantsTableSummary); + tableSubCaptionStart(); write(classStr); - thEnd(); - trEnd(); + tableCaptionEnd(); + summaryTableHeader(constantsTableHeader, "col"); } private void tableFooter(boolean isHeader) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java index cb5adbdeeaf..cc38edd8f2c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConstructorWriterImpl.java @@ -37,6 +37,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @author Robert Field * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter implements ConstructorWriter, MemberSummaryWriter { @@ -211,8 +212,34 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter this.foundNonPubConstructor = foundNonPubConstructor; } - public void printSummaryLabel(ClassDoc cd) { - writer.strongText("doclet.Constructor_Summary"); + public void printSummaryLabel() { + writer.printText("doclet.Constructor_Summary"); + } + + public void printTableSummary() { + writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + configuration().getText("doclet.Constructor_Summary"), + configuration().getText("doclet.constructors"))); + } + + public void printSummaryTableHeader(ProgramElementDoc member) { + String[] header; + if (foundNonPubConstructor) { + header = new String[] { + configuration().getText("doclet.Modifier"), + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Constructor"), + configuration().getText("doclet.Description")) + }; + } + else { + header = new String[] { + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Constructor"), + configuration().getText("doclet.Description")) + }; + } + writer.summaryTableHeader(header, "col"); } public void printSummaryAnchor(ClassDoc cd) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java index 68b04a7d72a..46c257b4b47 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/DeprecatedListWriter.java @@ -35,6 +35,7 @@ import java.io.*; * * @see java.util.List * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class DeprecatedListWriter extends SubWriterHolderWriter { @@ -55,6 +56,28 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { "doclet.Deprecated_Annotation_Type_Members" }; + private static final String[] SUMMARY_KEYS = new String[] { + "doclet.deprecated_interfaces", "doclet.deprecated_classes", + "doclet.deprecated_enums", "doclet.deprecated_exceptions", + "doclet.deprecated_errors", + "doclet.deprecated_annotation_types", + "doclet.deprecated_fields", + "doclet.deprecated_methods", "doclet.deprecated_constructors", + "doclet.deprecated_enum_constants", + "doclet.deprecated_annotation_type_members" + }; + + private static final String[] HEADER_KEYS = new String[] { + "doclet.Interface", "doclet.Class", + "doclet.Enum", "doclet.Exceptions", + "doclet.Errors", + "doclet.AnnotationType", + "doclet.Field", + "doclet.Method", "doclet.Constructor", + "doclet.Enum_Constant", + "doclet.Annotation_Type_Member" + }; + private AbstractMemberWriter[] writers; private ConfigurationImpl configuration; @@ -119,11 +142,20 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { ulEnd(); println(); + String memberTableSummary; + String[] memberTableHeader = new String[1]; for (int i = 0; i < DeprecatedAPIListBuilder.NUM_TYPES; i++) { if (deprapi.hasDocumentation(i)) { writeAnchor(deprapi, i); + memberTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText(HEADING_KEYS[i]), + configuration.getText(SUMMARY_KEYS[i])); + memberTableHeader[0] = configuration.getText("doclet.0_and_1", + configuration.getText(HEADER_KEYS[i]), + configuration.getText("doclet.Description")); writers[i].printDeprecatedAPI(deprapi.getList(i), - HEADING_KEYS[i]); + HEADING_KEYS[i], memberTableSummary, memberTableHeader); } } printDeprecatedFooter(); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java index 1d5b4ffbd29..2e7c08bcfb5 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/EnumConstantWriterImpl.java @@ -35,6 +35,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * Writes enum constant documentation in HTML format. * * @author Jamie Ho + * @author Bhavesh Patel (Modified) */ public class EnumConstantWriterImpl extends AbstractMemberWriter implements EnumConstantWriter, MemberSummaryWriter { @@ -194,8 +195,23 @@ public class EnumConstantWriterImpl extends AbstractMemberWriter return VisibleMemberMap.ENUM_CONSTANTS; } - public void printSummaryLabel(ClassDoc cd) { - writer.strongText("doclet.Enum_Constant_Summary"); + public void printSummaryLabel() { + writer.printText("doclet.Enum_Constant_Summary"); + } + + public void printTableSummary() { + writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + configuration().getText("doclet.Enum_Constant_Summary"), + configuration().getText("doclet.enum_constants"))); + } + + public void printSummaryTableHeader(ProgramElementDoc member) { + String[] header = new String[] { + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Enum_Constant"), + configuration().getText("doclet.Description")) + }; + writer.summaryTableHeader(header, "col"); } public void printSummaryAnchor(ClassDoc cd) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java index bd97166b8ab..0f3b1cc0ef3 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/FieldWriterImpl.java @@ -37,6 +37,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Robert Field * @author Atul M Dambalkar * @author Jamie Ho (rewrite) + * @author Bhavesh Patel (Modified) */ public class FieldWriterImpl extends AbstractMemberWriter implements FieldWriter, MemberSummaryWriter { @@ -236,8 +237,24 @@ public class FieldWriterImpl extends AbstractMemberWriter return VisibleMemberMap.FIELDS; } - public void printSummaryLabel(ClassDoc cd) { - writer.strongText("doclet.Field_Summary"); + public void printSummaryLabel() { + writer.printText("doclet.Field_Summary"); + } + + public void printTableSummary() { + writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + configuration().getText("doclet.Field_Summary"), + configuration().getText("doclet.fields"))); + } + + public void printSummaryTableHeader(ProgramElementDoc member) { + String[] header = new String[] { + writer.getModifierTypeHeader(), + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Field"), + configuration().getText("doclet.Description")) + }; + writer.summaryTableHeader(header, "col"); } public void printSummaryAnchor(ClassDoc cd) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java index 689661b2e54..453b8e8e74a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java @@ -236,17 +236,19 @@ public class HtmlDocletWriter extends HtmlDocWriter { configuration.tagletManager.getCustomTags(doc), getTagletWriterInstance(false), output); String outputString = output.toString().trim(); - // For RootDoc and ClassDoc, this section is not the definition description - // but the start of definition list. + // For RootDoc, ClassDoc and PackageDoc, this section is not the + // definition description but the start of definition list. if (!outputString.isEmpty()) { - if (!(doc instanceof RootDoc || doc instanceof ClassDoc)) { + if (!(doc instanceof RootDoc || doc instanceof ClassDoc || + doc instanceof PackageDoc)) { printMemberDetailsListStartTag(); dd(); } printTagsInfoHeader(); print(outputString); printTagsInfoFooter(); - if (!(doc instanceof RootDoc || doc instanceof ClassDoc)) + if (!(doc instanceof RootDoc || doc instanceof ClassDoc || + doc instanceof PackageDoc)) ddEnd(); } } @@ -784,6 +786,15 @@ public class HtmlDocletWriter extends HtmlDocWriter { table(1, "100%", 3, 0); } + /** + * Print the Html table tag for the index summary tables. + * + * @param summary the summary for the table tag summary attribute. + */ + public void tableIndexSummary(String summary) { + table(1, "100%", 3, 0, summary); + } + /** * Same as {@link #tableIndexSummary()}. */ @@ -799,6 +810,40 @@ public class HtmlDocletWriter extends HtmlDocWriter { print(""); } + /** + * Print table caption. + */ + public void tableCaptionStart() { + captionStyle("TableCaption"); + } + + /** + * Print table sub-caption. + */ + public void tableSubCaptionStart() { + captionStyle("TableSubCaption"); + } + + /** + * Print table caption end tags. + */ + public void tableCaptionEnd() { + captionEnd(); + } + + /** + * Print summary table header. + */ + public void summaryTableHeader(String[] header, String scope) { + tr(); + for ( int i=0; i < header.length; i++ ) { + thScopeNoWrap("TableHeader", scope); + print(header[i]); + thEnd(); + } + trEnd(); + } + /** * Prine table header information about color, column span and the font. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java index a74283179b3..c5500a34e4c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java @@ -38,6 +38,7 @@ import com.sun.tools.doclets.internal.toolkit.taglets.*; * @author Robert Field * @author Atul M Dambalkar * @author Jamie Ho (rewrite) + * @author Bhavesh Patel (Modified) */ public class MethodWriterImpl extends AbstractExecutableMemberWriter implements MethodWriter, MemberSummaryWriter { @@ -255,8 +256,24 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter return VisibleMemberMap.METHODS; } - public void printSummaryLabel(ClassDoc cd) { - writer.strongText("doclet.Method_Summary"); + public void printSummaryLabel() { + writer.printText("doclet.Method_Summary"); + } + + public void printTableSummary() { + writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + configuration().getText("doclet.Method_Summary"), + configuration().getText("doclet.methods"))); + } + + public void printSummaryTableHeader(ProgramElementDoc member) { + String[] header = new String[] { + writer.getModifierTypeHeader(), + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Method"), + configuration().getText("doclet.Description")) + }; + writer.summaryTableHeader(header, "col"); } public void printSummaryAnchor(ClassDoc cd) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java index 23803455ad1..c133708c108 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/NestedClassWriterImpl.java @@ -37,6 +37,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * @author Robert Field * @author Atul M Dambalkar * @author Jamie Ho (rewrite) + * @author Bhavesh Patel (Modified) */ public class NestedClassWriterImpl extends AbstractMemberWriter implements MemberSummaryWriter { @@ -147,8 +148,35 @@ public class NestedClassWriterImpl extends AbstractMemberWriter return VisibleMemberMap.INNERCLASSES; } - public void printSummaryLabel(ClassDoc cd) { - writer.strongText("doclet.Nested_Class_Summary"); + public void printSummaryLabel() { + writer.printText("doclet.Nested_Class_Summary"); + } + + public void printTableSummary() { + writer.tableIndexSummary(configuration().getText("doclet.Member_Table_Summary", + configuration().getText("doclet.Nested_Class_Summary"), + configuration().getText("doclet.nested_classes"))); + } + + public void printSummaryTableHeader(ProgramElementDoc member) { + String[] header; + if (member.isInterface()) { + header = new String[] { + writer.getModifierTypeHeader(), + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Interface"), + configuration().getText("doclet.Description")) + }; + } + else { + header = new String[] { + writer.getModifierTypeHeader(), + configuration().getText("doclet.0_and_1", + configuration().getText("doclet.Class"), + configuration().getText("doclet.Description")) + }; + } + writer.summaryTableHeader(header, "col"); } public void printSummaryAnchor(ClassDoc cd) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java index ebc7118ab5d..035c48cfa80 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexFrameWriter.java @@ -114,7 +114,7 @@ public class PackageIndexFrameWriter extends AbstractPackageIndexWriter { * * @param text Text string will not be used in this method. */ - protected void printIndexHeader(String text) { + protected void printIndexHeader(String text, String tableSummary) { printTableHeader(false); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java index 4562e6e9354..b785bf67c42 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java @@ -36,6 +36,7 @@ import java.util.*; * with the "pacakge-summary.html" file for the clicked package. * * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class PackageIndexWriter extends AbstractPackageIndexWriter { @@ -123,7 +124,10 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { List list = groupPackageMap.get(groupname); if (list != null && list.size() > 0) { printIndexContents(list.toArray(new PackageDoc[list.size()]), - groupname); + groupname, + configuration.getText("doclet.Member_Table_Summary", + groupname, + configuration.getText("doclet.packages"))); } } } @@ -149,11 +153,12 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { /** * Print Html tags for the table for this package index. */ - protected void printIndexHeader(String text) { - tableIndexSummary(); - tableHeaderStart("#CCCCFF"); - strong(text); - tableHeaderEnd(); + protected void printIndexHeader(String text, String tableSummary) { + tableIndexSummary(tableSummary); + tableCaptionStart(); + print(text); + tableCaptionEnd(); + summaryTableHeader(packageTableHeader, "col"); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java index a83cc3d70a0..d817ca5ad3b 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageUseWriter.java @@ -34,6 +34,7 @@ import java.util.*; * Generate package usage information. * * @author Robert G. Field + * @author Bhavesh Patel (Modified) */ public class PackageUseWriter extends SubWriterHolderWriter { @@ -131,11 +132,12 @@ public class PackageUseWriter extends SubWriterHolderWriter { } protected void generatePackageList() throws IOException { - tableIndexSummary(); - tableHeaderStart("#CCCCFF"); + tableIndexSummary(useTableSummary); + tableCaptionStart(); printText("doclet.ClassUse_Packages.that.use.0", getPackageLink(pkgdoc, Util.getPackageName(pkgdoc), false)); - tableHeaderEnd(); + tableCaptionEnd(); + summaryTableHeader(packageTableHeader, "col"); Iterator it = usingPackageToUsedClasses.keySet().iterator(); while (it.hasNext()) { PackageDoc pkg = configuration.root.packageNamed(it.next()); @@ -147,6 +149,11 @@ public class PackageUseWriter extends SubWriterHolderWriter { } protected void generateClassList() throws IOException { + String[] classTableHeader = new String[] { + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Class"), + configuration.getText("doclet.Description")) + }; Iterator itp = usingPackageToUsedClasses.keySet().iterator(); while (itp.hasNext()) { String packageName = itp.next(); @@ -154,12 +161,14 @@ public class PackageUseWriter extends SubWriterHolderWriter { if (usingPackage != null) { anchor(usingPackage.name()); } - tableIndexSummary(); - tableHeaderStart("#CCCCFF"); + tableIndexSummary(configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.classes"))); + tableCaptionStart(); printText("doclet.ClassUse_Classes.in.0.used.by.1", getPackageLink(pkgdoc, Util.getPackageName(pkgdoc), false), getPackageLink(usingPackage,Util.getPackageName(usingPackage), false)); - tableHeaderEnd(); + tableCaptionEnd(); + summaryTableHeader(classTableHeader, "col"); Iterator itc = usingPackageToUsedClasses.get(packageName).iterator(); while (itc.hasNext()) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java index eca6d49bbbf..60aa692ce0f 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageWriterImpl.java @@ -38,6 +38,7 @@ import java.util.*; * class-kind will update the frame with the clicked class-kind page. * * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class PackageWriterImpl extends HtmlDocletWriter implements PackageSummaryWriter { @@ -107,14 +108,15 @@ public class PackageWriterImpl extends HtmlDocletWriter /** * {@inheritDoc} */ - public void writeClassesSummary(ClassDoc[] classes, String label) { + public void writeClassesSummary(ClassDoc[] classes, String label, String tableSummary, String[] tableHeader) { if(classes.length > 0) { Arrays.sort(classes); - tableIndexSummary(); + tableIndexSummary(tableSummary); boolean printedHeading = false; for (int i = 0; i < classes.length; i++) { if (!printedHeading) { - printFirstRow(label); + printTableCaption(label); + printFirstRow(tableHeader); printedHeading = true; } if (!Util.isCoreClass(classes[i]) || @@ -148,15 +150,24 @@ public class PackageWriterImpl extends HtmlDocletWriter } } + /** + * Print the table caption for the class-listing. + * + * @param label label for the Class kind listing. + */ + protected void printTableCaption(String label) { + tableCaptionStart(); + print(label); + tableCaptionEnd(); + } + /** * Print the table heading for the class-listing. * - * @param label Label for the Class kind listing. + * @param tableHeader table header string for the Class listing. */ - protected void printFirstRow(String label) { - tableHeaderStart("#CCCCFF"); - strong(label); - tableHeaderEnd(); + protected void printFirstRow(String[] tableHeader) { + summaryTableHeader(tableHeader, "col"); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java index 1384bbb2bd5..f6664f94c1c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/StylesheetWriter.java @@ -33,6 +33,7 @@ import java.io.*; * Writes the style sheet for the doclet output. * * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class StylesheetWriter extends HtmlDocletWriter { @@ -115,6 +116,13 @@ public class StylesheetWriter extends HtmlDocletWriter { println("background-color:#FFFFFF; color:#000000}"); print(".NavBarCell3 { font-family: Arial, Helvetica, sans-serif; "); println("background-color:#FFFFFF; color:#000000}"); + + print("/* "); printText("doclet.Style_line_12"); println(" */"); + print(".TableCaption { background: #CCCCFF; color:#000000; text-align: left; font-size: 150%; font-weight: bold; border-left: 2px ridge; border-right: 2px ridge; border-top: 2px ridge; padding-left: 5px; }"); + print(" /* "); printText("doclet.Style_line_5"); println(" */"); + print(".TableSubCaption { background: #EEEEFF; color:#000000; text-align: left; font-weight: bold; border-left: 2px ridge; border-right: 2px ridge; border-top: 2px ridge; padding-left: 5px; }"); + print(" /* "); printText("doclet.Style_line_6"); println(" */"); + print(".TableHeader { text-align: center; font-size: 80%; font-weight: bold; }"); println(""); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java index f6b6b98b6e5..b1a2f868687 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SubWriterHolderWriter.java @@ -43,6 +43,7 @@ import java.io.*; * * @author Robert Field * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { @@ -72,10 +73,11 @@ public abstract class SubWriterHolderWriter extends HtmlDocletWriter { public void printSummaryHeader(AbstractMemberWriter mw, ClassDoc cd) { mw.printSummaryAnchor(cd); - tableIndexSummary(); - tableHeaderStart("#CCCCFF"); - mw.printSummaryLabel(cd); - tableHeaderEnd(); + mw.printTableSummary(); + tableCaptionStart(); + mw.printSummaryLabel(); + tableCaptionEnd(); + mw.printSummaryTableHeader(cd); } public void printTableHeadingBackground(String str) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 4df4f5d6a0e..cad683d9fa4 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java @@ -37,6 +37,7 @@ import com.sun.tools.doclets.internal.toolkit.util.*; * * @since 1.2 * @author Atul M Dambalkar + * @author Bhavesh Patel (Modified) */ public class HtmlWriter extends PrintWriter { @@ -66,6 +67,21 @@ public class HtmlWriter extends PrintWriter { */ protected boolean memberDetailsListPrinted; + /** + * Header for tables displaying packages and description.. + */ + protected final String[] packageTableHeader; + + /** + * Summary for use tables displaying class and package use. + */ + protected final String useTableSummary; + + /** + * Column header for class docs displaying Modifier and Type header. + */ + protected final String modifierTypeHeader; + /** * Constructor. * @@ -86,6 +102,15 @@ public class HtmlWriter extends PrintWriter { this.configuration = configuration; htmlFilename = filename; this.memberDetailsListPrinted = false; + packageTableHeader = new String[] { + configuration.getText("doclet.Package"), + configuration.getText("doclet.Description") + }; + useTableSummary = configuration.getText("doclet.Use_Table_Summary", + configuration.getText("doclet.packages")); + modifierTypeHeader = configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Modifier"), + configuration.getText("doclet.Type")); } /** @@ -802,6 +827,26 @@ public class HtmlWriter extends PrintWriter { "\" SUMMARY=\"\">"); } + /** + * Print HTML <TABLE BORDER="border" WIDTH="width" + * CELLPADDING="cellpadding" CELLSPACING="cellspacing" SUMMARY="summary"> tag. + * + * @param border Border size. + * @param width Width of the table. + * @param cellpadding Cellpadding for the table cells. + * @param cellspacing Cellspacing for the table cells. + * @param summary Table summary. + */ + public void table(int border, String width, int cellpadding, + int cellspacing, String summary) { + println(DocletConstants.NL + + ""); + } + /** * Print HTML <TABLE BORDER="border" CELLPADDING="cellpadding" * CELLSPACING="cellspacing"> tag. @@ -818,6 +863,23 @@ public class HtmlWriter extends PrintWriter { "\" SUMMARY=\"\">"); } + /** + * Print HTML <TABLE BORDER="border" CELLPADDING="cellpadding" + * CELLSPACING="cellspacing" SUMMARY="summary"> tag. + * + * @param border Border size. + * @param cellpadding Cellpadding for the table cells. + * @param cellspacing Cellspacing for the table cells. + * @param summary Table summary. + */ + public void table(int border, int cellpadding, int cellspacing, String summary) { + println(DocletConstants.NL + + "
    "); + } + /** * Print HTML <TABLE BORDER="border" WIDTH="width"> * @@ -912,6 +974,23 @@ public class HtmlWriter extends PrintWriter { println("-->"); } + /** + * Print <CAPTION CLASS="stylename"> tag. Adds a newline character + * at the end. + * + * @param stylename style to be applied. + */ + public void captionStyle(String stylename) { + println(""); + } + /** * Print <TR BGCOLOR="color" CLASS="stylename"> tag. Adds a newline character * at the end. @@ -952,6 +1031,23 @@ public class HtmlWriter extends PrintWriter { print("" + "" + NL + "" }, // Class documentation {BUG_ID + FS + "pkg1" + FS + "C1.html", - "" + "" + NL + "" }, {BUG_ID + FS + "pkg1" + FS + "C1.html", "" @@ -62,29 +64,32 @@ public class TestHeadings extends JavadocTester { // Class use documentation {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", - "" + "" + NL + "" }, {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", "" }, {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", - "" + "" + NL + "" }, // Deprecated {BUG_ID + FS + "deprecated-list.html", - "" + "" }, // Constant values {BUG_ID + FS + "constant-values.html", - "" - }, - {BUG_ID + FS + "constant-values.html", - "" + "" + NL + "" + NL + + "" }, // Serialized Form diff --git a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java index 5fa8db63ca5..652de517cb5 100644 --- a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java +++ b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/TestHtmlDefinitionListTag.java @@ -25,7 +25,7 @@ /* * @test - * @bug 6786690 + * @bug 6786690 6820360 * @summary This test verifies the nesting of definition list tags. * @author Bhavesh Patel * @library ../lib/ @@ -36,7 +36,7 @@ public class TestHtmlDefinitionListTag extends JavadocTester { - private static final String BUG_ID = "6786690"; + private static final String BUG_ID = "6786690-6820360"; // Test common to all runs of javadoc. The class signature should print // properly enclosed definition list tags and the Annotation Type @@ -55,6 +55,9 @@ public class TestHtmlDefinitionListTag extends JavadocTester { // serialized form should have properly nested definition list tags // enclosing comments, tags and deprecated information. private static final String[][] TEST_CMNT_DEPR = { + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", "
    " + NL + + "
    Since:
    " + NL + + "
    JDK1.0
    "}, {BUG_ID + FS + "pkg1" + FS + "C1.html", "
    " + NL + "
    Since:
    " + NL + "
    JDK1.0
    " + NL + "
    See Also:
    " + @@ -193,6 +196,9 @@ public class TestHtmlDefinitionListTag extends JavadocTester { // should display properly nested definition list tags for comments, tags // and deprecated information. private static final String[][] TEST_NODEPR = { + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", "
    " + NL + + "
    Since:
    " + NL + + "
    JDK1.0
    "}, {BUG_ID + FS + "pkg1" + FS + "C1.html", "
    " + NL + "
    Since:
    " + NL + "
    JDK1.0
    " + NL + "
    See Also:
    " + @@ -302,6 +308,8 @@ public class TestHtmlDefinitionListTag extends JavadocTester { // Test for valid HTML generation which should not comprise of empty // definition list tags. private static final String[][] NEGATED_TEST = { + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", "
    "}, + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", "
    " + NL + "
    "}, {BUG_ID + FS + "pkg1" + FS + "C1.html", "
    "}, {BUG_ID + FS + "pkg1" + FS + "C1.html", "
    " + NL + "
    "}, {BUG_ID + FS + "pkg1" + FS + "C1.ModalExclusionType.html", "
    "}, diff --git a/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/pkg1/package-info.java b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/pkg1/package-info.java new file mode 100644 index 00000000000..201ea4b6199 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlDefinitionListTag/pkg1/package-info.java @@ -0,0 +1,29 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Test package 1. + * + * @since JDK1.0 + */ +package pkg1; diff --git a/langtools/test/com/sun/javadoc/testHtmlStrongTag/TestHtmlStrongTag.java b/langtools/test/com/sun/javadoc/testHtmlStrongTag/TestHtmlStrongTag.java index 3bb26e83992..c1445255c42 100644 --- a/langtools/test/com/sun/javadoc/testHtmlStrongTag/TestHtmlStrongTag.java +++ b/langtools/test/com/sun/javadoc/testHtmlStrongTag/TestHtmlStrongTag.java @@ -38,14 +38,15 @@ public class TestHtmlStrongTag extends JavadocTester { private static final String BUG_ID = "6786028"; private static final String[][] TEST1 = { - {BUG_ID + FS + "pkg1" + FS + "C1.html", "Method Summary"}, - {BUG_ID + FS + "pkg1" + FS + "C1.html", "See Also:"}, - {BUG_ID + FS + "pkg1" + FS + "package-summary.html", "Class Summary"}}; + {BUG_ID + FS + "pkg1" + FS + "C1.html", "See Also:"}}; private static final String[][] NEGATED_TEST1 = { - {BUG_ID + FS + "pkg1" + FS + "C1.html", ""}}; + {BUG_ID + FS + "pkg1" + FS + "C1.html", "Method Summary"}, + {BUG_ID + FS + "pkg1" + FS + "C1.html", ""}, + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", "Class Summary"}}; private static final String[][] TEST2 = { + {BUG_ID + FS + "pkg2" + FS + "C2.html", "Comments:"}}; + private static final String[][] NEGATED_TEST2 = { {BUG_ID + FS + "pkg2" + FS + "C2.html", "Method Summary"}, - {BUG_ID + FS + "pkg2" + FS + "C2.html", "Comments:"}, {BUG_ID + FS + "pkg1" + FS + "package-summary.html", "Class Summary"}}; private static final String[] ARGS1 = @@ -62,7 +63,7 @@ public class TestHtmlStrongTag extends JavadocTester { public static void main(String[] args) { TestHtmlStrongTag tester = new TestHtmlStrongTag(); run(tester, ARGS1, TEST1, NEGATED_TEST1); - run(tester, ARGS2, TEST2, NO_TEST); + run(tester, ARGS2, TEST2, NEGATED_TEST2); tester.printSummary(); } diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/TestHtmlTableTags.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/TestHtmlTableTags.java new file mode 100644 index 00000000000..f08ff5783d1 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/TestHtmlTableTags.java @@ -0,0 +1,478 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6786688 + * @summary HTML tables should have table summary, caption and table headers. + * @author Bhavesh Patel + * @library ../lib/ + * @build JavadocTester + * @build TestHtmlTableTags + * @run main TestHtmlTableTags + */ + +public class TestHtmlTableTags extends JavadocTester { + + //Test information. + private static final String BUG_ID = "6786688"; + + //Javadoc arguments. + private static final String[] ARGS = new String[] { + "-d", BUG_ID, "-sourcepath", SRC_DIR, "-use", "pkg1", "pkg2" + }; + + //Input for string tests for HTML table tags. + private static final String[][] TABLE_TAGS_TEST = { + /* + * Test for validating summary for HTML tables + */ + + //Package summary + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", + "
    "); + } + + /** + * Print </CAPTION> tag. Add a newline character at the end. + */ + public void captionEnd() { + println("
    "); } + /** + * Print <TH CLASS="stylename" SCOPE="scope" NOWRAP> tag. + * + * @param stylename style to be applied. + * @param scope the scope attribute. + */ + public void thScopeNoWrap(String stylename, String scope) { + print(""); + } + + /* + * Returns a header for Modifier and Type column of a table. + */ + public String getModifierTypeHeader() { + return modifierTypeHeader; + } + /** * Print <TH align="align" COLSPAN=i> tag. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties index 492a77e7fcc..f4d86e3d5d8 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties @@ -83,6 +83,17 @@ doclet.Deprecated_Constructors=Deprecated Constructors doclet.Deprecated_Methods=Deprecated Methods doclet.Deprecated_Enum_Constants=Deprecated Enum Constants doclet.Deprecated_Annotation_Type_Members=Deprecated Annotation Type Elements +doclet.deprecated_classes=deprecated classes +doclet.deprecated_enums=deprecated enums +doclet.deprecated_interfaces=deprecated interfaces +doclet.deprecated_exceptions=deprecated exceptions +doclet.deprecated_annotation_types=deprecated annotation types +doclet.deprecated_errors=deprecated errors +doclet.deprecated_fields=deprecated fields +doclet.deprecated_constructors=deprecated constructors +doclet.deprecated_methods=deprecated methods +doclet.deprecated_enum_constants=deprecated enum constants +doclet.deprecated_annotation_type_members=deprecated annotation type elements doclet.Frame_Output=Frame Output doclet.Docs_generated_by_Javadoc=Documentation generated by Javadoc. doclet.Generated_Docs_Untitled=Generated Documentation (Untitled) @@ -171,6 +182,7 @@ doclet.Style_line_8=Font used in left-hand frame lists doclet.Style_line_9=Example of smaller, sans-serif font in frames doclet.Style_line_10=Navigation bar fonts and colors doclet.Style_line_11=Dark Blue +doclet.Style_line_12=Table caption style doclet.ClassUse_Packages.that.use.0=Packages that use {0} doclet.ClassUse_Uses.of.0.in.1=Uses of {0} in {1} doclet.ClassUse_Classes.in.0.used.by.1=Classes in {0} used by {1} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java index eb86fbea2d9..d46807d02e4 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/PackageSummaryWriter.java @@ -64,7 +64,7 @@ public interface PackageSummaryWriter { * @param classes the array of classes to document. * @param label the label for this table. */ - public abstract void writeClassesSummary(ClassDoc[] classes, String label); + public abstract void writeClassesSummary(ClassDoc[] classes, String label, String tableSummary, String[] tableHeader); /** * Write the header for the summary. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java index c85b0b30b8d..ac25c257739 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/PackageSummaryBuilder.java @@ -40,6 +40,7 @@ import java.lang.reflect.*; * Do not use it as an API * * @author Jamie Ho + * @author Bhavesh Patel (Modified) * @since 1.5 */ public class PackageSummaryBuilder extends AbstractBuilder { @@ -184,7 +185,15 @@ public class PackageSummaryBuilder extends AbstractBuilder { * Build the summary for the classes in this package. */ public void buildClassSummary() { - ClassDoc[] classes = + String classTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Class_Summary"), + configuration.getText("doclet.classes")); + String[] classTableHeader = new String[] { + configuration.getText("doclet.Class"), + configuration.getText("doclet.Description") + }; + ClassDoc[] classes = packageDoc.isIncluded() ? packageDoc.ordinaryClasses() : configuration.classDocCatalog.ordinaryClasses( @@ -192,7 +201,8 @@ public class PackageSummaryBuilder extends AbstractBuilder { if (classes.length > 0) { packageWriter.writeClassesSummary( classes, - configuration.getText("doclet.Class_Summary")); + configuration.getText("doclet.Class_Summary"), + classTableSummary, classTableHeader); } } @@ -200,7 +210,15 @@ public class PackageSummaryBuilder extends AbstractBuilder { * Build the summary for the interfaces in this package. */ public void buildInterfaceSummary() { - ClassDoc[] interfaces = + String interfaceTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Interface_Summary"), + configuration.getText("doclet.interfaces")); + String[] interfaceTableHeader = new String[] { + configuration.getText("doclet.Interface"), + configuration.getText("doclet.Description") + }; + ClassDoc[] interfaces = packageDoc.isIncluded() ? packageDoc.interfaces() : configuration.classDocCatalog.interfaces( @@ -208,7 +226,8 @@ public class PackageSummaryBuilder extends AbstractBuilder { if (interfaces.length > 0) { packageWriter.writeClassesSummary( interfaces, - configuration.getText("doclet.Interface_Summary")); + configuration.getText("doclet.Interface_Summary"), + interfaceTableSummary, interfaceTableHeader); } } @@ -216,7 +235,15 @@ public class PackageSummaryBuilder extends AbstractBuilder { * Build the summary for the enums in this package. */ public void buildAnnotationTypeSummary() { - ClassDoc[] annotationTypes = + String annotationtypeTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Annotation_Types_Summary"), + configuration.getText("doclet.annotationtypes")); + String[] annotationtypeTableHeader = new String[] { + configuration.getText("doclet.AnnotationType"), + configuration.getText("doclet.Description") + }; + ClassDoc[] annotationTypes = packageDoc.isIncluded() ? packageDoc.annotationTypes() : configuration.classDocCatalog.annotationTypes( @@ -224,7 +251,8 @@ public class PackageSummaryBuilder extends AbstractBuilder { if (annotationTypes.length > 0) { packageWriter.writeClassesSummary( annotationTypes, - configuration.getText("doclet.Annotation_Types_Summary")); + configuration.getText("doclet.Annotation_Types_Summary"), + annotationtypeTableSummary, annotationtypeTableHeader); } } @@ -232,7 +260,15 @@ public class PackageSummaryBuilder extends AbstractBuilder { * Build the summary for the enums in this package. */ public void buildEnumSummary() { - ClassDoc[] enums = + String enumTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Enum_Summary"), + configuration.getText("doclet.enums")); + String[] enumTableHeader = new String[] { + configuration.getText("doclet.Enum"), + configuration.getText("doclet.Description") + }; + ClassDoc[] enums = packageDoc.isIncluded() ? packageDoc.enums() : configuration.classDocCatalog.enums( @@ -240,7 +276,8 @@ public class PackageSummaryBuilder extends AbstractBuilder { if (enums.length > 0) { packageWriter.writeClassesSummary( enums, - configuration.getText("doclet.Enum_Summary")); + configuration.getText("doclet.Enum_Summary"), + enumTableSummary, enumTableHeader); } } @@ -248,7 +285,15 @@ public class PackageSummaryBuilder extends AbstractBuilder { * Build the summary for the exceptions in this package. */ public void buildExceptionSummary() { - ClassDoc[] exceptions = + String exceptionTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Exception_Summary"), + configuration.getText("doclet.exceptions")); + String[] exceptionTableHeader = new String[] { + configuration.getText("doclet.Exception"), + configuration.getText("doclet.Description") + }; + ClassDoc[] exceptions = packageDoc.isIncluded() ? packageDoc.exceptions() : configuration.classDocCatalog.exceptions( @@ -256,7 +301,8 @@ public class PackageSummaryBuilder extends AbstractBuilder { if (exceptions.length > 0) { packageWriter.writeClassesSummary( exceptions, - configuration.getText("doclet.Exception_Summary")); + configuration.getText("doclet.Exception_Summary"), + exceptionTableSummary, exceptionTableHeader); } } @@ -264,7 +310,15 @@ public class PackageSummaryBuilder extends AbstractBuilder { * Build the summary for the errors in this package. */ public void buildErrorSummary() { - ClassDoc[] errors = + String errorTableSummary = + configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Error_Summary"), + configuration.getText("doclet.errors")); + String[] errorTableHeader = new String[] { + configuration.getText("doclet.Error"), + configuration.getText("doclet.Description") + }; + ClassDoc[] errors = packageDoc.isIncluded() ? packageDoc.errors() : configuration.classDocCatalog.errors( @@ -272,7 +326,8 @@ public class PackageSummaryBuilder extends AbstractBuilder { if (errors.length > 0) { packageWriter.writeClassesSummary( errors, - configuration.getText("doclet.Error_Summary")); + configuration.getText("doclet.Error_Summary"), + errorTableSummary, errorTableHeader); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties index 57382de9ab2..371bdf596f1 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties @@ -82,6 +82,7 @@ doclet.Exceptions=Exceptions doclet.Errors=Errors doclet.Classes=Classes doclet.Packages=Packages +doclet.packages=packages doclet.All_Classes=All Classes doclet.All_Superinterfaces=All Superinterfaces: doclet.All_Implemented_Interfaces=All Implemented Interfaces: @@ -92,14 +93,20 @@ doclet.Interface=Interface doclet.Class=Class doclet.AnnotationType=Annotation Type doclet.annotationtype=annotation type +doclet.annotationtypes=annotation types doclet.Enum=Enum doclet.enum=enum +doclet.enums=enums doclet.interface=interface +doclet.interfaces=interfaces doclet.class=class +doclet.classes=classes doclet.Error=Error doclet.error=error +doclet.errors=errors doclet.Exception=Exception doclet.exception=exception +doclet.exceptions=exceptions doclet.extended_by=extended by doclet.extends=extends doclet.Package_private=(package private) @@ -125,6 +132,32 @@ doclet.value_tag_invalid_reference={0} (referenced by @value tag) is an unknown doclet.value_tag_invalid_constant=@value tag (which references {0}) can only be used in constants. doclet.dest_dir_create=Creating destination directory: "{0}" doclet.in={0} in {1} +doclet.Use_Table_Summary=Use table, listing {0}, and an explanation +doclet.Constants_Table_Summary={0} table, listing constant fields, and values +doclet.Member_Table_Summary={0} table, listing {1}, and an explanation +doclet.fields=fields +doclet.constructors=constructors +doclet.methods=methods +doclet.annotation_type_optional_members=optional elements +doclet.annotation_type_required_members=required elements +doclet.enum_constants=enum constants +doclet.nested_classes=nested classes +doclet.subclasses=subclasses +doclet.subinterfaces=subinterfaces +doclet.Modifier=Modifier +doclet.Type=Type +doclet.Field=Field +doclet.Constructor=Constructor +doclet.Method=Method +doclet.Annotation_Type_Optional_Member=Optional Element +doclet.Annotation_Type_Required_Member=Required Element +doclet.Annotation_Type_Member=Annotation Type Element +doclet.Enum_Constant=Enum Constant +doclet.Class=Class +doclet.Description=Description +doclet.ConstantField=Constant Field +doclet.Value=Value +doclet.0_and_1={0} and {1} #Documentation for Enums doclet.enum_values_doc=\n\ diff --git a/langtools/test/com/sun/javadoc/testHeadings/TestHeadings.java b/langtools/test/com/sun/javadoc/testHeadings/TestHeadings.java index 1ed62c535db..eb82d715b91 100644 --- a/langtools/test/com/sun/javadoc/testHeadings/TestHeadings.java +++ b/langtools/test/com/sun/javadoc/testHeadings/TestHeadings.java @@ -47,14 +47,16 @@ public class TestHeadings extends JavadocTester { private static final String[][] TEST = { //Package summary {BUG_ID + FS + "pkg1" + FS + "package-summary.html", - "" + NL + - "Class Summary" + + "ClassDescription" + NL + - "Field Summary" + + "Modifier and TypeField and DescriptionMethods inherited from class " + "java.lang.Object" + NL + - "Packages that use C1" + + "PackageDescription" + NL + "Uses of C1 in " + "pkg2Fields in " + "pkg2 " + "declared as C1" + + "Modifier and TypeField and Description" + NL + - "Deprecated Methods" + + "Method and Descriptionpkg1.C1pkg1.C1" + + "Modifier and TypeConstant FieldValue
    " + }, + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "package-summary.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "package-summary.html", + "
    " + }, + // Class documentation + {BUG_ID + FS + "pkg1" + FS + "C1.html", + "
    " + }, + {BUG_ID + FS + "pkg1" + FS + "C1.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "C2.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "C2.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "C2.ModalExclusionType.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "C3.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "C4.html", + "
    " + }, + // Class use documentation + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "I1.html", + "
    " + }, + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "
    " + }, + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.ModalExclusionType.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.ModalExclusionType.html", + "
    " + }, + // Package use documentation + {BUG_ID + FS + "pkg1" + FS + "package-use.html", + "
    " + }, + {BUG_ID + FS + "pkg1" + FS + "package-use.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "package-use.html", + "
    " + }, + {BUG_ID + FS + "pkg2" + FS + "package-use.html", + "
    " + }, + // Deprecated + {BUG_ID + FS + "deprecated-list.html", + "
    " + }, + {BUG_ID + FS + "deprecated-list.html", + "
    " + }, + // Constant values + {BUG_ID + FS + "constant-values.html", + "
    " + }, + // Overview Summary + {BUG_ID + FS + "overview-summary.html", + "
    " + }, + + /* + * Test for validating caption for HTML tables + */ + + //Package summary + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", + "" + }, + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-summary.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-summary.html", + "" + }, + // Class documentation + {BUG_ID + FS + "pkg1" + FS + "C1.html", + "" + }, + {BUG_ID + FS + "pkg1" + FS + "C1.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C2.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C2.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C2.ModalExclusionType.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C3.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C4.html", + "" + }, + // Class use documentation + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "I1.html", + "" + }, + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "" + }, + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.ModalExclusionType.html", + "" + }, + // Package use documentation + {BUG_ID + FS + "pkg1" + FS + "package-use.html", + "" + }, + {BUG_ID + FS + "pkg1" + FS + "package-use.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-use.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-use.html", + "" + }, + // Deprecated + {BUG_ID + FS + "deprecated-list.html", + "" + }, + {BUG_ID + FS + "deprecated-list.html", + "" + }, + // Constant values + {BUG_ID + FS + "constant-values.html", + "" + }, + // Overview Summary + {BUG_ID + FS + "overview-summary.html", + "" + }, + + /* + * Test for validating headers for HTML tables + */ + + //Package summary + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-summary.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-summary.html", + "" + NL + "" + }, + // Class documentation + {BUG_ID + FS + "pkg1" + FS + "C1.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg1" + FS + "C1.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C2.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C2.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C2.ModalExclusionType.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C3.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "C4.html", + "" + NL + "" + }, + // Class use documentation + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "I1.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg1" + FS + "class-use" + FS + "C1.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.ModalExclusionType.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "C2.ModalExclusionType.html", + "" + NL + "" + }, + // Package use documentation + {BUG_ID + FS + "pkg1" + FS + "package-use.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg1" + FS + "package-use.html", + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-use.html", + "" + NL + "" + }, + {BUG_ID + FS + "pkg2" + FS + "package-use.html", + "" + }, + // Deprecated + {BUG_ID + FS + "deprecated-list.html", + "" + }, + {BUG_ID + FS + "deprecated-list.html", + "" + }, + // Constant values + {BUG_ID + FS + "constant-values.html", + "" + NL + "" + NL + + "" + }, + // Overview Summary + {BUG_ID + FS + "overview-summary.html", + "" + NL + "" + } + }; + private static final String[][] NEGATED_TEST = NO_TEST; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestHtmlTableTags tester = new TestHtmlTableTags(); + run(tester, ARGS, TABLE_TAGS_TEST, NEGATED_TEST); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/C1.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/C1.java new file mode 100644 index 00000000000..5f38d4f1f29 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/C1.java @@ -0,0 +1,81 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg1; + +import pkg2.*; + +/** + * A test class. + * + * @author Bhavesh Patel + */ +public class C1 implements I1 { + + /** + * Test field for class. + */ + public C2 field; + + /** + * Constant value. + */ + public static final String CONSTANT1 = "C1"; + + /** + * A test constructor. + */ + C1() { + } + + /** + * Method thats does some processing. + * + * @param param some parameter that is passed. + * @return a sample object. + */ + public C2 method(C2 param) { + return param; + } + + /** + * Method that is implemented. + * + * @param a some random value. + * @param b some random value. + */ + public void method1(int a, int b) { + } + + /** + * Another inherited method. + * @param c some value. + */ + public void method2(int c) { + } + + /** + * @deprecated don't use this anymore. + */ + public void deprecatedMethod() {} +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/I1.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/I1.java new file mode 100644 index 00000000000..509417825ac --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/I1.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg1; + +/** + * A sample interface used to test table tags. + * + * @author Bhavesh Patel + */ +public interface I1 { + + /** + * A test method. + * + * @param a blah. + * @param b blah. + */ + void method1(int a, int b); + + /** + * Another test method. + * + * @param c blah. + */ + void method2(int c); + +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/package-info.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/package-info.java new file mode 100644 index 00000000000..024483be5a7 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg1/package-info.java @@ -0,0 +1,27 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Test package 1 used to test table tags. + */ +package pkg1; diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C2.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C2.java new file mode 100644 index 00000000000..07992e2bad1 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C2.java @@ -0,0 +1,73 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg2; + +import pkg1.*; + +/** + * Another test class. + * + * @author Bhavesh Patel + */ +public class C2 { + + /** + * A test field. + */ + public C1 field; + + /** + * @deprecated don't use this field anymore. + */ + public C1 dep_field; + + /** + * A sample enum. + */ + public static enum ModalExclusionType { + /** + * Test comment. + */ + NO_EXCLUDE, + /** + * Another comment. + */ + APPLICATION_EXCLUDE + }; + + /** + * A string constant. + */ + public static final String CONSTANT1 = "C2"; + + /** + * A sample method. + * + * @param param some parameter. + * @return a test object. + */ + public C1 method(C1 param) { + return param; + } +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C3.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C3.java new file mode 100644 index 00000000000..e410266b6a5 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C3.java @@ -0,0 +1,40 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg2; + +import java.lang.annotation.*; + +/** + * Test Annotation class. + * + * @author Bhavesh Patel + */ +public @interface C3 { + /** + * Comment. + */ + String[] value(); +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C4.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C4.java new file mode 100644 index 00000000000..7eec427be53 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/C4.java @@ -0,0 +1,35 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg2; + +import java.lang.annotation.*; + +/* + * A sample interface. + */ +public @interface C4 { + boolean value() default true; +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/package-info.java b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/package-info.java new file mode 100644 index 00000000000..a1523b14326 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTableTags/pkg2/package-info.java @@ -0,0 +1,27 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Test package 2 used to test table tags. + */ +package pkg2; diff --git a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java index 17eac18887a..5a5fb82b399 100644 --- a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -58,7 +58,8 @@ public class TestNewLanguageFeatures extends JavadocTester { "Coin>" }, //Check for enum constant section - {BUG_ID + FS + "pkg" + FS + "Coin.html", "Enum Constant Summary"}, + {BUG_ID + FS + "pkg" + FS + "Coin.html", ""}, //Detail for enum constant {BUG_ID + FS + "pkg" + FS + "Coin.html", "Dime"}, @@ -158,9 +159,11 @@ public class TestNewLanguageFeatures extends JavadocTester { "public @interface AnnotationType"}, //Make sure member summary headings are correct. {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", - "Required Element Summary"}, + ""}, {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", - "Optional Element Summary"}, + ""}, //Make sure element detail heading is correct {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", "Element Detail"}, @@ -286,39 +289,57 @@ public class TestNewLanguageFeatures extends JavadocTester { //ClassUseTest1: {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo.html", - "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo.html", "ParamTest<Foo>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", - "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", "ParamTest<Foo>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo2.html", - "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo2.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo2.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", "ParamTest<Foo>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", - "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", "<T extends ParamTest<Foo3>>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo3.html", - "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo3.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo3.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo3.html", "<T extends ParamTest<Foo3>>" @@ -371,38 +414,61 @@ public class TestNewLanguageFeatures extends JavadocTester { //ClassUseTest3: >> {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest2.html", - "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest2.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest2.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest2.html", "<T extends ParamTest2<java.util.List<? extends Foo4>>>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", - "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", "" + "" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", "<T extends ParamTest2<java.util.List<? extends Foo4>>>" @@ -410,81 +476,147 @@ public class TestNewLanguageFeatures extends JavadocTester { //Type parameters in constructor and method args {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", - "" + NL + - "" + NL + - "" + NL + - "" + NL + - "" + NL + + "" + NL + "" + NL + "" + NL + + "" + NL + + "" + NL + + "" + NL + + "" + NL + - "" + NL + - "" + NL + - "" + NL + + "" + NL + "" + NL + "" + NL + + "" + NL + + "" + NL + - "" + NL + - "" + "Packages with annotations of type " + + "AnnotationType" + NL + + "" + NL + "" + NL + "" + NL + "" + NL + + "" + NL + + "" }, {BUG_ID + FS + "pkg" + FS + "class-use" + FS + "AnnotationType.html", - "Classes in pkg with annotations of type AnnotationType" + NL + - "" + NL + - "" + NL + - "" + NL + - "" + NL + "" + NL + "" + NL + + "" + NL + + "" + NL + + "" + NL + + "" + NL + - "" + NL + - "" + NL + - "" + NL + "" + NL + "" + NL + + "" + NL + + "" + NL + + "" + NL + + "" + NL + - "" + NL + - "" + NL + - "" + NL + "" + NL + "" + NL + + "" + NL + + "" + NL + + "" + NL + + "" + NL + - "" + NL + - "" + NL + - "" + NL + "" + NL + "" + NL + + "" + NL + + "" + NL + + "" + NL + + "" + NL + - "" + NL + - "" + NL + "" + NL + "" + NL + + "" + NL + + "" + NL + - "" + NL + - "" + NL + "" + NL + "" + NL + + "" + NL + + ""} }; private static final String[][] NEGATED_TEST = NO_TEST; diff --git a/langtools/test/tools/javap/T4884240.java b/langtools/test/tools/javap/T4884240.java index 93d4cc9361c..f2f36167760 100644 --- a/langtools/test/tools/javap/T4884240.java +++ b/langtools/test/tools/javap/T4884240.java @@ -16,7 +16,7 @@ * * 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-15301 USA. + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or
    " + NL + + "Class Summary" + NL + + "Interface Summary" + NL + + "Enum Summary" + NL + + "Annotation Types Summary" + NL + + "Field Summary" + NL + + "Method Summary" + NL + + "Nested Class Summary" + NL + + "Constructor Summary" + NL + + "Enum Constant Summary" + NL + + "Required Element Summary" + NL + + "Optional Element Summary" + NL + + "Packages that use I1" + NL + + "Fields in pkg2 " + + "declared as " + + "C1" + NL + + "Methods in pkg2 " + + "with parameters of type C1" + NL + + "Fields in pkg1 " + + "declared as " + + "C2" + NL + + "Methods in pkg1 " + + "with parameters of type C2" + NL + + "Methods in pkg2 " + + "that return C2.ModalExclusionType" + NL + + "Packages that use " + + "pkg1" + NL + + "Classes in pkg1 " + + "used by pkg1" + NL + + "Packages that use " + + "pkg2" + NL + + "Classes in pkg2 " + + "used by pkg1" + NL + + "Deprecated Fields" + NL + + "Deprecated Methods" + NL + + "pkg1.C1" + NL + + "Packages
    " + + "ClassDescription" + + "InterfaceDescription" + + "EnumDescription" + + "Annotation TypeDescription" + + "Modifier and TypeField and Description" + + "Modifier and TypeMethod and Description" + + "Modifier and TypeClass and Description" + + "Constructor and Description" + + "Enum Constant and Description" + + "Modifier and TypeRequired Element and Description" + + "Modifier and TypeOptional Element and Description" + + "PackageDescription" + + "Modifier and TypeField and Description" + + "Modifier and TypeMethod and Description" + + "Modifier and TypeField and Description" + + "Modifier and TypeMethod and Description" + + "PackageDescription" + + "Modifier and TypeMethod and Description" + + "PackageDescription" + + "Class and Description" + + "PackageDescription" + + "Class and Description" + + "Field and Description" + + "Method and Description" + + "Modifier and TypeConstant FieldValue" + + "PackageDescription
    " + NL + + "Enum Constant Summary" + NL + + "Required Element Summary" + NL + + "Optional Element Summary
    Classes in pkg2 with type parameters of type Foo
    " + NL + + "Classes in pkg2" + + " with type parameters of type Foo
    ClassUseTest1<T extends Foo & Foo2>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo.html", - "Methods in pkg2 with type parameters of type Foo
    " + NL + + "Methods in pkg2" + + " with type parameters of type Foo
    ClassUseTest1.method(T t)" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo.html", - "Fields in pkg2 with type parameters of type Foo
    " + NL + + "Fields in pkg2" + + " with type parameters of type Foo
    Fields in pkg2 declared as ParamTest
    " + NL + + "Fields in pkg2" + + " declared as ParamTest
    Classes in pkg2 with type parameters of type Foo2
    " + NL + + "Classes in pkg2" + + " with type parameters of type Foo2
    ClassUseTest1<T extends Foo & Foo2>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo2.html", - "Methods in pkg2 with type parameters of type Foo2
    " + NL + + "Methods in pkg2" + + " with type parameters of type Foo2
    ClassUseTest1.method(T t)" @@ -326,44 +347,66 @@ public class TestNewLanguageFeatures extends JavadocTester { //ClassUseTest2: > {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", - "Classes in pkg2 with type parameters of type ParamTest
    " + NL + + "Classes in pkg2" + + " with type parameters of type ParamTest
    ClassUseTest2<T extends ParamTest<Foo3>>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", - "Methods in pkg2 with type parameters of type ParamTest
    " + NL + + "Methods in pkg2" + + " with type parameters of type ParamTest
    ClassUseTest2.method(T t)" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest.html", - "Fields in pkg2 declared as ParamTest
    " + NL + + "Fields in pkg2" + + " declared as ParamTest
    Methods in pkg2 with type parameters of type ParamTest
    " + NL + + "Methods in pkg2" + + " with type parameters of type ParamTest
    Classes in pkg2 with type parameters of type Foo3
    " + NL + + "Classes in pkg2" + + " with type parameters of type Foo3
    ClassUseTest2<T extends ParamTest<Foo3>>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo3.html", - "Methods in pkg2 with type parameters of type Foo3
    " + NL + + "Methods in pkg2" + + " with type parameters of type Foo3
    ClassUseTest2.method(T t)" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo3.html", - "Methods in pkg2 that return types with arguments of type Foo3
    " + NL + + "Methods in pkg2" + + " that return types with arguments of type " + + "" + + "Foo3
    Classes in pkg2 with type parameters of type ParamTest2
    " + NL + + "Classes in pkg2" + + " with type parameters of type " + + "" + + "ParamTest2
    ClassUseTest3<T extends ParamTest2<java.util.List<? extends Foo4>>>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest2.html", - "Methods in pkg2 with type parameters of type ParamTest2
    " + NL + + "Methods in pkg2" + + " with type parameters of type " + + "" + + "ParamTest2
    ClassUseTest3.method(T t)" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "ParamTest2.html", - "Methods in pkg2 with type parameters of type ParamTest2
    " + NL + + "Methods in pkg2" + + " with type parameters of type " + + "" + + "ParamTest2
    Classes in pkg2 with type parameters of type Foo4
    " + NL + + "Classes in pkg2" + + " with type parameters of type " + + "" + + "Foo4
    ClassUseTest3<T extends ParamTest2<java.util.List<? extends Foo4>>>" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", - "Methods in pkg2 with type parameters of type Foo4
    " + NL + + "Methods in pkg2" + + " with type parameters of type Foo4
    ClassUseTest3.method(T t)" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", - "Methods in pkg2 that return types with arguments of type Foo4
    " + NL + + "Methods in pkg2" + + " that return types with arguments of type " + + "" + + "Foo4
    Method parameters in pkg2 with type arguments of type Foo4
    " + NL + - " voidClassUseTest3.method(java.util.Set<Foo4> p)" + "
    " + NL + + "Method parameters in pkg2" + + " with type arguments of type Foo4
    Modifier and Type" + + "Method and Description
    " + NL + + " voidClassUseTest3." + + "" + + "method(java.util.Set<Foo4> p)" }, {BUG_ID + FS + "pkg2" + FS + "class-use" + FS + "Foo4.html", - "Constructor parameters in pkg2 with type arguments of type Foo4
    ClassUseTest3(java.util.Set<Foo4> p)" + "
    " + NL + + "Constructor parameters in " + + "pkg2 with type arguments of type Foo4
    Constructor and Description" + + "
    ClassUseTest3(java.util.Set<" + + "" + + "Foo4> p)" }, //================================= // Annotatation Type Usage //================================= {BUG_ID + FS + "pkg" + FS + "class-use" + FS + "AnnotationType.html", - "" + NL + - "Packages with annotations of type AnnotationType" + NL + - "
    pkg
    Package" + + "Description
    pkg" + + "
    " + NL + - " classAnnotationTypeUsage" + "Classes in pkg" + + " with annotations of type AnnotationType" + NL + + "
    Modifier and Type" + + "Class and Description
    " + NL + + " classAnnotationTypeUsage" }, {BUG_ID + FS + "pkg" + FS + "class-use" + FS + "AnnotationType.html", - "Fields in pkg with annotations of type AnnotationType" + NL + - "
    " + NL + - " intAnnotationTypeUsage.field" + "Fields in pkg" + + " with annotations of type AnnotationType" + NL + + "
    Modifier and Type" + + "Field and Description
    " + NL + + " intAnnotationTypeUsage." + + "field" + + "" }, {BUG_ID + FS + "pkg" + FS + "class-use" + FS + "AnnotationType.html", - "Methods in pkg with annotations of type AnnotationType" + NL + - "
    " + NL + - " voidAnnotationTypeUsage.method()" + "Methods in pkg" + + " with annotations of type AnnotationType" + NL + + "
    Modifier and Type" + + "Method and Description
    " + NL + + " voidAnnotationTypeUsage." + + "" + + "method()" }, {BUG_ID + FS + "pkg" + FS + "class-use" + FS + "AnnotationType.html", - "Method parameters in pkg with annotations of type AnnotationType" + NL + - "
    " + NL + - " voidAnnotationTypeUsage.methodWithParams(int documented," + NL + - " int undocmented)" + "Method parameters in pkg" + + " with annotations of type AnnotationType" + NL + + "
    Modifier and Type" + + "Method and Description
    " + NL + + " voidAnnotationTypeUsage." + + "methodWithParams(int documented," + NL + + " int undocmented)" }, {BUG_ID + FS + "pkg" + FS + "class-use" + FS + "AnnotationType.html", - "Constructors in pkg with annotations of type AnnotationType" + NL + - "
    AnnotationTypeUsage()" + "Constructors in pkg" + + " with annotations of type AnnotationType" + NL + + "
    Constructor and Description" + + "
    " + + "AnnotationTypeUsage()" }, {BUG_ID + FS + "pkg" + FS + "class-use" + FS + "AnnotationType.html", - "Constructor parameters in pkg with annotations of type AnnotationType" + NL + - "
    AnnotationTypeUsage(int documented," + NL + - " int undocmented)" + "Constructor parameters in pkg" + + " with annotations of type AnnotationType" + NL + + "
    Constructor and Description" + + "
    " + + "AnnotationTypeUsage(int documented," + NL + + " int undocmented)" }, //================================= diff --git a/langtools/test/com/sun/javadoc/testSummaryHeading/TestSummaryHeading.java b/langtools/test/com/sun/javadoc/testSummaryHeading/TestSummaryHeading.java index 36cd089c32f..49aafe21ffc 100644 --- a/langtools/test/com/sun/javadoc/testSummaryHeading/TestSummaryHeading.java +++ b/langtools/test/com/sun/javadoc/testSummaryHeading/TestSummaryHeading.java @@ -46,7 +46,8 @@ public class TestSummaryHeading extends JavadocTester { //Input for string search tests. private static final String[][] TEST = { - {BUG_ID + FS + "C.html", "Method Summary"} + {BUG_ID + FS + "C.html", "
    " + NL + + "Method Summary