This commit is contained in:
Tim Bell 2009-04-20 22:51:20 -07:00
commit e01ed73046
890 changed files with 64482 additions and 17518 deletions

View File

@ -25,3 +25,8 @@ caf58ffa084568990cbb3441f9ae188e36b31770 jdk7-b42
1bf51a4c2627c2f0e0cbcc2cf0421bdb37f1f2b2 jdk7-b48 1bf51a4c2627c2f0e0cbcc2cf0421bdb37f1f2b2 jdk7-b48
6b84b04a80afe23262377c60913eebfc898f14c4 jdk7-b49 6b84b04a80afe23262377c60913eebfc898f14c4 jdk7-b49
5da0e6b9f4f18ef483c977337214b12ee0e1fc8f jdk7-b50 5da0e6b9f4f18ef483c977337214b12ee0e1fc8f jdk7-b50
a25c5ec5e40e07733d1ff9898a0abe36159288ff jdk7-b51
7a90e89e36d103038f8667f6a7daae34ecfa1ad8 jdk7-b52
d52186ee770dac57950536cd00ccbfdef360b04c jdk7-b53
15096652c4d48dfb9fc0b2cb135304db94c65ba0 jdk7-b54
c8b275d62d6b0a980c510e839b70292245863e85 jdk7-b55

View File

@ -25,3 +25,8 @@ d7744e86dedc21a8ecf6bdb73eb191b8eaf5b0da jdk7-b47
4ae9f4bfdb98f65bd957e3fe72471b320150b38e jdk7-b48 4ae9f4bfdb98f65bd957e3fe72471b320150b38e jdk7-b48
aee93a8992d2389121eb610c00a86196f3e2b9b0 jdk7-b49 aee93a8992d2389121eb610c00a86196f3e2b9b0 jdk7-b49
5111e13e44e542fe945b47ab154546daec36737d jdk7-b50 5111e13e44e542fe945b47ab154546daec36737d jdk7-b50
0f0189d55ce4a1f7840da7582ac7d970b3b7ab15 jdk7-b51
4264c2fe66493e57c411045a1b61377796641e45 jdk7-b52
c235f4a8559d196879c56af80159f67ee5d0e720 jdk7-b53
2ef382b1bbd58a68e668391c6145a4b2066c5b96 jdk7-b54
aea0ace7a1e43619800931d42bbf69c579361c2d jdk7-b55

View File

@ -25,3 +25,8 @@ ccd6a16502e0650d91d85c4b86be05cbcd461a87 jdk7-b42
0be222241fd405e48915647facfaa176621b39b9 jdk7-b48 0be222241fd405e48915647facfaa176621b39b9 jdk7-b48
d70978bc64bc7a04be7797ab0dcd9b7b1b3a6bff jdk7-b49 d70978bc64bc7a04be7797ab0dcd9b7b1b3a6bff jdk7-b49
0edbd0074b02b42b2b83cc47cb391d4869b7a8ec jdk7-b50 0edbd0074b02b42b2b83cc47cb391d4869b7a8ec jdk7-b50
3eb8f1047a7402a9a79937d1c39560e931e91da2 jdk7-b51
bec82237d694f9802b820fa11bbb4f7fa9bf8e77 jdk7-b52
3c4d73194f6f89f040ae3b2d257335dfa8a1b2b5 jdk7-b53
8130ac858d6789d5853d23044ba4a992afda574a jdk7-b54
7a869f16ba83060c34b77620406cfa89d1cd7084 jdk7-b55

View File

@ -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_PortableActivationIDL.jmk
include $(CORBA_JMK_DIRECTORY)com_sun_corba_se_impl_logging.jmk include $(CORBA_JMK_DIRECTORY)com_sun_corba_se_impl_logging.jmk
FILES_java += com/sun/corba/se/org/omg/CORBA/ORB.java
# #
# Dirs # 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 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 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_CLASS = make-class
MC_GENERATE_LOG_RB = $(SRC_DIR)/com/sun/tools/corba/se/logutil/scripts/mc.scm -main main make-resource MC_GENERATE_LOG_RB = make-resource
JSCHEME_GENERATE_CLASS = $(BOOT_JAVA_CMD) jscheme.REPL $(MC_GENERATE_CLASS) JSCHEME_GENERATE_CLASS = $(BOOT_JAVA_CMD) com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_CLASS)
JSCHEME_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) jscheme.REPL $(MC_GENERATE_LOG_RB) JSCHEME_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_LOG_RB)
# #

View File

@ -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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # 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 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 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_CLASS = make-class
MC_GENERATE_LOG_RB = $(SRC_DIR)/com/sun/tools/corba/se/logutil/scripts/mc.scm -main main make-resource MC_GENERATE_LOG_RB = make-resource
JSCHEME_LIB_DIRECTORY=$(SRC_DIR)/com/sun/tools/corba/se/logutil/lib MC_CLASSPATH=$(BUILDTOOLJARDIR)/MC.jar
JSCHEME_CLASSPATH=$(JSCHEME_LIB_DIRECTORY)/jscheme.jar$(CLASSPATH_SEPARATOR)$(JSCHEME_LIB_DIRECTORY)/jschemelogutil.jar MCJ_GENERATE_CLASS = $(BOOT_JAVA_CMD) \
JSCHEME_GENERATE_CLASS = $(BOOT_JAVA_CMD) \ -cp "$(MC_CLASSPATH)" com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_CLASS)
-cp "$(JSCHEME_CLASSPATH)" jscheme.REPL $(MC_GENERATE_CLASS) MCJ_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) \
JSCHEME_GENERATE_LOG_RB = $(BOOT_JAVA_CMD) \ -cp "$(MC_CLASSPATH)" com.sun.tools.corba.se.logutil.MC $(MC_GENERATE_LOG_RB)
-cp "$(JSCHEME_CLASSPATH)" jscheme.REPL $(MC_GENERATE_LOG_RB)
# #
@ -104,28 +103,28 @@ $(LOG_GENDIRECTORY):
$(MKDIR) -p $(LOG_GENDIRECTORY) $(MKDIR) -p $(LOG_GENDIRECTORY)
$(LOG_GENDIRECTORY)/ActivationSystemException.java : $(ACTIVATION.MC) $(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) $(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) $(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) $(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) $(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) $(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) $(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) $(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 logresource.generate: $(LOG_GENDIRECTORY)/LogStrings.properties
@ -142,28 +141,28 @@ $(LOG_GENDIRECTORY)/LogStrings.properties: \
$(CAT) $(LOG_GENDIRECTORY)/*.resource > $(LOG_GENDIRECTORY)/LogStrings.properties $(CAT) $(LOG_GENDIRECTORY)/*.resource > $(LOG_GENDIRECTORY)/LogStrings.properties
$(LOG_GENDIRECTORY)/ActivationSystemException.resource : $(ACTIVATION.MC) $(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) $(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) $(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) $(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) $(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) $(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) $(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) $(LOG_GENDIRECTORY)/UtilSystemException.resource : $(UTIL.MC)
$(JSCHEME_GENERATE_LOG_RB) $(UTIL.MC) $(LOG_GENDIRECTORY) $(MCJ_GENERATE_LOG_RB) $(UTIL.MC) $(LOG_GENDIRECTORY)
# #

View File

@ -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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -33,6 +33,7 @@ include $(BUILDDIR)/common/Defs.gmk
SUBDIRS = \ SUBDIRS = \
strip_properties \ strip_properties \
idlj \ idlj \
logutil \
all build clean clobber:: all build clean clobber::
$(SUBDIRS-loop) $(SUBDIRS-loop)

View File

@ -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

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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.OutputStream ;
import java.io.BufferedWriter ; import java.io.BufferedWriter ;
import java.io.OutputStreamWriter ; import java.io.OutputStreamWriter ;
import jsint.Pair ;
import java.util.StringTokenizer ; import java.util.StringTokenizer ;
public class IndentingPrintWriter extends PrintWriter { public class IndentingPrintWriter extends PrintWriter {
@ -38,22 +37,20 @@ public class IndentingPrintWriter extends PrintWriter {
private int indentWidth = 4 ; private int indentWidth = 4 ;
private String indentString = "" ; 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 ) ; // System.out.println( "printMsg called with msg=" + msg + " data=" + data ) ;
StringTokenizer st = new StringTokenizer( msg, "@", true ) ; StringTokenizer st = new StringTokenizer( msg, "@", true ) ;
StringBuffer result = new StringBuffer() ; StringBuffer result = new StringBuffer() ;
Object head = data.first ;
Pair tail = (Pair)data.rest ;
String token = null ; String token = null ;
int pos = 0;
while (st.hasMoreTokens()) { while (st.hasMoreTokens()) {
token = st.nextToken() ; token = st.nextToken() ;
if (token.equals("@")) { if (token.equals("@")) {
if (head != null) { if (pos < data.length) {
result.append( head ) ; result.append( data[pos] );
head = tail.first ; ++pos;
tail = (Pair)tail.rest ;
} else { } else {
throw new Error( "List too short for message" ) ; throw new Error( "List too short for message" ) ;
} }

View File

@ -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<InputException> 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<InputException>();
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<String> lines = new LinkedList<String>();
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<InputException> 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 +
"]";
}
}

View File

@ -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 +
"]";
}
}

View File

@ -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<InputCode> 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<InputCode>();
}
/**
* 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<InputCode> getCodes() {
return codes;
}
/**
* Returns a textual representation of this exception.
*
* @return a textual representation.
*/
public String toString() {
return getClass().getName()
+ "[name=" + name
+ ",codes=" + codes
+ "]";
}
}

View File

@ -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<String> SUN_EXCEPTION_GROUPS = Arrays.asList(new String[]
{ "SUNBASE", "ORBUTIL", "ACTIVATION", "NAMING", "INTERCEPTORS", "POA", "IOR", "UTIL" });
private static final List<String> 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<InputException> 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<InputException> 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<InputException> 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) <input file> <output dir>");
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]);
}
}

View File

@ -1,2 +0,0 @@
#! /bin/sh
java -cp lib/jscheme.jar:lib/util.jar jscheme.REPL mc.scm -main main $@

View File

@ -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

View File

@ -1,2 +0,0 @@
#! /bin/sh
java -cp ${CLASSPATH}:lib/jscheme.jar:lib/util.jar jscheme.REPL mc.scm

View File

@ -25,3 +25,8 @@ fcb923bad68e2b10380a030ea83a723f4dc3d4d6 jdk7-b47
bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48 bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48
8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49 8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49
dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50 dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50
2581d90c6c9b2012da930eb4742add94a03069a0 jdk7-b51
1b1e8f1a4fe8cebc01c022484f78148e17b62a0d jdk7-b52
032c6af894dae8d939b3dd31d82042549e7793e0 jdk7-b53
fafab5d5349c7c066d677538db67a1ee0fb33bd2 jdk7-b54
f8e839c086152da70d6ec5913ba6f9f509282e8d jdk7-b55

View File

@ -118,9 +118,9 @@ public interface Debugger extends SymbolLookup, ThreadAccess {
public long getJIntSize(); public long getJIntSize();
public long getJLongSize(); public long getJLongSize();
public long getJShortSize(); public long getJShortSize();
public long getHeapBase();
public long getHeapOopSize(); public long getHeapOopSize();
public long getLogMinObjAlignmentInBytes(); public long getNarrowOopBase();
public int getNarrowOopShift();
public ReadResult readBytesFromProcess(long address, long numBytes) public ReadResult readBytesFromProcess(long address, long numBytes)
throws DebuggerException; throws DebuggerException;

View File

@ -56,8 +56,8 @@ public abstract class DebuggerBase implements Debugger {
// heap data. // heap data.
protected long oopSize; protected long oopSize;
protected long heapOopSize; protected long heapOopSize;
protected long heapBase; // heap base for compressed oops. protected long narrowOopBase; // heap base for compressed oops.
protected long logMinObjAlignmentInBytes; // Used to decode compressed oops. protected int narrowOopShift; // shift to decode compressed oops.
// Should be initialized if desired by calling initCache() // Should be initialized if desired by calling initCache()
private PageCache cache; private PageCache cache;
@ -159,10 +159,10 @@ public abstract class DebuggerBase implements Debugger {
javaPrimitiveTypesConfigured = true; javaPrimitiveTypesConfigured = true;
} }
public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignmentInBytes) { public void putHeapConst(long heapOopSize, long narrowOopBase, int narrowOopShift) {
this.heapBase = heapBase;
this.heapOopSize = heapOopSize; this.heapOopSize = heapOopSize;
this.logMinObjAlignmentInBytes = logMinObjAlignmentInBytes; this.narrowOopBase = narrowOopBase;
this.narrowOopShift = narrowOopShift;
} }
/** May be called by subclasses if desired to initialize the page /** 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); long value = readCInteger(address, getHeapOopSize(), true);
if (value != 0) { if (value != 0) {
// See oop.inline.hpp decode_heap_oop // See oop.inline.hpp decode_heap_oop
value = (long)(heapBase + (long)(value << logMinObjAlignmentInBytes)); value = (long)(narrowOopBase + (long)(value << narrowOopShift));
} }
return value; return value;
} }
@ -545,10 +545,10 @@ public abstract class DebuggerBase implements Debugger {
return heapOopSize; return heapOopSize;
} }
public long getHeapBase() { public long getNarrowOopBase() {
return heapBase; return narrowOopBase;
} }
public long getLogMinObjAlignmentInBytes() { public int getNarrowOopShift() {
return logMinObjAlignmentInBytes; return narrowOopShift;
} }
} }

View File

@ -42,5 +42,5 @@ public interface JVMDebugger extends Debugger {
long jintSize, long jintSize,
long jlongSize, long jlongSize,
long jshortSize); long jshortSize);
public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignment); public void putHeapConst(long heapOopSize, long narrowOopBase, int narrowOopShift);
} }

View File

@ -65,9 +65,10 @@ public interface RemoteDebugger extends Remote {
public long getJIntSize() throws RemoteException; public long getJIntSize() throws RemoteException;
public long getJLongSize() throws RemoteException; public long getJLongSize() throws RemoteException;
public long getJShortSize() throws RemoteException; public long getJShortSize() throws RemoteException;
public long getHeapBase() throws RemoteException;
public long getHeapOopSize() 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, public boolean areThreadsEqual(long addrOrId1, boolean isAddress1,
long addrOrId2, boolean isAddress2) throws RemoteException; long addrOrId2, boolean isAddress2) throws RemoteException;
public int getThreadHashCode(long addrOrId, boolean isAddress) throws RemoteException; public int getThreadHashCode(long addrOrId, boolean isAddress) throws RemoteException;

View File

@ -85,9 +85,9 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
jlongSize = remoteDebugger.getJLongSize(); jlongSize = remoteDebugger.getJLongSize();
jshortSize = remoteDebugger.getJShortSize(); jshortSize = remoteDebugger.getJShortSize();
javaPrimitiveTypesConfigured = true; javaPrimitiveTypesConfigured = true;
heapBase = remoteDebugger.getHeapBase(); narrowOopBase = remoteDebugger.getNarrowOopBase();
narrowOopShift = remoteDebugger.getNarrowOopShift();
heapOopSize = remoteDebugger.getHeapOopSize(); heapOopSize = remoteDebugger.getHeapOopSize();
logMinObjAlignmentInBytes = remoteDebugger.getLogMinObjAlignmentInBytes();
} }
catch (RemoteException e) { catch (RemoteException e) {
throw new DebuggerException(e); throw new DebuggerException(e);

View File

@ -114,17 +114,18 @@ public class RemoteDebuggerServer extends UnicastRemoteObject
return debugger.getJShortSize(); return debugger.getJShortSize();
} }
public long getHeapBase() throws RemoteException {
return debugger.getHeapBase();
}
public long getHeapOopSize() throws RemoteException { public long getHeapOopSize() throws RemoteException {
return debugger.getHeapOopSize(); return debugger.getHeapOopSize();
} }
public long getLogMinObjAlignmentInBytes() throws RemoteException { public long getNarrowOopBase() throws RemoteException {
return debugger.getLogMinObjAlignmentInBytes(); return debugger.getNarrowOopBase();
} }
public int getNarrowOopShift() throws RemoteException {
return debugger.getNarrowOopShift();
}
public boolean areThreadsEqual(long addrOrId1, boolean isAddress1, public boolean areThreadsEqual(long addrOrId1, boolean isAddress1,
long addrOrId2, boolean isAddress2) throws RemoteException { long addrOrId2, boolean isAddress2) throws RemoteException {
ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1); ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1);

View File

@ -53,7 +53,8 @@ public class Universe {
// system obj array klass object // system obj array klass object
private static sun.jvm.hotspot.types.OopField systemObjArrayKlassObjField; private static sun.jvm.hotspot.types.OopField systemObjArrayKlassObjField;
private static AddressField heapBaseField; private static AddressField narrowOopBaseField;
private static CIntegerField narrowOopShiftField;
static { static {
VM.registerVMInitializedObserver(new Observer() { VM.registerVMInitializedObserver(new Observer() {
@ -86,7 +87,8 @@ public class Universe {
systemObjArrayKlassObjField = type.getOopField("_systemObjArrayKlassObj"); systemObjArrayKlassObjField = type.getOopField("_systemObjArrayKlassObj");
heapBaseField = type.getAddressField("_heap_base"); narrowOopBaseField = type.getAddressField("_narrow_oop._base");
narrowOopShiftField = type.getCIntegerField("_narrow_oop._shift");
} }
public Universe() { public Universe() {
@ -100,14 +102,18 @@ public class Universe {
} }
} }
public static long getHeapBase() { public static long getNarrowOopBase() {
if (heapBaseField.getValue() == null) { if (narrowOopBaseField.getValue() == null) {
return 0; return 0;
} else { } 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. */ /** Returns "TRUE" iff "p" points into the allocated area of the heap. */
public boolean isIn(Address p) { public boolean isIn(Address p) {
return heap().isIn(p); return heap().isIn(p);

View File

@ -142,34 +142,35 @@ public interface ClassConstants
// from jvm.h // from jvm.h
public static final long JVM_RECOGNIZED_CLASS_MODIFIERS = (JVM_ACC_PUBLIC | public static final long JVM_RECOGNIZED_CLASS_MODIFIERS = (JVM_ACC_PUBLIC |
JVM_ACC_FINAL | JVM_ACC_FINAL |
JVM_ACC_SUPER | JVM_ACC_SUPER |
JVM_ACC_INTERFACE | JVM_ACC_INTERFACE |
JVM_ACC_ABSTRACT | JVM_ACC_ABSTRACT |
JVM_ACC_ANNOTATION | JVM_ACC_ANNOTATION |
JVM_ACC_SYNTHETIC); JVM_ACC_ENUM |
JVM_ACC_SYNTHETIC);
public static final long JVM_RECOGNIZED_FIELD_MODIFIERS = (JVM_ACC_PUBLIC | public static final long JVM_RECOGNIZED_FIELD_MODIFIERS = (JVM_ACC_PUBLIC |
JVM_ACC_PRIVATE | JVM_ACC_PRIVATE |
JVM_ACC_PROTECTED | JVM_ACC_PROTECTED |
JVM_ACC_STATIC | JVM_ACC_STATIC |
JVM_ACC_FINAL | JVM_ACC_FINAL |
JVM_ACC_VOLATILE | JVM_ACC_VOLATILE |
JVM_ACC_TRANSIENT | JVM_ACC_TRANSIENT |
JVM_ACC_ENUM | JVM_ACC_ENUM |
JVM_ACC_SYNTHETIC); JVM_ACC_SYNTHETIC);
public static final long JVM_RECOGNIZED_METHOD_MODIFIERS = (JVM_ACC_PUBLIC | public static final long JVM_RECOGNIZED_METHOD_MODIFIERS = (JVM_ACC_PUBLIC |
JVM_ACC_PRIVATE | JVM_ACC_PRIVATE |
JVM_ACC_PROTECTED | JVM_ACC_PROTECTED |
JVM_ACC_STATIC | JVM_ACC_STATIC |
JVM_ACC_FINAL | JVM_ACC_FINAL |
JVM_ACC_SYNCHRONIZED | JVM_ACC_SYNCHRONIZED |
JVM_ACC_BRIDGE | JVM_ACC_BRIDGE |
JVM_ACC_VARARGS | JVM_ACC_VARARGS |
JVM_ACC_NATIVE | JVM_ACC_NATIVE |
JVM_ACC_ABSTRACT | JVM_ACC_ABSTRACT |
JVM_ACC_STRICT | JVM_ACC_STRICT |
JVM_ACC_SYNTHETIC); JVM_ACC_SYNTHETIC);
} }

View File

@ -48,6 +48,8 @@ public class JavaThread extends Thread {
private static AddressField lastJavaPCField; private static AddressField lastJavaPCField;
private static CIntegerField threadStateField; private static CIntegerField threadStateField;
private static AddressField osThreadField; private static AddressField osThreadField;
private static AddressField stackBaseField;
private static CIntegerField stackSizeField;
private static JavaThreadPDAccess access; private static JavaThreadPDAccess access;
@ -83,6 +85,8 @@ public class JavaThread extends Thread {
lastJavaPCField = anchorType.getAddressField("_last_Java_pc"); lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
threadStateField = type.getCIntegerField("_thread_state"); threadStateField = type.getCIntegerField("_thread_state");
osThreadField = type.getAddressField("_osthread"); osThreadField = type.getAddressField("_osthread");
stackBaseField = type.getAddressField("_stack_base");
stackSizeField = type.getCIntegerField("_stack_size");
UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue(); UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
NEW = db.lookupIntConstant("_thread_new").intValue(); NEW = db.lookupIntConstant("_thread_new").intValue();
@ -312,6 +316,14 @@ public class JavaThread extends Thread {
return (OSThread) VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr)); return (OSThread) VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr));
} }
public Address getStackBase() {
return stackBaseField.getValue();
}
public long getStackSize() {
return stackSizeField.getValue();
}
/** Gets the Java-side thread object for this JavaThread */ /** Gets the Java-side thread object for this JavaThread */
public Oop getThreadObj() { public Oop getThreadObj() {
return VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr)); return VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr));
@ -345,11 +357,18 @@ public class JavaThread extends Thread {
if (Assert.ASSERTS_ENABLED) { if (Assert.ASSERTS_ENABLED) {
Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system"); Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system");
} }
Address highest = highestLock();
Address sp = lastSPDbg(); Address sp = lastSPDbg();
Address stackBase = getStackBase();
// Be robust // Be robust
if ((highest == null) || (sp == null)) return false; if (sp == null) return false;
return (highest.greaterThanOrEqual(a) && sp.lessThanOrEqual(a)); return stackBase.greaterThanOrEqual(a) && sp.lessThanOrEqual(a);
}
public boolean isLockOwned(Address a) {
Address stackBase = getStackBase();
Address stackLimit = stackBase.addOffsetTo(-getStackSize());
return stackBase.greaterThanOrEqual(a) && stackLimit.lessThanOrEqual(a);
// FIXME: should traverse MonitorArray/MonitorChunks as in VM // FIXME: should traverse MonitorArray/MonitorChunks as in VM
} }

View File

@ -46,12 +46,18 @@ public class StubRoutines {
Type type = db.lookupType("StubRoutines"); Type type = db.lookupType("StubRoutines");
callStubReturnAddressField = type.getAddressField("_call_stub_return_address"); callStubReturnAddressField = type.getAddressField("_call_stub_return_address");
// Only some platforms have specif return from compiled to call_stub // Only some platforms have specific return from compiled to call_stub
try { try {
callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return"); type = db.lookupType("StubRoutines::x86");
if (type != null) {
callStubCompiledReturnAddressField = type.getAddressField("_call_stub_compiled_return");
}
} catch (RuntimeException re) { } catch (RuntimeException re) {
callStubCompiledReturnAddressField = null; callStubCompiledReturnAddressField = null;
} }
if (callStubCompiledReturnAddressField == null && VM.getVM().getCPU().equals("x86")) {
throw new InternalError("Missing definition for _call_stub_compiled_return");
}
} }
public StubRoutines() { public StubRoutines() {

View File

@ -38,7 +38,6 @@ public class Thread extends VMObject {
private static int HAS_ASYNC_EXCEPTION; private static int HAS_ASYNC_EXCEPTION;
private static AddressField activeHandlesField; private static AddressField activeHandlesField;
private static AddressField highestLockField;
private static AddressField currentPendingMonitorField; private static AddressField currentPendingMonitorField;
private static AddressField currentWaitingMonitorField; private static AddressField currentWaitingMonitorField;
@ -60,7 +59,6 @@ public class Thread extends VMObject {
tlabFieldOffset = type.getField("_tlab").getOffset(); tlabFieldOffset = type.getField("_tlab").getOffset();
activeHandlesField = type.getAddressField("_active_handles"); activeHandlesField = type.getAddressField("_active_handles");
highestLockField = type.getAddressField("_highest_lock");
currentPendingMonitorField = type.getAddressField("_current_pending_monitor"); currentPendingMonitorField = type.getAddressField("_current_pending_monitor");
currentWaitingMonitorField = type.getAddressField("_current_waiting_monitor"); currentWaitingMonitorField = type.getAddressField("_current_waiting_monitor");
} }
@ -121,10 +119,6 @@ public class Thread extends VMObject {
// pending exception // pending exception
} }
public Address highestLock() {
return highestLockField.getValue(addr);
}
public ObjectMonitor getCurrentPendingMonitor() { public ObjectMonitor getCurrentPendingMonitor() {
Address monitorAddr = currentPendingMonitorField.getValue(addr); Address monitorAddr = currentPendingMonitorField.getValue(addr);
if (monitorAddr == null) { if (monitorAddr == null) {

View File

@ -164,20 +164,11 @@ public class Threads {
} }
} }
long leastDiff = 0;
boolean leastDiffInitialized = false;
JavaThread theOwner = null;
for (JavaThread thread = first(); thread != null; thread = thread.next()) { for (JavaThread thread = first(); thread != null; thread = thread.next()) {
Address addr = thread.highestLock(); if (thread.isLockOwned(o))
if (addr == null || addr.lessThan(o)) continue; return thread;
long diff = addr.minus(o);
if (!leastDiffInitialized || diff < leastDiff) {
leastDiffInitialized = true;
leastDiff = diff;
theOwner = thread;
}
} }
return theOwner; return null;
} }
public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) { public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) {

View File

@ -342,11 +342,14 @@ public class VM {
throw new RuntimeException("Attempt to initialize VM twice"); throw new RuntimeException("Attempt to initialize VM twice");
} }
soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); 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(); ) { for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
((Observer) iter.next()).update(null, null); ((Observer) iter.next()).update(null, null);
} }
} }
/** This is used by the debugging system */ /** This is used by the debugging system */

View File

@ -89,29 +89,6 @@ public class ByteCodeRewriter
// update the code buffer hotspot specific bytecode with the jvm bytecode // update the code buffer hotspot specific bytecode with the jvm bytecode
code[bci] = (byte) (0xFF & bytecode); code[bci] = (byte) (0xFF & bytecode);
// RewriteFrequentPairs
if(hotspotcode == Bytecodes._fast_iaccess_0 ||
hotspotcode == Bytecodes._fast_aaccess_0 ||
hotspotcode == Bytecodes._fast_faccess_0) {
// rewrite next bytecode as _getfield
bci++;
code[bci] = (byte) (0xFF & Bytecodes._getfield);
bytecode = Bytecodes._getfield;
hotspotcode = Bytecodes._getfield;
} else if (hotspotcode == Bytecodes._fast_iload2) {
// rewrite next bytecode as _iload
bci++;
code[bci] = (byte) (0xFF & Bytecodes._iload);
bytecode = Bytecodes._iload;
hotspotcode = Bytecodes._iload;
} else if (hotspotcode == Bytecodes._fast_icaload) {
// rewrite next bytecode as _caload
bci++;
code[bci] = (byte) (0xFF & Bytecodes._caload);
bytecode = Bytecodes._caload;
bytecode = Bytecodes._caload;
}
short cpoolIndex = 0; short cpoolIndex = 0;
switch (bytecode) { switch (bytecode) {
// bytecodes with ConstantPoolCache index // bytecodes with ConstantPoolCache index

View File

@ -59,8 +59,14 @@ public class ClassDump extends Tool {
SystemDictionary dict = VM.getVM().getSystemDictionary(); SystemDictionary dict = VM.getVM().getSystemDictionary();
dict.classesDo(new SystemDictionary.ClassVisitor() { dict.classesDo(new SystemDictionary.ClassVisitor() {
public void visit(Klass k) { public void visit(Klass k) {
if (k instanceof InstanceKlass) if (k instanceof InstanceKlass) {
dumpKlass((InstanceKlass) k); try {
dumpKlass((InstanceKlass) k);
} catch (Exception e) {
System.out.println(k.getName().asString());
e.printStackTrace();
}
}
} }
}); });
} }

View File

@ -40,7 +40,6 @@ public class ClassWriter implements /* imports */ ClassConstants
protected InstanceKlass klass; protected InstanceKlass klass;
protected DataOutputStream dos; protected DataOutputStream dos;
protected ConstantPool cpool; protected ConstantPool cpool;
protected boolean is15Format;
// Map between class name to index of type CONSTANT_Class // Map between class name to index of type CONSTANT_Class
protected Map classToIndex = new HashMap(); protected Map classToIndex = new HashMap();
@ -73,7 +72,6 @@ public class ClassWriter implements /* imports */ ClassConstants
klass = kls; klass = kls;
dos = new DataOutputStream(os); dos = new DataOutputStream(os);
cpool = klass.getConstants(); cpool = klass.getConstants();
is15Format = is15ClassFile();
} }
public void write() throws IOException { public void write() throws IOException {
@ -82,7 +80,7 @@ public class ClassWriter implements /* imports */ ClassConstants
// write magic // write magic
dos.writeInt(0xCAFEBABE); dos.writeInt(0xCAFEBABE);
writeVersion(is15Format); writeVersion();
writeConstantPool(); writeConstantPool();
writeClassAccessFlags(); writeClassAccessFlags();
writeThisClass(); writeThisClass();
@ -96,43 +94,14 @@ public class ClassWriter implements /* imports */ ClassConstants
dos.flush(); dos.flush();
} }
protected boolean is15ClassFile() { protected void writeVersion() throws IOException {
// if klass has generic signature, then it is 1.5 class file. dos.writeShort((short)klass.minorVersion());
if (klass.getGenericSignature() != null) { dos.writeShort((short)klass.majorVersion());
return true;
}
// if atleast one method has generic signature
// , then we have 1.5 class file.
ObjArray methods = klass.getMethods();
final int numMethods = (int) methods.getLength();
for (int m = 0; m < numMethods; m++) {
Method curMethod = (Method) methods.getObjAt(m);
if (curMethod.getGenericSignature() != null) {
return true;
}
}
// if atleast one field has non-zero generic signature index, then we have
// 1.5 class file
TypeArray fields = klass.getFields();
final int numFields = (int) fields.getLength();
for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) {
short genSigIndex = fields.getShortAt(f + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET);
if (genSigIndex != (short)0) return true;
}
return false;
} }
protected void writeVersion(boolean is15Format) throws IOException { protected void writeIndex(int index) throws IOException {
if (is15Format) { if (index == 0) throw new InternalError();
dos.writeShort(MINOR_VERSION); dos.writeShort(index);
dos.writeShort(MAJOR_VERSION);
} else {
dos.writeShort(MINOR_VERSION_OLD);
dos.writeShort(MAJOR_VERSION_OLD);
}
} }
protected void writeConstantPool() throws IOException { protected void writeConstantPool() throws IOException {
@ -392,8 +361,8 @@ public class ClassWriter implements /* imports */ ClassConstants
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex); if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
short fieldAttributeCount = 0; short fieldAttributeCount = 0;
boolean isSyn = isSynthetic(accessFlags); boolean hasSyn = hasSyntheticAttribute(accessFlags);
if (isSyn) if (hasSyn)
fieldAttributeCount++; fieldAttributeCount++;
short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET); short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET);
@ -407,18 +376,18 @@ public class ClassWriter implements /* imports */ ClassConstants
dos.writeShort(fieldAttributeCount); dos.writeShort(fieldAttributeCount);
// write synthetic, if applicable // write synthetic, if applicable
if (isSyn) if (hasSyn)
writeSynthetic(); writeSynthetic();
if (initvalIndex != 0) { if (initvalIndex != 0) {
dos.writeShort(_constantValueIndex); writeIndex(_constantValueIndex);
dos.writeInt(2); dos.writeInt(2);
dos.writeShort(initvalIndex); dos.writeShort(initvalIndex);
if (DEBUG) debugMessage("\tfield init value = " + initvalIndex); if (DEBUG) debugMessage("\tfield init value = " + initvalIndex);
} }
if (genSigIndex != 0) { if (genSigIndex != 0) {
dos.writeShort(_signatureIndex); writeIndex(_signatureIndex);
dos.writeInt(2); dos.writeInt(2);
dos.writeShort(genSigIndex); dos.writeShort(genSigIndex);
if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex); if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex);
@ -430,8 +399,13 @@ public class ClassWriter implements /* imports */ ClassConstants
return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0; return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0;
} }
protected boolean hasSyntheticAttribute(short accessFlags) {
// Check if flags have the attribute and if the constant pool contains an entry for it.
return isSynthetic(accessFlags) && _syntheticIndex != 0;
}
protected void writeSynthetic() throws IOException { protected void writeSynthetic() throws IOException {
dos.writeShort(_syntheticIndex); writeIndex(_syntheticIndex);
dos.writeInt(0); dos.writeInt(0);
} }
@ -459,8 +433,8 @@ public class ClassWriter implements /* imports */ ClassConstants
short methodAttributeCount = 0; short methodAttributeCount = 0;
final boolean isSyn = isSynthetic((short)accessFlags); final boolean hasSyn = hasSyntheticAttribute((short)accessFlags);
if (isSyn) if (hasSyn)
methodAttributeCount++; methodAttributeCount++;
final boolean hasCheckedExceptions = m.hasCheckedExceptions(); final boolean hasCheckedExceptions = m.hasCheckedExceptions();
@ -478,27 +452,11 @@ public class ClassWriter implements /* imports */ ClassConstants
dos.writeShort(methodAttributeCount); dos.writeShort(methodAttributeCount);
if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount); if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount);
if (isSyn) { if (hasSyn) {
if (DEBUG) debugMessage("\tmethod is synthetic"); if (DEBUG) debugMessage("\tmethod is synthetic");
writeSynthetic(); writeSynthetic();
} }
if (hasCheckedExceptions) {
CheckedExceptionElement[] exceptions = m.getCheckedExceptions();
dos.writeShort(_exceptionsIndex);
int attrSize = 2 /* number_of_exceptions */ +
exceptions.length * 2 /* exception_index */;
dos.writeInt(attrSize);
dos.writeShort(exceptions.length);
if (DEBUG) debugMessage("\tmethod has " + exceptions.length
+ " checked exception(s)");
for (int e = 0; e < exceptions.length; e++) {
short cpIndex = (short) exceptions[e].getClassCPIndex();
dos.writeShort(cpIndex);
}
}
if (isCodeAvailable) { if (isCodeAvailable) {
byte[] code = m.getByteCode(); byte[] code = m.getByteCode();
short codeAttrCount = 0; short codeAttrCount = 0;
@ -574,7 +532,7 @@ public class ClassWriter implements /* imports */ ClassConstants
// start writing Code // start writing Code
dos.writeShort(_codeIndex); writeIndex(_codeIndex);
dos.writeInt(codeSize); dos.writeInt(codeSize);
if (DEBUG) debugMessage("\tcode attribute length = " + codeSize); if (DEBUG) debugMessage("\tcode attribute length = " + codeSize);
@ -608,7 +566,7 @@ public class ClassWriter implements /* imports */ ClassConstants
// write LineNumberTable, if available. // write LineNumberTable, if available.
if (hasLineNumberTable) { if (hasLineNumberTable) {
dos.writeShort(_lineNumberTableIndex); writeIndex(_lineNumberTableIndex);
dos.writeInt(lineNumberAttrLen); dos.writeInt(lineNumberAttrLen);
dos.writeShort((short) lineNumberTable.length); dos.writeShort((short) lineNumberTable.length);
for (int l = 0; l < lineNumberTable.length; l++) { for (int l = 0; l < lineNumberTable.length; l++) {
@ -619,7 +577,7 @@ public class ClassWriter implements /* imports */ ClassConstants
// write LocalVariableTable, if available. // write LocalVariableTable, if available.
if (hasLocalVariableTable) { if (hasLocalVariableTable) {
dos.writeShort((short) _localVariableTableIndex); writeIndex((short) _localVariableTableIndex);
dos.writeInt(localVarAttrLen); dos.writeInt(localVarAttrLen);
dos.writeShort((short) localVariableTable.length); dos.writeShort((short) localVariableTable.length);
for (int l = 0; l < localVariableTable.length; l++) { for (int l = 0; l < localVariableTable.length; l++) {
@ -632,6 +590,22 @@ public class ClassWriter implements /* imports */ ClassConstants
} }
} }
if (hasCheckedExceptions) {
CheckedExceptionElement[] exceptions = m.getCheckedExceptions();
writeIndex(_exceptionsIndex);
int attrSize = 2 /* number_of_exceptions */ +
exceptions.length * 2 /* exception_index */;
dos.writeInt(attrSize);
dos.writeShort(exceptions.length);
if (DEBUG) debugMessage("\tmethod has " + exceptions.length
+ " checked exception(s)");
for (int e = 0; e < exceptions.length; e++) {
short cpIndex = (short) exceptions[e].getClassCPIndex();
dos.writeShort(cpIndex);
}
}
if (isGeneric) { if (isGeneric) {
writeGenericSignature(m.getGenericSignature().asString()); writeGenericSignature(m.getGenericSignature().asString());
} }
@ -643,7 +617,7 @@ public class ClassWriter implements /* imports */ ClassConstants
} }
protected void writeGenericSignature(String signature) throws IOException { protected void writeGenericSignature(String signature) throws IOException {
dos.writeShort(_signatureIndex); writeIndex(_signatureIndex);
if (DEBUG) debugMessage("signature attribute = " + _signatureIndex); if (DEBUG) debugMessage("signature attribute = " + _signatureIndex);
dos.writeInt(2); dos.writeInt(2);
Short index = (Short) utf8ToIndex.get(signature); Short index = (Short) utf8ToIndex.get(signature);
@ -653,12 +627,12 @@ public class ClassWriter implements /* imports */ ClassConstants
protected void writeClassAttributes() throws IOException { protected void writeClassAttributes() throws IOException {
final long flags = klass.getAccessFlags(); final long flags = klass.getAccessFlags();
final boolean isSyn = isSynthetic((short) flags); final boolean hasSyn = hasSyntheticAttribute((short) flags);
// check for source file // check for source file
short classAttributeCount = 0; short classAttributeCount = 0;
if (isSyn) if (hasSyn)
classAttributeCount++; classAttributeCount++;
Symbol sourceFileName = klass.getSourceFileName(); Symbol sourceFileName = klass.getSourceFileName();
@ -677,12 +651,12 @@ public class ClassWriter implements /* imports */ ClassConstants
dos.writeShort(classAttributeCount); dos.writeShort(classAttributeCount);
if (DEBUG) debugMessage("class attribute count = " + classAttributeCount); if (DEBUG) debugMessage("class attribute count = " + classAttributeCount);
if (isSyn) if (hasSyn)
writeSynthetic(); writeSynthetic();
// write SourceFile, if any // write SourceFile, if any
if (sourceFileName != null) { if (sourceFileName != null) {
dos.writeShort(_sourceFileIndex); writeIndex(_sourceFileIndex);
if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex); if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex);
dos.writeInt(2); dos.writeInt(2);
Short index = (Short) utf8ToIndex.get(sourceFileName.asString()); Short index = (Short) utf8ToIndex.get(sourceFileName.asString());
@ -697,7 +671,7 @@ public class ClassWriter implements /* imports */ ClassConstants
// write inner classes, if any // write inner classes, if any
if (numInnerClasses != 0) { if (numInnerClasses != 0) {
dos.writeShort(_innerClassesIndex); writeIndex(_innerClassesIndex);
final int innerAttrLen = 2 /* number_of_inner_classes */ + final int innerAttrLen = 2 /* number_of_inner_classes */ +
numInnerClasses * ( numInnerClasses * (
2 /* inner_class_info_index */ + 2 /* inner_class_info_index */ +

View File

@ -31,11 +31,11 @@
# #
# Don't put quotes (fail windows build). # Don't put quotes (fail windows build).
HOTSPOT_VM_COPYRIGHT=Copyright 2008 HOTSPOT_VM_COPYRIGHT=Copyright 2009
HS_MAJOR_VER=15 HS_MAJOR_VER=16
HS_MINOR_VER=0 HS_MINOR_VER=0
HS_BUILD_NUMBER=03 HS_BUILD_NUMBER=01
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=7 JDK_MINOR_VER=7

View File

@ -73,6 +73,7 @@ if [ "${osname}" = SunOS ] ; then
else else
if [ "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6" -o \ if [ "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6" -o \
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6u10" -o \ "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6u10" -o \
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6u14" -o \
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6perf" ] ; then "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6perf" ] ; then
# All jdk6 builds use SS11 # All jdk6 builds use SS11
compiler_name=SS11 compiler_name=SS11

View File

@ -19,12 +19,12 @@
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, # Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or # CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions. # have any questions.
# #
# #
# Properties for jprt # 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. # need the 32bit sibling bundle installed.
# Note: If the hotspot/make/Makefile changed to only bundle the 64bit files # 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 # 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}-jvm98, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \ ${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, \
${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}-fastdebug-c1-runThese_Xshare, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_default, \ ${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_SerialGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \ ${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_ParNewGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \ ${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_G1, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC_2, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \
${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}-GCOld_default, \ ${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_SerialGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParallelGC, \ ${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_ParNewGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_CMS, \ ${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_default, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \ ${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_ParallelGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \ ${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}-jbb_G1, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark_3 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParOldGC
jprt.my.solaris.sparcv9.test.targets= \ jprt.my.solaris.sparcv9.test.targets= \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \
${jprt.my.solaris.sparcv9}-product-c2-runThese, \ ${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_default, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${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_ParallelGC, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${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_CMS, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default_2, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_G1, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_SerialGC_2, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParOldGC, \
${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-GCOld_default, \ ${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_SerialGC, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${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_ParNewGC, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_CMS, \ ${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_default, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_SerialGC, \ ${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_ParallelGC, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_CMS, \ ${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-jbb_G1, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark_3 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParOldGC
jprt.my.solaris.x64.test.targets= \ jprt.my.solaris.x64.test.targets= \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98, \ ${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_ParallelGC, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${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_CMS, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_default_2, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_G1, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_SerialGC_2, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParOldGC, \
${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-GCOld_default, \ ${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_SerialGC, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \ ${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_ParNewGC, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_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.x64}-{product|fastdebug}-c2-jbb_default, \ ${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_SerialGC, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${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.test.targets= \
${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \
${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \ ${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, \
${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp_2, \
${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xshare, \ ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xshare, \
${jprt.my.solaris.i586}-product-c1-GCBasher_default, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_default, \
${jprt.my.solaris.i586}-product-c1-GCBasher_SerialGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_SerialGC, \
${jprt.my.solaris.i586}-product-c1-GCBasher_ParallelGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_ParallelGC, \
${jprt.my.solaris.i586}-product-c1-GCBasher_ParNewGC, \ ${jprt.my.solaris.i586}-product-c1-GCBasher_ParNewGC, \
${jprt.my.solaris.i586}-product-c1-GCBasher_CMS, \ ${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_default, \
${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_SerialGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_SerialGC, \
${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParallelGC, \
${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParNewGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParNewGC, \
${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_CMS, \ ${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_default, \
${jprt.my.solaris.i586}-product-c1-GCOld_SerialGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_SerialGC, \
${jprt.my.solaris.i586}-product-c1-GCOld_ParallelGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParallelGC, \
${jprt.my.solaris.i586}-product-c1-GCOld_ParNewGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParNewGC, \
${jprt.my.solaris.i586}-product-c1-GCOld_CMS, \ ${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_default, \
${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \
${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \
${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark_2, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_G1, \
${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark_3 ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParOldGC
jprt.my.linux.i586.test.targets = \ jprt.my.linux.i586.test.targets = \
${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${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, \
${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-c1-runThese_Xshare, \
${jprt.my.linux.i586}-fastdebug-c2-runThese_Xcomp, \ ${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_default, \
${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \ ${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_ParallelGC, \
${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${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_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_default, \
${jprt.my.linux.i586}-product-{c1|c2}-GCOld_SerialGC, \ ${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_ParallelGC, \
${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParNewGC, \ ${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_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_default, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \
${jprt.my.linux.i586}-{product|fastdebug}-c2-scimark_2, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_G1, \
${jprt.my.linux.i586}-{product|fastdebug}-c2-scimark_3 ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParOldGC
jprt.my.linux.x64.test.targets = \ jprt.my.linux.x64.test.targets = \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \ ${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_ParallelGC, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${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_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_default, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${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_ParallelGC, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${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_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_default, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${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-jbb_G1, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark_3 ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParOldGC
jprt.my.windows.i586.test.targets = \ jprt.my.windows.i586.test.targets = \
${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${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_ParallelGC, \
${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \ ${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_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_default, \
${jprt.my.windows.i586}-product-{c1|c2}-GCOld_SerialGC, \ ${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_ParallelGC, \
${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParNewGC, \ ${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_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|fastdebug}-{c1|c2}-jbb_default, \
${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParallelGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParallelGC, \
${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \
${jprt.my.windows.i586}-product-{c1|c2}-scimark_2, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_G1, \
${jprt.my.windows.i586}-product-{c1|c2}-scimark_3 ${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParOldGC
jprt.my.windows.x64.test.targets = \ jprt.my.windows.x64.test.targets = \
${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98, \ ${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_ParallelGC, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \ ${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_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_default, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \ ${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_ParallelGC, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${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_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|fastdebug}-c2-jbb_default, \
${jprt.my.windows.x64}-product-c2-jbb_CMS, \ ${jprt.my.windows.x64}-product-c2-jbb_CMS, \
${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \ ${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark_2, \ ${jprt.my.windows.x64}-product-c2-jbb_G1, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark_3 ${jprt.my.windows.x64}-product-c2-jbb_ParOldGC
# The complete list of test targets for jprt # The complete list of test targets for jprt

View File

@ -52,6 +52,19 @@ CAT="$MKS_HOME/cat.exe"
RM="$MKS_HOME/rm.exe" RM="$MKS_HOME/rm.exe"
DUMPBIN="link.exe /dump" 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 $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 "$CAT" vm1.def vm2.def > vm.def
"$RM" -f vm1.def vm2.def "$RM" -f vm1.def vm2.def

View File

@ -72,12 +72,20 @@ REM figure out MSC version
for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i
echo ************************************************************** echo **************************************************************
set ProjectFile=vm.vcproj
if "%MSC_VER%" == "1200" ( if "%MSC_VER%" == "1200" (
set ProjectFile=vm.dsp set ProjectFile=vm.dsp
echo Will generate VC6 project {unsupported} echo Will generate VC6 project {unsupported}
) else ( ) else (
set ProjectFile=vm.vcproj if "%MSC_VER%" == "1400" (
echo Will generate VC7 project 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 %ProjectFile%
echo ************************************************************** echo **************************************************************

View File

@ -29,6 +29,7 @@
# cl version 13.10.3077 returns "MSC_VER=1310" # 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.30701 returns "MSC_VER=1399" (OLD_MSSDK version)
# cl version 14.00.40310.41 returns "MSC_VER=1400" # 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 # 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 # the batch build, but so far this has not seemed to be a problem. The

View File

@ -46,6 +46,7 @@ ADLCFLAGS=-q -T -D_LP64
ADLCFLAGS=-q -T -U_LP64 ADLCFLAGS=-q -T -U_LP64
!endif !endif
CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
CPP_INCLUDE_DIRS=\ CPP_INCLUDE_DIRS=\
/I "..\generated" \ /I "..\generated" \

View File

@ -170,10 +170,6 @@ LINK_FLAGS = /manifest $(LINK_FLAGS) $(BUFFEROVERFLOWLIB)
# Manifest Tool - used in VS2005 and later to adjust manifests stored # Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts. # as resources inside build artifacts.
MT=mt.exe 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 !endif
!if "$(COMPILER_NAME)" == "VS2008" !if "$(COMPILER_NAME)" == "VS2008"
@ -185,10 +181,6 @@ LINK_FLAGS = /manifest $(LINK_FLAGS)
# Manifest Tool - used in VS2005 and later to adjust manifests stored # Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts. # as resources inside build artifacts.
MT=mt.exe 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 !endif
# Compile for space above time. # Compile for space above time.

View File

@ -48,6 +48,8 @@ MakeDepsSources=\
$(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatform.java \ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatform.java \
$(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC6.java \ $(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC6.java \
$(WorkSpace)\src\share\tools\MakeDeps\WinGammaPlatformVC7.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\Util.java \
$(WorkSpace)\src\share\tools\MakeDeps\BuildConfig.java \ $(WorkSpace)\src\share\tools\MakeDeps\BuildConfig.java \
$(WorkSpace)\src\share\tools\MakeDeps\ArgsParser.java $(WorkSpace)\src\share\tools\MakeDeps\ArgsParser.java
@ -121,7 +123,7 @@ MakeDepsIDEOptions=\
-additionalFile includeDB_gc_shared \ -additionalFile includeDB_gc_shared \
-additionalFile includeDB_gc_serial \ -additionalFile includeDB_gc_serial \
-additionalGeneratedFile $(HOTSPOTBUILDSPACE)\%f\%b vm.def \ -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) $(MakeDepsIncludesPRIVATE)
# Add in build-specific options # Add in build-specific options

View File

@ -42,10 +42,23 @@ COMPILE_RMIC=rmic
BOOT_JAVA_HOME= BOOT_JAVA_HOME=
!endif !endif
ProjectFile=vm.vcproj
!if "$(MSC_VER)" == "1200" !if "$(MSC_VER)" == "1200"
VcVersion=VC6 VcVersion=VC6
ProjectFile=vm.dsp ProjectFile=vm.dsp
!elseif "$(MSC_VER)" == "1400"
VcVersion=VC8
!elseif "$(MSC_VER)" == "1500"
VcVersion=VC9
!else !else
VcVersion=VC7 VcVersion=VC7
ProjectFile=vm.vcproj
!endif !endif

View File

@ -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 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" !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 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, # On amd64, VS2005 compiler requires bufferoverflowU.lib on the link command line,
# otherwise we get missing __security_check_cookie externals at link time. # otherwise we get missing __security_check_cookie externals at link time.
SA_LINK_FLAGS = bufferoverflowU.lib SA_LINK_FLAGS = bufferoverflowU.lib
!endif
!else !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 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 !endif

View File

@ -27,9 +27,9 @@
all: checkCL checkLink all: checkCL checkLink
checkCL: 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. echo *** WARNING *** unrecognized cl.exe version $(MSC_VER) ($(RAW_MSC_VER)). Use FORCE_MSC_VER to override automatic detection.
checkLink: 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. echo *** WARNING *** unrecognized link.exe version $(LINK_VER) ($(RAW_LINK_VER)). Use FORCE_LINK_VER to override automatic detection.

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -2615,12 +2615,12 @@ void MacroAssembler::cas_under_lock(Register top_ptr_reg, Register top_reg, Regi
} }
} }
RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr,
Register tmp, Register tmp,
int offset) { int offset) {
intptr_t value = *delayed_value_addr; intptr_t value = *delayed_value_addr;
if (value != 0) if (value != 0)
return RegisterConstant(value + offset); return RegisterOrConstant(value + offset);
// load indirectly to solve generation ordering problem // load indirectly to solve generation ordering problem
Address a(tmp, (address) delayed_value_addr); Address a(tmp, (address) delayed_value_addr);
@ -2634,11 +2634,11 @@ RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
if (offset != 0) if (offset != 0)
add(tmp, offset, tmp); add(tmp, offset, tmp);
return RegisterConstant(tmp); return RegisterOrConstant(tmp);
} }
void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { void MacroAssembler::regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) {
assert(dest.register_or_noreg() != G0, "lost side effect"); assert(dest.register_or_noreg() != G0, "lost side effect");
if ((src.is_constant() && src.as_constant() == 0) || if ((src.is_constant() && src.as_constant() == 0) ||
(src.is_register() && src.as_register() == G0)) { (src.is_register() && src.as_register() == G0)) {
@ -2647,15 +2647,15 @@ void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant sr
add(dest.as_register(), ensure_rs2(src, temp), dest.as_register()); add(dest.as_register(), ensure_rs2(src, temp), dest.as_register());
} else if (src.is_constant()) { } else if (src.is_constant()) {
intptr_t res = dest.as_constant() + src.as_constant(); intptr_t res = dest.as_constant() + src.as_constant();
dest = RegisterConstant(res); // side effect seen by caller dest = RegisterOrConstant(res); // side effect seen by caller
} else { } else {
assert(temp != noreg, "cannot handle constant += register"); assert(temp != noreg, "cannot handle constant += register");
add(src.as_register(), ensure_rs2(dest, temp), temp); add(src.as_register(), ensure_rs2(dest, temp), temp);
dest = RegisterConstant(temp); // side effect seen by caller dest = RegisterOrConstant(temp); // side effect seen by caller
} }
} }
void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) { void MacroAssembler::regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src, Register temp ) {
assert(dest.register_or_noreg() != G0, "lost side effect"); assert(dest.register_or_noreg() != G0, "lost side effect");
if (!is_simm13(src.constant_or_zero())) if (!is_simm13(src.constant_or_zero()))
src = (src.as_constant() & 0xFF); src = (src.as_constant() & 0xFF);
@ -2666,12 +2666,12 @@ void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant sr
sll_ptr(dest.as_register(), src, dest.as_register()); sll_ptr(dest.as_register(), src, dest.as_register());
} else if (src.is_constant()) { } else if (src.is_constant()) {
intptr_t res = dest.as_constant() << src.as_constant(); intptr_t res = dest.as_constant() << src.as_constant();
dest = RegisterConstant(res); // side effect seen by caller dest = RegisterOrConstant(res); // side effect seen by caller
} else { } else {
assert(temp != noreg, "cannot handle constant <<= register"); assert(temp != noreg, "cannot handle constant <<= register");
set(dest.as_constant(), temp); set(dest.as_constant(), temp);
sll_ptr(temp, src, temp); sll_ptr(temp, src, temp);
dest = RegisterConstant(temp); // side effect seen by caller dest = RegisterOrConstant(temp); // side effect seen by caller
} }
} }
@ -2683,7 +2683,7 @@ void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant sr
// On failure, execution transfers to the given label. // On failure, execution transfers to the given label.
void MacroAssembler::lookup_interface_method(Register recv_klass, void MacroAssembler::lookup_interface_method(Register recv_klass,
Register intf_klass, Register intf_klass,
RegisterConstant itable_index, RegisterOrConstant itable_index,
Register method_result, Register method_result,
Register scan_temp, Register scan_temp,
Register sethi_temp, Register sethi_temp,
@ -2720,7 +2720,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
add(recv_klass, scan_temp, scan_temp); add(recv_klass, scan_temp, scan_temp);
// Adjust recv_klass by scaled itable_index, so we can free itable_index. // Adjust recv_klass by scaled itable_index, so we can free itable_index.
RegisterConstant itable_offset = itable_index; RegisterOrConstant itable_offset = itable_index;
regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize));
regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes()); regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes());
add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass); add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass);
@ -2767,6 +2767,320 @@ 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,
RegisterOrConstant 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 = RegisterOrConstant(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::check_method_handle_type(Register mtype_reg, Register mh_reg,
Register temp_reg,
Label& wrong_method_type) {
assert_different_registers(mtype_reg, mh_reg, temp_reg);
// compare method type against that of the receiver
RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg);
ld_ptr(mh_reg, mhtype_offset, temp_reg);
cmp(temp_reg, mtype_reg);
br(Assembler::notEqual, false, Assembler::pn, wrong_method_type);
delayed()->nop();
}
void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
assert(mh_reg == G3_method_handle, "caller must put MH object in G3");
assert_different_registers(mh_reg, temp_reg);
// pick out the interpreted side of the handler
ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg);
// off we go...
ld_ptr(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes(), temp_reg);
jmp(temp_reg, 0);
// for the various stubs which take control at this point,
// see MethodHandles::generate_method_handle_stub
// (Can any caller use this delay slot? If so, add an option for supression.)
delayed()->nop();
}
RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot,
int extra_slot_offset) {
// cf. TemplateTable::prepare_invoke(), if (load_receiver).
int stackElementSize = Interpreter::stackElementWords() * wordSize;
int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
assert(offset1 - offset == stackElementSize, "correct arithmetic");
if (arg_slot.is_constant()) {
offset += arg_slot.as_constant() * stackElementSize;
return offset;
} else {
Register temp = arg_slot.as_register();
sll_ptr(temp, exact_log2(stackElementSize), temp);
if (offset != 0)
add(temp, offset, temp);
return temp;
}
}
void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
Register temp_reg, Register temp_reg,
Label& done, Label* slow_case, Label& done, Label* slow_case,
@ -3972,7 +4286,6 @@ void MacroAssembler::g1_write_barrier_pre(Register obj, Register index, int offs
static jint num_ct_writes = 0; static jint num_ct_writes = 0;
static jint num_ct_writes_filtered_in_hr = 0; static jint num_ct_writes_filtered_in_hr = 0;
static jint num_ct_writes_filtered_null = 0; static jint num_ct_writes_filtered_null = 0;
static jint num_ct_writes_filtered_pop = 0;
static G1CollectedHeap* g1 = NULL; static G1CollectedHeap* g1 = NULL;
static Thread* count_ct_writes(void* filter_val, void* new_val) { static Thread* count_ct_writes(void* filter_val, void* new_val) {
@ -3985,25 +4298,19 @@ static Thread* count_ct_writes(void* filter_val, void* new_val) {
if (g1 == NULL) { if (g1 == NULL) {
g1 = G1CollectedHeap::heap(); g1 = G1CollectedHeap::heap();
} }
if ((HeapWord*)new_val < g1->popular_object_boundary()) {
Atomic::inc(&num_ct_writes_filtered_pop);
}
} }
if ((num_ct_writes % 1000000) == 0) { if ((num_ct_writes % 1000000) == 0) {
jint num_ct_writes_filtered = jint num_ct_writes_filtered =
num_ct_writes_filtered_in_hr + num_ct_writes_filtered_in_hr +
num_ct_writes_filtered_null + num_ct_writes_filtered_null;
num_ct_writes_filtered_pop;
tty->print_cr("%d potential CT writes: %5.2f%% filtered\n" tty->print_cr("%d potential CT writes: %5.2f%% filtered\n"
" (%5.2f%% intra-HR, %5.2f%% null, %5.2f%% popular).", " (%5.2f%% intra-HR, %5.2f%% null).",
num_ct_writes, num_ct_writes,
100.0*(float)num_ct_writes_filtered/(float)num_ct_writes, 100.0*(float)num_ct_writes_filtered/(float)num_ct_writes,
100.0*(float)num_ct_writes_filtered_in_hr/ 100.0*(float)num_ct_writes_filtered_in_hr/
(float)num_ct_writes, (float)num_ct_writes,
100.0*(float)num_ct_writes_filtered_null/ 100.0*(float)num_ct_writes_filtered_null/
(float)num_ct_writes,
100.0*(float)num_ct_writes_filtered_pop/
(float)num_ct_writes); (float)num_ct_writes);
} }
return Thread::current(); return Thread::current();
@ -4210,7 +4517,7 @@ void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_v
} }
// Loading values by size and signed-ness // Loading values by size and signed-ness
void MacroAssembler::load_sized_value(Register s1, RegisterConstant s2, Register d, void MacroAssembler::load_sized_value(Register s1, RegisterOrConstant s2, Register d,
int size_in_bytes, bool is_signed) { int size_in_bytes, bool is_signed) {
switch (size_in_bytes ^ (is_signed ? -1 : 0)) { switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
case ~8: // fall through: case ~8: // fall through:
@ -4316,7 +4623,13 @@ void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) {
void MacroAssembler::encode_heap_oop(Register src, Register dst) { void MacroAssembler::encode_heap_oop(Register src, Register dst) {
assert (UseCompressedOops, "must be compressed"); 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); verify_oop(src);
if (Universe::narrow_oop_base() == NULL) {
srlx(src, LogMinObjAlignmentInBytes, dst);
return;
}
Label done; Label done;
if (src == dst) { if (src == dst) {
// optimize for frequent case src == dst // optimize for frequent case src == dst
@ -4338,26 +4651,39 @@ void MacroAssembler::encode_heap_oop(Register src, Register dst) {
void MacroAssembler::encode_heap_oop_not_null(Register r) { void MacroAssembler::encode_heap_oop_not_null(Register r) {
assert (UseCompressedOops, "must be compressed"); 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); verify_oop(r);
sub(r, G6_heapbase, r); if (Universe::narrow_oop_base() != NULL)
sub(r, G6_heapbase, r);
srlx(r, LogMinObjAlignmentInBytes, r); srlx(r, LogMinObjAlignmentInBytes, r);
} }
void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) { void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) {
assert (UseCompressedOops, "must be compressed"); 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); verify_oop(src);
sub(src, G6_heapbase, dst); if (Universe::narrow_oop_base() == NULL) {
srlx(dst, LogMinObjAlignmentInBytes, dst); srlx(src, LogMinObjAlignmentInBytes, dst);
} else {
sub(src, G6_heapbase, dst);
srlx(dst, LogMinObjAlignmentInBytes, dst);
}
} }
// Same algorithm as oops.inline.hpp decode_heap_oop. // Same algorithm as oops.inline.hpp decode_heap_oop.
void MacroAssembler::decode_heap_oop(Register src, Register dst) { void MacroAssembler::decode_heap_oop(Register src, Register dst) {
assert (UseCompressedOops, "must be compressed"); 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); sllx(src, LogMinObjAlignmentInBytes, dst);
bpr(rc_nz, true, Assembler::pt, dst, done); if (Universe::narrow_oop_base() != NULL) {
delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken Label done;
bind(done); bpr(rc_nz, true, Assembler::pt, dst, done);
delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken
bind(done);
}
verify_oop(dst); verify_oop(dst);
} }
@ -4366,8 +4692,11 @@ void MacroAssembler::decode_heap_oop_not_null(Register r) {
// pd_code_size_limit. // pd_code_size_limit.
// Also do not verify_oop as this is called by verify_oop. // Also do not verify_oop as this is called by verify_oop.
assert (UseCompressedOops, "must be compressed"); 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); 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) { void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) {
@ -4375,14 +4704,17 @@ void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) {
// pd_code_size_limit. // pd_code_size_limit.
// Also do not verify_oop as this is called by verify_oop. // Also do not verify_oop as this is called by verify_oop.
assert (UseCompressedOops, "must be compressed"); 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); sllx(src, LogMinObjAlignmentInBytes, dst);
add(dst, G6_heapbase, dst); if (Universe::narrow_oop_base() != NULL)
add(dst, G6_heapbase, dst);
} }
void MacroAssembler::reinit_heapbase() { void MacroAssembler::reinit_heapbase() {
if (UseCompressedOops) { if (UseCompressedOops) {
// call indirectly to solve generation ordering problem // 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); load_ptr_contents(base, G6_heapbase);
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -84,6 +84,10 @@ REGISTER_DECLARATION(Register, G4_scratch , G4);
REGISTER_DECLARATION(Register, Gtemp , G5); REGISTER_DECLARATION(Register, Gtemp , G5);
// JSR 292 fixed register usages:
REGISTER_DECLARATION(Register, G5_method_type , G5);
REGISTER_DECLARATION(Register, G3_method_handle , G3);
// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass, // The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
// because a single patchable "set" instruction (NativeMovConstReg, // because a single patchable "set" instruction (NativeMovConstReg,
// or NativeMovConstPatching for compiler1) instruction // or NativeMovConstPatching for compiler1) instruction
@ -91,9 +95,13 @@ REGISTER_DECLARATION(Register, Gtemp , G5);
// call site is an inline cache or is megamorphic. See the function // call site is an inline cache or is megamorphic. See the function
// CompiledIC::set_to_megamorphic. // CompiledIC::set_to_megamorphic.
// //
// On the other hand, G5_inline_cache_klass must differ from G5_method, // If a inline cache targets an interpreted method, then the
// because both registers are needed for an inline cache that calls // G5 register will be used twice during the call. First,
// an interpreted method. // the call site will be patched to load a compiledICHolder
// into G5. (This is an ordered pair of ic_klass, method.)
// The c2i adapter will first check the ic_klass, then load
// G5_method with the method part of the pair just before
// jumping into the interpreter.
// //
// Note that G5_method is only the method-self for the interpreter, // Note that G5_method is only the method-self for the interpreter,
// and is logically unrelated to G5_megamorphic_method. // and is logically unrelated to G5_megamorphic_method.
@ -1088,8 +1096,8 @@ public:
inline void add( Register s1, Register s2, Register d ); inline void add( Register s1, Register s2, Register d );
inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none); inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec); inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec);
inline void add( Register s1, RegisterConstant s2, Register d, int offset = 0); inline void add( Register s1, RegisterOrConstant s2, Register d, int offset = 0);
inline void add( const Address& a, Register d, int offset = 0); inline void add( const Address& a, Register d, int offset = 0);
void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
@ -1305,15 +1313,15 @@ public:
inline void ld( const Address& a, Register d, int offset = 0 ); inline void ld( const Address& a, Register d, int offset = 0 );
inline void ldd( const Address& a, Register d, int offset = 0 ); inline void ldd( const Address& a, Register d, int offset = 0 );
inline void ldub( Register s1, RegisterConstant s2, Register d ); inline void ldub( Register s1, RegisterOrConstant s2, Register d );
inline void ldsb( Register s1, RegisterConstant s2, Register d ); inline void ldsb( Register s1, RegisterOrConstant s2, Register d );
inline void lduh( Register s1, RegisterConstant s2, Register d ); inline void lduh( Register s1, RegisterOrConstant s2, Register d );
inline void ldsh( Register s1, RegisterConstant s2, Register d ); inline void ldsh( Register s1, RegisterOrConstant s2, Register d );
inline void lduw( Register s1, RegisterConstant s2, Register d ); inline void lduw( Register s1, RegisterOrConstant s2, Register d );
inline void ldsw( Register s1, RegisterConstant s2, Register d ); inline void ldsw( Register s1, RegisterOrConstant s2, Register d );
inline void ldx( Register s1, RegisterConstant s2, Register d ); inline void ldx( Register s1, RegisterOrConstant s2, Register d );
inline void ld( Register s1, RegisterConstant s2, Register d ); inline void ld( Register s1, RegisterOrConstant s2, Register d );
inline void ldd( Register s1, RegisterConstant s2, Register d ); inline void ldd( Register s1, RegisterOrConstant s2, Register d );
// pp 177 // pp 177
@ -1535,12 +1543,12 @@ public:
inline void st( Register d, const Address& a, int offset = 0 ); inline void st( Register d, const Address& a, int offset = 0 );
inline void std( Register d, const Address& a, int offset = 0 ); inline void std( Register d, const Address& a, int offset = 0 );
inline void stb( Register d, Register s1, RegisterConstant s2 ); inline void stb( Register d, Register s1, RegisterOrConstant s2 );
inline void sth( Register d, Register s1, RegisterConstant s2 ); inline void sth( Register d, Register s1, RegisterOrConstant s2 );
inline void stw( Register d, Register s1, RegisterConstant s2 ); inline void stw( Register d, Register s1, RegisterOrConstant s2 );
inline void stx( Register d, Register s1, RegisterConstant s2 ); inline void stx( Register d, Register s1, RegisterOrConstant s2 );
inline void std( Register d, Register s1, RegisterConstant s2 ); inline void std( Register d, Register s1, RegisterOrConstant s2 );
inline void st( Register d, Register s1, RegisterConstant s2 ); inline void st( Register d, Register s1, RegisterOrConstant s2 );
// pp 177 // pp 177
@ -1859,7 +1867,7 @@ class MacroAssembler: public Assembler {
// Functions for isolating 64 bit shifts for LP64 // Functions for isolating 64 bit shifts for LP64
inline void sll_ptr( Register s1, Register s2, Register d ); inline void sll_ptr( Register s1, Register s2, Register d );
inline void sll_ptr( Register s1, int imm6a, Register d ); inline void sll_ptr( Register s1, int imm6a, Register d );
inline void sll_ptr( Register s1, RegisterConstant s2, Register d ); inline void sll_ptr( Register s1, RegisterOrConstant s2, Register d );
inline void srl_ptr( Register s1, Register s2, Register d ); inline void srl_ptr( Register s1, Register s2, Register d );
inline void srl_ptr( Register s1, int imm6a, Register d ); inline void srl_ptr( Register s1, int imm6a, Register d );
@ -1931,6 +1939,7 @@ class MacroAssembler: public Assembler {
inline void store_ptr_contents( Register s, Address& a, int offset = 0 ); inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
inline void jumpl_to( Address& a, Register d, int offset = 0 ); inline void jumpl_to( Address& a, Register d, int offset = 0 );
inline void jump_to( Address& a, int offset = 0 ); inline void jump_to( Address& a, int offset = 0 );
inline void jump_indirect_to( Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0 );
// ring buffer traceable jumps // ring buffer traceable jumps
@ -1965,26 +1974,26 @@ class MacroAssembler: public Assembler {
// st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's
inline void ld_ptr( Register s1, Register s2, Register d ); inline void ld_ptr( Register s1, Register s2, Register d );
inline void ld_ptr( Register s1, int simm13a, Register d); inline void ld_ptr( Register s1, int simm13a, Register d);
inline void ld_ptr( Register s1, RegisterConstant s2, Register d ); inline void ld_ptr( Register s1, RegisterOrConstant s2, Register d );
inline void ld_ptr( const Address& a, Register d, int offset = 0 ); inline void ld_ptr( const Address& a, Register d, int offset = 0 );
inline void st_ptr( Register d, Register s1, Register s2 ); inline void st_ptr( Register d, Register s1, Register s2 );
inline void st_ptr( Register d, Register s1, int simm13a); inline void st_ptr( Register d, Register s1, int simm13a);
inline void st_ptr( Register d, Register s1, RegisterConstant s2 ); inline void st_ptr( Register d, Register s1, RegisterOrConstant s2 );
inline void st_ptr( Register d, const Address& a, int offset = 0 ); inline void st_ptr( Register d, const Address& a, int offset = 0 );
// ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's
// st_long will perform st for 32 bit VM's and stx for 64 bit VM's // st_long will perform st for 32 bit VM's and stx for 64 bit VM's
inline void ld_long( Register s1, Register s2, Register d ); inline void ld_long( Register s1, Register s2, Register d );
inline void ld_long( Register s1, int simm13a, Register d ); inline void ld_long( Register s1, int simm13a, Register d );
inline void ld_long( Register s1, RegisterConstant s2, Register d ); inline void ld_long( Register s1, RegisterOrConstant s2, Register d );
inline void ld_long( const Address& a, Register d, int offset = 0 ); inline void ld_long( const Address& a, Register d, int offset = 0 );
inline void st_long( Register d, Register s1, Register s2 ); inline void st_long( Register d, Register s1, Register s2 );
inline void st_long( Register d, Register s1, int simm13a ); inline void st_long( Register d, Register s1, int simm13a );
inline void st_long( Register d, Register s1, RegisterConstant s2 ); inline void st_long( Register d, Register s1, RegisterOrConstant s2 );
inline void st_long( Register d, const Address& a, int offset = 0 ); inline void st_long( Register d, const Address& a, int offset = 0 );
// Loading values by size and signed-ness // Loading values by size and signed-ness
void load_sized_value(Register s1, RegisterConstant s2, Register d, void load_sized_value(Register s1, RegisterOrConstant s2, Register d,
int size_in_bytes, bool is_signed); int size_in_bytes, bool is_signed);
// Helpers for address formation. // Helpers for address formation.
@ -1994,11 +2003,11 @@ class MacroAssembler: public Assembler {
// is required, and becomes the result. // is required, and becomes the result.
// If dest is a register and src is a non-simm13 constant, // If dest is a register and src is a non-simm13 constant,
// the temp argument is required, and is used to materialize the constant. // the temp argument is required, and is used to materialize the constant.
void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, void regcon_inc_ptr( RegisterOrConstant& dest, RegisterOrConstant src,
Register temp = noreg ); Register temp = noreg );
void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, void regcon_sll_ptr( RegisterOrConstant& dest, RegisterOrConstant src,
Register temp = noreg ); Register temp = noreg );
RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) { RegisterOrConstant ensure_rs2(RegisterOrConstant rs2, Register sethi_temp) {
guarantee(sethi_temp != noreg, "constant offset overflow"); guarantee(sethi_temp != noreg, "constant offset overflow");
if (is_simm13(rs2.constant_or_zero())) if (is_simm13(rs2.constant_or_zero()))
return rs2; // register or short constant return rs2; // register or short constant
@ -2322,11 +2331,61 @@ class MacroAssembler: public Assembler {
// interface method calling // interface method calling
void lookup_interface_method(Register recv_klass, void lookup_interface_method(Register recv_klass,
Register intf_klass, Register intf_klass,
RegisterConstant itable_index, RegisterOrConstant itable_index,
Register method_result, Register method_result,
Register temp_reg, Register temp2_reg, Register temp_reg, Register temp2_reg,
Label& no_such_interface); 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,
RegisterOrConstant super_check_offset = RegisterOrConstant(-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);
// method handles (JSR 292)
void check_method_handle_type(Register mtype_reg, Register mh_reg,
Register temp_reg,
Label& wrong_method_type);
void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
// offset relative to Gargs of argument at tos[arg_slot].
// (arg_slot == 0 means the last argument, not the first).
RegisterOrConstant argument_offset(RegisterOrConstant arg_slot,
int extra_slot_offset = 0);
// Stack overflow checking // Stack overflow checking
// Note: this clobbers G3_scratch // Note: this clobbers G3_scratch
@ -2341,7 +2400,7 @@ class MacroAssembler: public Assembler {
// stack overflow + shadow pages. Clobbers tsp and scratch registers. // stack overflow + shadow pages. Clobbers tsp and scratch registers.
void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch); void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch);
virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset); virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset);
void verify_tlab(); void verify_tlab();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 1997-2006 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -143,45 +143,45 @@ inline void Assembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2
inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); }
#endif #endif
inline void Assembler::ldub( Register s1, RegisterConstant s2, Register d) { inline void Assembler::ldub( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldsb(s1, s2.as_register(), d); if (s2.is_register()) ldsb(s1, s2.as_register(), d);
else ldsb(s1, s2.as_constant(), d); else ldsb(s1, s2.as_constant(), d);
} }
inline void Assembler::ldsb( Register s1, RegisterConstant s2, Register d) { inline void Assembler::ldsb( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldsb(s1, s2.as_register(), d); if (s2.is_register()) ldsb(s1, s2.as_register(), d);
else ldsb(s1, s2.as_constant(), d); else ldsb(s1, s2.as_constant(), d);
} }
inline void Assembler::lduh( Register s1, RegisterConstant s2, Register d) { inline void Assembler::lduh( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldsh(s1, s2.as_register(), d); if (s2.is_register()) ldsh(s1, s2.as_register(), d);
else ldsh(s1, s2.as_constant(), d); else ldsh(s1, s2.as_constant(), d);
} }
inline void Assembler::ldsh( Register s1, RegisterConstant s2, Register d) { inline void Assembler::ldsh( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldsh(s1, s2.as_register(), d); if (s2.is_register()) ldsh(s1, s2.as_register(), d);
else ldsh(s1, s2.as_constant(), d); else ldsh(s1, s2.as_constant(), d);
} }
inline void Assembler::lduw( Register s1, RegisterConstant s2, Register d) { inline void Assembler::lduw( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldsw(s1, s2.as_register(), d); if (s2.is_register()) ldsw(s1, s2.as_register(), d);
else ldsw(s1, s2.as_constant(), d); else ldsw(s1, s2.as_constant(), d);
} }
inline void Assembler::ldsw( Register s1, RegisterConstant s2, Register d) { inline void Assembler::ldsw( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldsw(s1, s2.as_register(), d); if (s2.is_register()) ldsw(s1, s2.as_register(), d);
else ldsw(s1, s2.as_constant(), d); else ldsw(s1, s2.as_constant(), d);
} }
inline void Assembler::ldx( Register s1, RegisterConstant s2, Register d) { inline void Assembler::ldx( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldx(s1, s2.as_register(), d); if (s2.is_register()) ldx(s1, s2.as_register(), d);
else ldx(s1, s2.as_constant(), d); else ldx(s1, s2.as_constant(), d);
} }
inline void Assembler::ld( Register s1, RegisterConstant s2, Register d) { inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ld(s1, s2.as_register(), d); if (s2.is_register()) ld(s1, s2.as_register(), d);
else ld(s1, s2.as_constant(), d); else ld(s1, s2.as_constant(), d);
} }
inline void Assembler::ldd( Register s1, RegisterConstant s2, Register d) { inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) {
if (s2.is_register()) ldd(s1, s2.as_register(), d); if (s2.is_register()) ldd(s1, s2.as_register(), d);
else ldd(s1, s2.as_constant(), d); else ldd(s1, s2.as_constant(), d);
} }
// form effective addresses this way: // form effective addresses this way:
inline void Assembler::add( Register s1, RegisterConstant s2, Register d, int offset) { inline void Assembler::add( Register s1, RegisterOrConstant s2, Register d, int offset) {
if (s2.is_register()) add(s1, s2.as_register(), d); if (s2.is_register()) add(s1, s2.as_register(), d);
else { add(s1, s2.as_constant() + offset, d); offset = 0; } else { add(s1, s2.as_constant() + offset, d); offset = 0; }
if (offset != 0) add(d, offset, d); if (offset != 0) add(d, offset, d);
@ -243,23 +243,23 @@ inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); a
inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); } inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); }
inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); } inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); }
inline void Assembler::stb( Register d, Register s1, RegisterConstant s2) { inline void Assembler::stb( Register d, Register s1, RegisterOrConstant s2) {
if (s2.is_register()) stb(d, s1, s2.as_register()); if (s2.is_register()) stb(d, s1, s2.as_register());
else stb(d, s1, s2.as_constant()); else stb(d, s1, s2.as_constant());
} }
inline void Assembler::sth( Register d, Register s1, RegisterConstant s2) { inline void Assembler::sth( Register d, Register s1, RegisterOrConstant s2) {
if (s2.is_register()) sth(d, s1, s2.as_register()); if (s2.is_register()) sth(d, s1, s2.as_register());
else sth(d, s1, s2.as_constant()); else sth(d, s1, s2.as_constant());
} }
inline void Assembler::stx( Register d, Register s1, RegisterConstant s2) { inline void Assembler::stx( Register d, Register s1, RegisterOrConstant s2) {
if (s2.is_register()) stx(d, s1, s2.as_register()); if (s2.is_register()) stx(d, s1, s2.as_register());
else stx(d, s1, s2.as_constant()); else stx(d, s1, s2.as_constant());
} }
inline void Assembler::std( Register d, Register s1, RegisterConstant s2) { inline void Assembler::std( Register d, Register s1, RegisterOrConstant s2) {
if (s2.is_register()) std(d, s1, s2.as_register()); if (s2.is_register()) std(d, s1, s2.as_register());
else std(d, s1, s2.as_constant()); else std(d, s1, s2.as_constant());
} }
inline void Assembler::st( Register d, Register s1, RegisterConstant s2) { inline void Assembler::st( Register d, Register s1, RegisterOrConstant s2) {
if (s2.is_register()) st(d, s1, s2.as_register()); if (s2.is_register()) st(d, s1, s2.as_register());
else st(d, s1, s2.as_constant()); else st(d, s1, s2.as_constant());
} }
@ -308,7 +308,7 @@ inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) {
#endif #endif
} }
inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) { inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) {
#ifdef _LP64 #ifdef _LP64
Assembler::ldx( s1, s2, d); Assembler::ldx( s1, s2, d);
#else #else
@ -340,7 +340,7 @@ inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) {
#endif #endif
} }
inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) { inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) {
#ifdef _LP64 #ifdef _LP64
Assembler::stx( d, s1, s2); Assembler::stx( d, s1, s2);
#else #else
@ -373,7 +373,7 @@ inline void MacroAssembler::ld_long( Register s1, int simm13a, Register d ) {
#endif #endif
} }
inline void MacroAssembler::ld_long( Register s1, RegisterConstant s2, Register d ) { inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) {
#ifdef _LP64 #ifdef _LP64
Assembler::ldx(s1, s2, d); Assembler::ldx(s1, s2, d);
#else #else
@ -405,7 +405,7 @@ inline void MacroAssembler::st_long( Register d, Register s1, int simm13a ) {
#endif #endif
} }
inline void MacroAssembler::st_long( Register d, Register s1, RegisterConstant s2 ) { inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) {
#ifdef _LP64 #ifdef _LP64
Assembler::stx(d, s1, s2); Assembler::stx(d, s1, s2);
#else #else
@ -455,7 +455,7 @@ inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) {
#endif #endif
} }
inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) { inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) {
if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); if (s2.is_register()) sll_ptr(s1, s2.as_register(), d);
else sll_ptr(s1, s2.as_constant(), d); else sll_ptr(s1, s2.as_constant(), d);
} }
@ -671,6 +671,15 @@ inline void MacroAssembler::jump_to( Address& a, int offset ) {
} }
inline void MacroAssembler::jump_indirect_to( Address& a, Register temp,
int ld_offset, int jmp_offset ) {
assert_not_delayed();
//sethi(a); // sethi is caller responsibility for this one
ld_ptr(a, temp, ld_offset);
jmp(temp, jmp_offset);
}
inline void MacroAssembler::set_oop( jobject obj, Register d ) { inline void MacroAssembler::set_oop( jobject obj, Register d ) {
set_oop(allocate_oop_address(obj, d)); set_oop(allocate_oop_address(obj, d));
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -2393,23 +2393,11 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
// get instance klass // get instance klass
load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL); load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL);
// get super_check_offset // perform the fast part of the checking logic
load(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), Rtmp1, T_INT, NULL); __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, &done, stub->entry(), 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();
// 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); __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);
__ delayed()->nop(); __ delayed()->nop();
__ cmp(G3, 0); __ cmp(G3, 0);
@ -2493,58 +2481,30 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
__ delayed()->nop(); __ delayed()->nop();
__ bind(done); __ bind(done);
} else { } else {
bool need_slow_path = true;
if (k->is_loaded()) { if (k->is_loaded()) {
load(klass_RInfo, k->super_check_offset(), Rtmp1, T_OBJECT, NULL); if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes())
need_slow_path = false;
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { // perform the fast part of the checking logic
// See if we get an immediate positive hit __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg,
__ cmp(Rtmp1, k_RInfo ); (need_slow_path ? &done : NULL),
__ br(Assembler::notEqual, false, Assembler::pn, *stub->entry()); stub->entry(), NULL,
__ delayed()->nop(); RegisterOrConstant(k->super_check_offset()));
} 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);
} else { } else {
assert_different_registers(Rtmp1, klass_RInfo, k_RInfo); // perform the fast part of the checking logic
__ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7,
load(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), Rtmp1, T_INT, NULL); &done, stub->entry(), NULL);
// See if we get an immediate positive hit }
load(klass_RInfo, Rtmp1, FrameMap::O7_oop_opr, T_OBJECT); if (need_slow_path) {
__ cmp(k_RInfo, O7); // call out-of-line instance of __ check_klass_subtype_slow_path(...):
__ br(Assembler::equal, false, Assembler::pn, done); assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup");
__ 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");
__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);
__ delayed()->nop(); __ delayed()->nop();
__ cmp(G3, 0); __ cmp(G3, 0);
__ br(Assembler::equal, false, Assembler::pn, *stub->entry()); __ br(Assembler::equal, false, Assembler::pn, *stub->entry());
__ delayed()->nop(); __ delayed()->nop();
__ bind(done);
} }
__ bind(done);
} }
__ mov(obj, dst); __ mov(obj, dst);
} else if (code == lir_instanceof) { } else if (code == lir_instanceof) {
@ -2582,58 +2542,32 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
__ set(0, dst); __ set(0, dst);
__ bind(done); __ bind(done);
} else { } else {
bool need_slow_path = true;
if (k->is_loaded()) { if (k->is_loaded()) {
assert_different_registers(Rtmp1, klass_RInfo, k_RInfo); if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes())
load(klass_RInfo, k->super_check_offset(), Rtmp1, T_OBJECT, NULL); need_slow_path = false;
// perform the fast part of the checking logic
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, noreg,
// See if we get an immediate positive hit (need_slow_path ? &done : NULL),
__ cmp(Rtmp1, k_RInfo ); (need_slow_path ? &done : NULL), NULL,
__ br(Assembler::equal, true, Assembler::pt, done); RegisterOrConstant(k->super_check_offset()),
__ delayed()->set(1, dst); 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);
}
} else { } else {
assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers");
// perform the fast part of the checking logic
load(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), dst, T_INT, NULL); __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, dst,
// See if we get an immediate positive hit &done, &done, NULL,
load(klass_RInfo, dst, FrameMap::O7_oop_opr, T_OBJECT); RegisterOrConstant(-1),
__ cmp(k_RInfo, O7); dst);
__ br(Assembler::equal, true, Assembler::pt, done); }
__ delayed()->set(1, dst); if (need_slow_path) {
// check for immediate negative hit // call out-of-line instance of __ check_klass_subtype_slow_path(...):
__ cmp(dst, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup");
__ 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");
__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);
__ delayed()->nop(); __ delayed()->nop();
__ mov(G3, dst); __ mov(G3, dst);
__ bind(done);
} }
__ bind(done);
} }
} else { } else {
ShouldNotReachHere(); ShouldNotReachHere();

View File

@ -714,38 +714,19 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// sub : G3, argument, destroyed // sub : G3, argument, destroyed
// super: G1, argument, not changed // super: G1, argument, not changed
// raddr: O7, blown by call // raddr: O7, blown by call
Label loop, miss; Label miss;
__ save_frame(0); // Blow no registers! __ save_frame(0); // Blow no registers!
__ ld_ptr( G3, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), L3 ); __ check_klass_subtype_slow_path(G3, G1, L0, L1, L2, L4, NULL, &miss);
__ 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() );
__ mov(1, G3); __ 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 __ delayed()->restore(); // free copy or add can go here
__ bind(miss); __ bind(miss);
__ mov(0, G3); __ 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 __ delayed()->restore(); // free copy or add can go here
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1017,6 +1017,7 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
const int slop_factor = 2*wordSize; const int slop_factor = 2*wordSize;
const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor? const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
//6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
frame::memory_parameter_word_sp_offset + // register save area + param window frame::memory_parameter_word_sp_offset + // register save area + param window
(native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class (native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
@ -1163,6 +1164,9 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
__ lduh(max_stack, O3); // Full size expression stack __ lduh(max_stack, O3); // Full size expression stack
guarantee(!EnableMethodHandles, "no support yet for java.dyn.MethodHandle"); //6815692
//6815692//if (EnableMethodHandles)
//6815692// __ inc(O3, methodOopDesc::extra_stack_entries());
__ sll(O3, LogBytesPerWord, O3); __ sll(O3, LogBytesPerWord, O3);
__ sub(O2, O3, O3); __ sub(O2, O3, O3);
// __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds // __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
@ -2017,7 +2021,9 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
frame::memory_parameter_word_sp_offset; // register save area + param window frame::memory_parameter_word_sp_offset; // register save area + param window
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
return (round_to(max_stack + return (round_to(max_stack +
extra_stack +
slop_factor + slop_factor +
fixed_size + fixed_size +
monitor_size + monitor_size +
@ -2104,7 +2110,8 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
// Need +1 here because stack_base points to the word just above the first expr stack entry // Need +1 here because stack_base points to the word just above the first expr stack entry
// and stack_limit is supposed to point to the word just below the last expr stack entry. // and stack_limit is supposed to point to the word just below the last expr stack entry.
// See generate_compute_interpreter_state. // See generate_compute_interpreter_state.
to_fill->_stack_limit = stack_base - (method->max_stack() + 1); int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
to_fill->_stack_limit = stack_base - (method->max_stack() + 1 + extra_stack);
to_fill->_monitor_base = (BasicObjectLock*) monitor_base; to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
// sparc specific // sparc specific

View File

@ -46,6 +46,7 @@ define_pd_global(uintx, TLABSize, 0);
define_pd_global(uintx, NewSize, ScaleForWordSize((2048 * K) + (2 * (64 * K)))); define_pd_global(uintx, NewSize, ScaleForWordSize((2048 * K) + (2 * (64 * K))));
define_pd_global(intx, SurvivorRatio, 8); define_pd_global(intx, SurvivorRatio, 8);
define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC
define_pd_global(intx, InlineSmallCode, 1500);
#ifdef _LP64 #ifdef _LP64
// Stack slots are 2X larger in LP64 than in the 32 bit VM. // Stack slots are 2X larger in LP64 than in the 32 bit VM.
define_pd_global(intx, ThreadStackSize, 1024); define_pd_global(intx, ThreadStackSize, 1024);

View File

@ -866,65 +866,18 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
Register Rtmp2, Register Rtmp2,
Register Rtmp3, Register Rtmp3,
Label &ok_is_subtype ) { Label &ok_is_subtype ) {
Label not_subtype, loop; Label not_subtype;
// Profile the not-null value's klass. // Profile the not-null value's klass.
profile_typecheck(Rsub_klass, Rtmp1); profile_typecheck(Rsub_klass, Rtmp1);
// Load the super-klass's check offset into Rtmp1 check_klass_subtype_fast_path(Rsub_klass, Rsuper_klass,
ld( Rsuper_klass, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes(), Rtmp1 ); Rtmp1, Rtmp2,
// Load from the sub-klass's super-class display list, or a 1-word cache of &ok_is_subtype, &not_subtype, NULL);
// 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 );
// Now do a linear scan of the secondary super-klass chain. check_klass_subtype_slow_path(Rsub_klass, Rsuper_klass,
delayed()->ld_ptr( Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), Rtmp2 ); Rtmp1, Rtmp2, Rtmp3, /*hack:*/ noreg,
&ok_is_subtype, NULL);
// 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() );
bind(not_subtype); bind(not_subtype);
profile_typecheck_failed(Rtmp1); profile_typecheck_failed(Rtmp1);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 1997-2007 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,6 +29,7 @@
address generate_normal_entry(bool synchronized); address generate_normal_entry(bool synchronized);
address generate_native_entry(bool synchronized); address generate_native_entry(bool synchronized);
address generate_abstract_entry(void); address generate_abstract_entry(void);
address generate_method_handle_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind); address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void); address generate_empty_entry(void);
address generate_accessor_entry(void); address generate_accessor_entry(void);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 1997-2007 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -235,6 +235,19 @@ address InterpreterGenerator::generate_abstract_entry(void) {
} }
// Method handle invoker
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) {
return generate_abstract_entry();
}
return generate_abstract_entry(); //6815692//
}
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
// Entry points & stack frame layout // Entry points & stack frame layout
// //
@ -364,6 +377,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
case Interpreter::java_lang_math_sin : break; case Interpreter::java_lang_math_sin : break;
case Interpreter::java_lang_math_cos : break; case Interpreter::java_lang_math_cos : break;
case Interpreter::java_lang_math_tan : break; case Interpreter::java_lang_math_tan : break;

View File

@ -0,0 +1,70 @@
/*
* 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
* 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.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_methodHandles_sparc.cpp.incl"
#define __ _masm->
address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
address interpreted_entry) {
__ align(wordSize);
address target = __ pc() + sizeof(Data);
while (__ pc() < target) {
__ nop();
__ align(wordSize);
}
MethodHandleEntry* me = (MethodHandleEntry*) __ pc();
me->set_end_address(__ pc()); // set a temporary end_address
me->set_from_interpreted_entry(interpreted_entry);
me->set_type_checking_entry(NULL);
return (address) me;
}
MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
address start_addr) {
MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
assert(me->end_address() == start_addr, "valid ME");
// Fill in the real end_address:
__ align(wordSize);
me->set_end_address(__ pc());
return me;
}
// Code generation
address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
ShouldNotReachHere(); //NYI, 6815692
return NULL;
}
// Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls.
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
ShouldNotReachHere(); //NYI, 6815692
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -142,6 +142,8 @@ REGISTER_DEFINITION(Register, G1_scratch);
REGISTER_DEFINITION(Register, G3_scratch); REGISTER_DEFINITION(Register, G3_scratch);
REGISTER_DEFINITION(Register, G4_scratch); REGISTER_DEFINITION(Register, G4_scratch);
REGISTER_DEFINITION(Register, Gtemp); REGISTER_DEFINITION(Register, Gtemp);
REGISTER_DEFINITION(Register, G5_method_type);
REGISTER_DEFINITION(Register, G3_method_handle);
REGISTER_DEFINITION(Register, Lentry_args); REGISTER_DEFINITION(Register, Lentry_args);
#ifdef CC_INTERP #ifdef CC_INTERP

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2008 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -937,12 +937,12 @@ void AdapterGenerator::gen_i2c_adapter(
// Inputs: // Inputs:
// G2_thread - TLS // G2_thread - TLS
// G5_method - Method oop // G5_method - Method oop
// O0 - Flag telling us to restore SP from O5 // G4 (Gargs) - Pointer to interpreter's args
// O4_args - Pointer to interpreter's args // O0..O4 - free for scratch
// O5 - Caller's saved SP, to be restored if needed // O5_savedSP - Caller's saved SP, to be restored if needed
// O6 - Current SP! // O6 - Current SP!
// O7 - Valid return address // O7 - Valid return address
// L0-L7, I0-I7 - Caller's temps (no frame pushed yet) // L0-L7, I0-I7 - Caller's temps (no frame pushed yet)
// Outputs: // Outputs:
// G2_thread - TLS // G2_thread - TLS
@ -954,7 +954,7 @@ void AdapterGenerator::gen_i2c_adapter(
// F0-F7 - more outgoing args // F0-F7 - more outgoing args
// O4 is about to get loaded up with compiled callee's args // Gargs is the incoming argument base, and also an outgoing argument.
__ sub(Gargs, BytesPerWord, Gargs); __ sub(Gargs, BytesPerWord, Gargs);
#ifdef ASSERT #ifdef ASSERT

View File

@ -547,7 +547,11 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
int klass_load_size; int klass_load_size;
if (UseCompressedOops) { 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 { } else {
klass_load_size = 1*BytesPerInstWord; klass_load_size = 1*BytesPerInstWord;
} }
@ -1601,9 +1605,11 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("\nUEP:"); st->print_cr("\nUEP:");
#ifdef _LP64 #ifdef _LP64
if (UseCompressedOops) { 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("\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("\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 { } else {
st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); 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); __ load_klass(O0, G3_scratch);
int klass_load_size; int klass_load_size;
if (UseCompressedOops) { 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 { } else {
klass_load_size = 1*BytesPerInstWord; klass_load_size = 1*BytesPerInstWord;
} }
@ -2993,6 +3003,202 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
__ bind(Ldone); __ bind(Ldone);
%} %}
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
MacroAssembler _masm(&cbuf);
Register str1_reg = reg_to_register_object($str1$$reg);
Register str2_reg = reg_to_register_object($str2$$reg);
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
Register result_reg = reg_to_register_object($result$$reg);
// Get the first character position in both strings
// [8] char array, [12] offset, [16] count
int value_offset = java_lang_String:: value_offset_in_bytes();
int offset_offset = java_lang_String::offset_offset_in_bytes();
int count_offset = java_lang_String:: count_offset_in_bytes();
// load str1 (jchar*) base address into tmp1_reg
__ load_heap_oop(Address(str1_reg, 0, value_offset), tmp1_reg);
__ ld(Address(str1_reg, 0, offset_offset), result_reg);
__ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
__ ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
__ load_heap_oop(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
__ add(result_reg, tmp1_reg, tmp1_reg);
// load str2 (jchar*) base address into tmp2_reg
// __ ld_ptr(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
__ ld(Address(str2_reg, 0, offset_offset), result_reg);
__ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
__ ld(Address(str2_reg, 0, count_offset), str2_reg); // hoisted
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
__ cmp(str1_reg, str2_reg); // hoisted
__ add(result_reg, tmp2_reg, tmp2_reg);
__ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg); // not equal
__ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone);
__ delayed()->add(G0, 1, result_reg); //equals
__ cmp(tmp1_reg, tmp2_reg); //same string ?
__ brx(Assembler::equal, true, Assembler::pn, Ldone);
__ delayed()->add(G0, 1, result_reg);
//rename registers
Register limit_reg = str1_reg;
Register chr2_reg = str2_reg;
Register chr1_reg = result_reg;
// tmp{12} are the base pointers
//check for alignment and position the pointers to the ends
__ or3(tmp1_reg, tmp2_reg, chr1_reg);
__ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned
__ br(Assembler::notZero, false, Assembler::pn, Lchar);
__ delayed()->nop();
__ bind(Lword);
__ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2)
__ andn(limit_reg, 0x3, limit_reg);
__ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word);
__ delayed()->nop();
__ add(tmp1_reg, limit_reg, tmp1_reg);
__ add(tmp2_reg, limit_reg, tmp2_reg);
__ neg(limit_reg);
__ lduw(tmp1_reg, limit_reg, chr1_reg);
__ bind(Lword_loop);
__ lduw(tmp2_reg, limit_reg, chr2_reg);
__ cmp(chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg);
__ inccc(limit_reg, 2*sizeof(jchar));
// annul LDUW if branch i s not taken to prevent access past end of string
__ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken
__ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted
__ bind(Lpost_word);
__ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone);
__ delayed()->add(G0, 1, result_reg);
__ lduh(tmp1_reg, 0, chr1_reg);
__ lduh(tmp2_reg, 0, chr2_reg);
__ cmp (chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg);
__ ba(false,Ldone);
__ delayed()->add(G0, 1, result_reg);
__ bind(Lchar);
__ add(tmp1_reg, limit_reg, tmp1_reg);
__ add(tmp2_reg, limit_reg, tmp2_reg);
__ neg(limit_reg); //negate count
__ lduh(tmp1_reg, limit_reg, chr1_reg);
__ bind(Lchar_loop);
__ lduh(tmp2_reg, limit_reg, chr2_reg);
__ cmp(chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg); //not equal
__ inccc(limit_reg, sizeof(jchar));
// annul LDUH if branch is not taken to prevent access past end of string
__ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken
__ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
__ add(G0, 1, result_reg); //equal
__ bind(Ldone);
%}
enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
Label Lvector, Ldone, Lloop;
MacroAssembler _masm(&cbuf);
Register ary1_reg = reg_to_register_object($ary1$$reg);
Register ary2_reg = reg_to_register_object($ary2$$reg);
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
Register result_reg = reg_to_register_object($result$$reg);
int length_offset = arrayOopDesc::length_offset_in_bytes();
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
// return true if the same array
__ cmp(ary1_reg, ary2_reg);
__ br(Assembler::equal, true, Assembler::pn, Ldone);
__ delayed()->add(G0, 1, result_reg); // equal
__ br_null(ary1_reg, true, Assembler::pn, Ldone);
__ delayed()->mov(G0, result_reg); // not equal
__ br_null(ary2_reg, true, Assembler::pn, Ldone);
__ delayed()->mov(G0, result_reg); // not equal
//load the lengths of arrays
__ ld(Address(ary1_reg, 0, length_offset), tmp1_reg);
__ ld(Address(ary2_reg, 0, length_offset), tmp2_reg);
// return false if the two arrays are not equal length
__ cmp(tmp1_reg, tmp2_reg);
__ br(Assembler::notEqual, true, Assembler::pn, Ldone);
__ delayed()->mov(G0, result_reg); // not equal
__ br_zero(Assembler::zero, true, Assembler::pn, tmp1_reg, Ldone);
__ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
// load array addresses
__ add(ary1_reg, base_offset, ary1_reg);
__ add(ary2_reg, base_offset, ary2_reg);
// renaming registers
Register chr1_reg = tmp2_reg; // for characters in ary1
Register chr2_reg = result_reg; // for characters in ary2
Register limit_reg = tmp1_reg; // length
// set byte count
__ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg);
__ andcc(limit_reg, 0x2, chr1_reg); //trailing character ?
__ br(Assembler::zero, false, Assembler::pt, Lvector);
__ delayed()->nop();
//compare the trailing char
__ sub(limit_reg, sizeof(jchar), limit_reg);
__ lduh(ary1_reg, limit_reg, chr1_reg);
__ lduh(ary2_reg, limit_reg, chr2_reg);
__ cmp(chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg); // not equal
// only one char ?
__ br_zero(Assembler::zero, true, Assembler::pn, limit_reg, Ldone);
__ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
__ bind(Lvector);
// Shift ary1_reg and ary2_reg to the end of the arrays, negate limit
__ add(ary1_reg, limit_reg, ary1_reg);
__ add(ary2_reg, limit_reg, ary2_reg);
__ neg(limit_reg, limit_reg);
__ lduw(ary1_reg, limit_reg, chr1_reg);
__ bind(Lloop);
__ lduw(ary2_reg, limit_reg, chr2_reg);
__ cmp(chr1_reg, chr2_reg);
__ br(Assembler::notEqual, false, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg); // not equal
__ inccc(limit_reg, 2*sizeof(jchar));
// annul LDUW if branch is not taken to prevent access past end of string
__ br(Assembler::notZero, true, Assembler::pt, Lloop); //annul on taken
__ delayed()->lduw(ary1_reg, limit_reg, chr1_reg); // hoisted
__ add(G0, 1, result_reg); // equals
__ bind(Ldone);
%}
enc_class enc_rethrow() %{ enc_class enc_rethrow() %{
cbuf.set_inst_mark(); cbuf.set_inst_mark();
Register temp_reg = G3; Register temp_reg = G3;
@ -9005,6 +9211,52 @@ instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, note
ins_pipe(long_memory_op); ins_pipe(long_memory_op);
%} %}
instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
o7RegI tmp3, flagsReg ccr) %{
match(Set result (StrEquals str1 str2));
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
ins_cost(300);
format %{ "String Equals $str1,$str2 -> $result" %}
ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) );
ins_pipe(long_memory_op);
%}
instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
flagsReg ccr) %{
match(Set result (AryEq ary1 ary2));
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
ins_cost(300);
format %{ "Array Equals $ary1,$ary2 -> $result" %}
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result));
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-------------------------------------------------- //------------Bytes reverse--------------------------------------------------

View File

@ -817,21 +817,6 @@ class StubGenerator: public StubCodeGenerator {
Label _atomic_add_stub; // called from other stubs Label _atomic_add_stub; // called from other stubs
// Support for void OrderAccess::fence().
//
address generate_fence() {
StubCodeMark mark(this, "StubRoutines", "fence");
address start = __ pc();
__ membar(Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore |
Assembler::StoreLoad | Assembler::StoreStore));
__ retl(false);
__ delayed()->nop();
return start;
}
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
// The following routine generates a subroutine to throw an asynchronous // The following routine generates a subroutine to throw an asynchronous
// UnknownError when an unsafe access gets a fault that could not be // UnknownError when an unsafe access gets a fault that could not be
@ -900,19 +885,7 @@ class StubGenerator: public StubCodeGenerator {
__ align(CodeEntryAlignment); __ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "partial_subtype_check"); StubCodeMark mark(this, "StubRoutines", "partial_subtype_check");
address start = __ pc(); address start = __ pc();
Label loop, miss; Label 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);
}
#if defined(COMPILER2) && !defined(_LP64) #if defined(COMPILER2) && !defined(_LP64)
// Do not use a 'save' because it blows the 64-bit O registers. // Do not use a 'save' because it blows the 64-bit O registers.
@ -936,56 +909,12 @@ class StubGenerator: public StubCodeGenerator {
Register L2_super = L2; Register L2_super = L2;
Register L3_index = L3; Register L3_index = L3;
#ifdef _LP64 __ check_klass_subtype_slow_path(Rsub, Rsuper,
Register L4_ooptmp = L4; L0, L1, L2, L3,
NULL, &miss);
if (UseCompressedOops) { // Match falls through here.
// this must be under UseCompressedOops check, as we rely upon fact __ addcc(G0,0,Rret); // set Z flags, Z result
// 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() );
#if defined(COMPILER2) && !defined(_LP64) #if defined(COMPILER2) && !defined(_LP64)
__ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0); __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0);
@ -999,7 +928,6 @@ class StubGenerator: public StubCodeGenerator {
__ delayed()->restore(); __ delayed()->restore();
#endif #endif
// Hit or miss falls through here
__ BIND(miss); __ BIND(miss);
__ addcc(G0,1,Rret); // set NZ flags, NZ result __ addcc(G0,1,Rret); // set NZ flags, NZ result
@ -2330,51 +2258,31 @@ class StubGenerator: public StubCodeGenerator {
Register super_check_offset, Register super_check_offset,
Register super_klass, Register super_klass,
Register temp, Register temp,
Label& L_success, Label& L_success) {
Register deccc_hack = noreg) {
assert_different_registers(sub_klass, super_check_offset, super_klass, temp); assert_different_registers(sub_klass, super_check_offset, super_klass, temp);
BLOCK_COMMENT("type_check:"); BLOCK_COMMENT("type_check:");
Label L_miss; Label L_miss, L_pop_to_miss;
assert_clean_int(super_check_offset, temp); assert_clean_int(super_check_offset, temp);
// maybe decrement caller's trip count: __ check_klass_subtype_fast_path(sub_klass, super_klass, temp, noreg,
#define DELAY_SLOT delayed(); \ &L_success, &L_miss, NULL,
{ if (deccc_hack == noreg) __ nop(); else __ deccc(deccc_hack); } super_check_offset);
// 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();
BLOCK_COMMENT("type_check_slow_path:");
__ save_frame(0); __ save_frame(0);
__ mov(sub_klass->after_save(), O1); __ check_klass_subtype_slow_path(sub_klass->after_save(),
// mov(super_klass->after_save(), O2); //fill delay slot super_klass->after_save(),
assert(StubRoutines::Sparc::_partial_subtype_check != NULL, "order of generation"); L0, L1, L2, L4,
__ call(StubRoutines::Sparc::_partial_subtype_check); NULL, &L_pop_to_miss);
__ delayed()->mov(super_klass->after_save(), O2); __ ba(false, L_success);
__ delayed()->restore();
__ bind(L_pop_to_miss);
__ restore(); __ 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! // Fall through on failure!
__ BIND(L_miss); __ BIND(L_miss);
} }
@ -2411,7 +2319,7 @@ class StubGenerator: public StubCodeGenerator {
gen_write_ref_array_pre_barrier(O1, O2); gen_write_ref_array_pre_barrier(O1, O2);
#ifdef ASSERT #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. // If this will cause trouble, let's fail now instead of later.
__ save_frame(0); __ save_frame(0);
__ restore(); __ restore();
@ -2455,41 +2363,39 @@ class StubGenerator: public StubCodeGenerator {
// G3, G4, G5 --- current oop, oop.klass, oop.klass.super // G3, G4, G5 --- current oop, oop.klass, oop.klass.super
__ align(16); __ align(16);
__ bind(store_element); __ BIND(store_element);
// deccc(G1_remain); // decrement the count (hoisted) __ deccc(G1_remain); // decrement the count
__ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
__ inc(O5_offset, heapOopSize); // step to next offset __ inc(O5_offset, heapOopSize); // step to next offset
__ brx(Assembler::zero, true, Assembler::pt, do_card_marks); __ brx(Assembler::zero, true, Assembler::pt, do_card_marks);
__ delayed()->set(0, O0); // return -1 on success __ delayed()->set(0, O0); // return -1 on success
// ======== loop entry is here ======== // ======== loop entry is here ========
__ bind(load_element); __ BIND(load_element);
__ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop
__ br_null(G3_oop, true, Assembler::pt, store_element); __ 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 __ load_klass(G3_oop, G4_klass); // query the object klass
generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super, generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
// branch to this on success: // branch to this on success:
store_element, store_element);
// decrement this on success:
G1_remain);
// ======== end loop ======== // ======== end loop ========
// It was a real error; we must depend on the caller to finish the job. // 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. // 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), // Emit GC store barriers for the oops we have copied (O2 minus G1),
// and report their number to the caller. // and report their number to the caller.
__ bind(fail); __ BIND(fail);
__ subcc(O2_count, G1_remain, O2_count); __ subcc(O2_count, G1_remain, O2_count);
__ brx(Assembler::zero, false, Assembler::pt, done); __ brx(Assembler::zero, false, Assembler::pt, done);
__ delayed()->not1(O2_count, O0); // report (-1^K) to caller __ 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] 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); inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
__ retl(); __ retl();
__ delayed()->nop(); // return value in 00 __ delayed()->nop(); // return value in 00
@ -2940,16 +2846,16 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_atomic_cmpxchg_ptr_entry = StubRoutines::_atomic_cmpxchg_entry; StubRoutines::_atomic_cmpxchg_ptr_entry = StubRoutines::_atomic_cmpxchg_entry;
StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long();
StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry; StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry;
StubRoutines::_fence_entry = generate_fence();
#endif // COMPILER2 !=> _LP64 #endif // COMPILER2 !=> _LP64
StubRoutines::Sparc::_partial_subtype_check = generate_partial_subtype_check();
} }
void generate_all() { void generate_all() {
// Generates all stubs and initializes the entry points // 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 // 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_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); StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -108,6 +108,24 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
} }
// Arguments are: required type in G5_method_type, and
// failing object (or NULL) in G3_method_handle.
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
address entry = __ pc();
// expression stack must be empty before entering the VM if an exception
// happened
__ empty_expression_stack();
// load exception object
__ call_VM(Oexception,
CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_WrongMethodTypeException),
G5_method_type, // required
G3_method_handle); // actual
__ should_not_reach_here();
return entry;
}
address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) { address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
address entry = __ pc(); address entry = __ pc();
// expression stack must be empty before entering the VM if an exception happened // expression stack must be empty before entering the VM if an exception happened
@ -448,6 +466,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
const int extra_space = const int extra_space =
rounded_vm_local_words + // frame local scratch space rounded_vm_local_words + // frame local scratch space
//6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
frame::memory_parameter_word_sp_offset + // register save area frame::memory_parameter_word_sp_offset + // register save area
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0); (native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
@ -1447,6 +1466,7 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong); round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong);
const int max_stack_words = max_stack * Interpreter::stackElementWords(); const int max_stack_words = max_stack * Interpreter::stackElementWords();
return (round_to((max_stack_words return (round_to((max_stack_words
//6815692//+ methodOopDesc::extra_stack_words()
+ rounded_vm_local_words + rounded_vm_local_words
+ frame::memory_parameter_word_sp_offset), WordsPerLong) + frame::memory_parameter_word_sp_offset), WordsPerLong)
// already rounded // already rounded

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -62,7 +62,7 @@ void VM_Version::initialize() {
if (is_niagara1()) { if (is_niagara1()) {
// Indirect branch is the same cost as direct // Indirect branch is the same cost as direct
if (FLAG_IS_DEFAULT(UseInlineCaches)) { if (FLAG_IS_DEFAULT(UseInlineCaches)) {
UseInlineCaches = false; FLAG_SET_DEFAULT(UseInlineCaches, false);
} }
#ifdef _LP64 #ifdef _LP64
// Single issue niagara1 is slower for CompressedOops // Single issue niagara1 is slower for CompressedOops
@ -72,33 +72,50 @@ void VM_Version::initialize() {
FLAG_SET_ERGO(bool, UseCompressedOops, false); 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 #endif // _LP64
#ifdef COMPILER2 #ifdef COMPILER2
// Indirect branch is the same cost as direct // Indirect branch is the same cost as direct
if (FLAG_IS_DEFAULT(UseJumpTables)) { if (FLAG_IS_DEFAULT(UseJumpTables)) {
UseJumpTables = true; FLAG_SET_DEFAULT(UseJumpTables, true);
} }
// Single-issue, so entry and loop tops are // Single-issue, so entry and loop tops are
// aligned on a single instruction boundary // aligned on a single instruction boundary
if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) { if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) {
InteriorEntryAlignment = 4; FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
} }
if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { if (FLAG_IS_DEFAULT(OptoLoopAlignment)) {
OptoLoopAlignment = 4; FLAG_SET_DEFAULT(OptoLoopAlignment, 4);
}
if (is_niagara1_plus() && FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
// Use smaller prefetch distance on N2
FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256);
} }
#endif #endif
} }
// Use hardware population count instruction if available.
if (has_hardware_popc()) {
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
FLAG_SET_DEFAULT(UsePopCountInstruction, true);
}
}
char buf[512]; 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_v8() ? ", has_v8" : ""),
(has_v9() ? ", has_v9" : ""), (has_v9() ? ", has_v9" : ""),
(has_hardware_popc() ? ", popc" : ""),
(has_vis1() ? ", has_vis1" : ""), (has_vis1() ? ", has_vis1" : ""),
(has_vis2() ? ", has_vis2" : ""), (has_vis2() ? ", has_vis2" : ""),
(is_ultra3() ? ", is_ultra3" : ""), (is_ultra3() ? ", is_ultra3" : ""),
(is_sun4v() ? ", is_sun4v" : ""), (is_sun4v() ? ", is_sun4v" : ""),
(is_niagara1() ? ", is_niagara1" : ""), (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" : "")); (!has_hardware_fsmuld() ? ", no-fsmuld" : ""));
// buf is started with ", " or is empty // buf is started with ", " or is empty

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,34 +25,38 @@
class VM_Version: public Abstract_VM_Version { class VM_Version: public Abstract_VM_Version {
protected: protected:
enum Feature_Flag { enum Feature_Flag {
v8_instructions = 0, v8_instructions = 0,
hardware_int_muldiv = 1, hardware_mul32 = 1,
hardware_fsmuld = 2, hardware_div32 = 2,
v9_instructions = 3, hardware_fsmuld = 3,
vis1_instructions = 4, hardware_popc = 4,
vis2_instructions = 5, v9_instructions = 5,
sun4v_instructions = 6 vis1_instructions = 6,
vis2_instructions = 7,
sun4v_instructions = 8
}; };
enum Feature_Flag_Set { enum Feature_Flag_Set {
unknown_m = 0, unknown_m = 0,
all_features_m = -1, all_features_m = -1,
v8_instructions_m = 1 << v8_instructions, v8_instructions_m = 1 << v8_instructions,
hardware_int_muldiv_m = 1 << hardware_int_muldiv, hardware_mul32_m = 1 << hardware_mul32,
hardware_fsmuld_m = 1 << hardware_fsmuld, hardware_div32_m = 1 << hardware_div32,
v9_instructions_m = 1 << v9_instructions, hardware_fsmuld_m = 1 << hardware_fsmuld,
vis1_instructions_m = 1 << vis1_instructions, hardware_popc_m = 1 << hardware_popc,
vis2_instructions_m = 1 << vis2_instructions, v9_instructions_m = 1 << v9_instructions,
sun4v_m = 1 << sun4v_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_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
generic_v9_m = generic_v8_m | v9_instructions_m | vis1_instructions_m, generic_v9_m = generic_v8_m | v9_instructions_m,
ultra3_m = generic_v9_m | vis2_instructions_m, ultra3_m = generic_v9_m | vis1_instructions_m | vis2_instructions_m,
// Temporary until we have something more accurate // Temporary until we have something more accurate
niagara1_unique_m = sun4v_m, niagara1_unique_m = sun4v_m,
niagara1_m = generic_v9_m | niagara1_unique_m niagara1_m = generic_v9_m | niagara1_unique_m
}; };
static int _features; static int _features;
@ -62,7 +66,7 @@ protected:
static int determine_features(); static int determine_features();
static int platform_features(int 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; } static int maximum_niagara1_processor_count() { return 32; }
// Returns true if the platform is in the niagara line and // Returns true if the platform is in the niagara line and
@ -76,8 +80,10 @@ public:
// Instruction support // Instruction support
static bool has_v8() { return (_features & v8_instructions_m) != 0; } static bool has_v8() { return (_features & v8_instructions_m) != 0; }
static bool has_v9() { return (_features & v9_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_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_vis1() { return (_features & vis1_instructions_m) != 0; }
static bool has_vis2() { return (_features & vis2_instructions_m) != 0; } static bool has_vis2() { return (_features & vis2_instructions_m) != 0; }

View File

@ -114,6 +114,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
} }
guarantee(__ pc() <= s->code_end(), "overflowed buffer"); guarantee(__ pc() <= s->code_end(), "overflowed buffer");
// shut the door on sizing bugs
int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one
assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add");
s->set_exception_points(npe_addr, ame_addr); s->set_exception_points(npe_addr, ame_addr);
return s; return s;
@ -208,6 +211,9 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
} }
guarantee(__ pc() <= s->code_end(), "overflowed buffer"); guarantee(__ pc() <= s->code_end(), "overflowed buffer");
// shut the door on sizing bugs
int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one
assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add");
s->set_exception_points(npe_addr, ame_addr); s->set_exception_points(npe_addr, ame_addr);
return s; return s;
@ -221,16 +227,62 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
if (is_vtable_stub) { if (is_vtable_stub) {
// ld;ld;ld,jmp,nop // ld;ld;ld,jmp,nop
const int basic = 5*BytesPerInstWord + const int basic = 5*BytesPerInstWord +
// shift;add for load_klass // shift;add for load_klass (only shift with zero heap based)
(UseCompressedOops ? 2*BytesPerInstWord : 0); (UseCompressedOops ?
((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
return basic + slop; return basic + slop;
} else { } else {
const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
// shift;add for load_klass // shift;add for load_klass (only shift with zero heap based)
(UseCompressedOops ? 2*BytesPerInstWord : 0); (UseCompressedOops ?
((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
return (basic + slop); return (basic + slop);
} }
} }
// In order to tune these parameters, run the JVM with VM options
// +PrintMiscellaneous and +WizardMode to see information about
// actual itable stubs. Look for lines like this:
// itable #1 at 0x5551212[116] left over: 8
// Reduce the constants so that the "left over" number is 8
// Do not aim at a left-over number of zero, because a very
// large vtable or itable offset (> 4K) will require an extra
// sethi/or pair of instructions.
//
// The JVM98 app. _202_jess has a megamorphic interface call.
// The itable code looks like this:
// Decoding VtableStub itbl[1]@16
// ld [ %o0 + 4 ], %g3
// save %sp, -64, %sp
// ld [ %g3 + 0xe8 ], %l2
// sll %l2, 2, %l2
// add %l2, 0x134, %l2
// and %l2, -8, %l2 ! NOT_LP64 only
// add %g3, %l2, %l2
// add %g3, 4, %g3
// ld [ %l2 ], %l5
// brz,pn %l5, throw_icce
// cmp %l5, %g5
// be %icc, success
// add %l2, 8, %l2
// loop:
// ld [ %l2 ], %l5
// brz,pn %l5, throw_icce
// cmp %l5, %g5
// bne,pn %icc, loop
// add %l2, 8, %l2
// success:
// ld [ %l2 + -4 ], %l2
// ld [ %g3 + %l2 ], %l5
// restore %l5, 0, %g5
// ld [ %g5 + 0x44 ], %g3
// jmp %g3
// nop
// throw_icce:
// sethi %hi(throw_ICCE_entry), %g3
// ! 5 more instructions here, LP64_ONLY
// jmp %g3 + %lo(throw_ICCE_entry)
// restore
} }

View File

@ -727,7 +727,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
} }
#ifdef _LP64 #ifdef _LP64
assert(false, "fix locate_operand"); assert(which == narrow_oop_operand && !is_64bit, "instruction is not a movl adr, imm32");
#else #else
assert(which == imm_operand, "instruction has only an imm field"); assert(which == imm_operand, "instruction has only an imm field");
#endif // LP64 #endif // LP64
@ -1438,26 +1438,12 @@ void Assembler::lock() {
} }
} }
// Serializes memory. // Emit mfence instruction
void Assembler::mfence() { void Assembler::mfence() {
// Memory barriers are only needed on multiprocessors NOT_LP64(assert(VM_Version::supports_sse2(), "unsupported");)
if (os::is_MP()) { emit_byte( 0x0F );
if( LP64_ONLY(true ||) VM_Version::supports_sse2() ) { emit_byte( 0xAE );
emit_byte( 0x0F ); // MFENCE; faster blows no regs emit_byte( 0xF0 );
emit_byte( 0xAE );
emit_byte( 0xF0 );
} else {
// All usable chips support "locked" instructions which suffice
// as barriers, and are much faster than the alternative of
// using cpuid instruction. We use here a locked add [esp],0.
// This is conveniently otherwise a no-op except for blowing
// flags (which we save and restore.)
pushf(); // Save eflags register
lock();
addl(Address(rsp, 0), 0);// Assert the lock# signal here
popf(); // Restore eflags register
}
}
} }
void Assembler::mov(Register dst, Register src) { void Assembler::mov(Register dst, Register src) {
@ -2187,12 +2173,56 @@ void Assembler::orl(Register dst, Register src) {
emit_arith(0x0B, 0xC0, dst, src); emit_arith(0x0B, 0xC0, dst, src);
} }
void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
assert(VM_Version::supports_sse4_2(), "");
InstructionMark im(this);
emit_byte(0x66);
prefix(src, dst);
emit_byte(0x0F);
emit_byte(0x3A);
emit_byte(0x61);
emit_operand(dst, src);
emit_byte(imm8);
}
void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) {
assert(VM_Version::supports_sse4_2(), "");
emit_byte(0x66);
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
emit_byte(0x0F);
emit_byte(0x3A);
emit_byte(0x61);
emit_byte(0xC0 | encode);
emit_byte(imm8);
}
// generic // generic
void Assembler::pop(Register dst) { void Assembler::pop(Register dst) {
int encode = prefix_and_encode(dst->encoding()); int encode = prefix_and_encode(dst->encoding());
emit_byte(0x58 | encode); 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() { void Assembler::popf() {
emit_byte(0x9D); emit_byte(0x9D);
} }
@ -2325,6 +2355,29 @@ void Assembler::psrlq(XMMRegister dst, int shift) {
emit_byte(shift); emit_byte(shift);
} }
void Assembler::ptest(XMMRegister dst, Address src) {
assert(VM_Version::supports_sse4_1(), "");
InstructionMark im(this);
emit_byte(0x66);
prefix(src, dst);
emit_byte(0x0F);
emit_byte(0x38);
emit_byte(0x17);
emit_operand(dst, src);
}
void Assembler::ptest(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_sse4_1(), "");
emit_byte(0x66);
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
emit_byte(0x0F);
emit_byte(0x38);
emit_byte(0x17);
emit_byte(0xC0 | encode);
}
void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) { void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), "")); NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_byte(0x66); emit_byte(0x66);
@ -3224,12 +3277,6 @@ void Assembler::fyl2x() {
emit_byte(0xF1); 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 #ifndef _LP64
@ -3249,6 +3296,12 @@ void Assembler::mov_literal32(Address dst, int32_t imm32, RelocationHolder cons
emit_data((int)imm32, rspec, 0); 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 void Assembler::popa() { // 32bit
emit_byte(0x61); emit_byte(0x61);
@ -3857,6 +3910,37 @@ void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder con
emit_data64(imm64, rspec); 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) { void Assembler::movdq(XMMRegister dst, Register src) {
// table D-1 says MMX/SSE2 // table D-1 says MMX/SSE2
NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), ""));
@ -4049,6 +4133,25 @@ void Assembler::popa() { // 64bit
addq(rsp, 16 * wordSize); 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) { void Assembler::popq(Address dst) {
InstructionMark im(this); InstructionMark im(this);
prefixq(dst); prefixq(dst);
@ -7149,7 +7252,7 @@ void MacroAssembler::trigfunc(char trig, int num_fpu_regs_in_use) {
// On failure, execution transfers to the given label. // On failure, execution transfers to the given label.
void MacroAssembler::lookup_interface_method(Register recv_klass, void MacroAssembler::lookup_interface_method(Register recv_klass,
Register intf_klass, Register intf_klass,
RegisterConstant itable_index, RegisterOrConstant itable_index,
Register method_result, Register method_result,
Register scan_temp, Register scan_temp,
Label& L_no_such_interface) { Label& L_no_such_interface) {
@ -7217,6 +7320,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,
RegisterOrConstant 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 = RegisterOrConstant(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) { void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) {
ucomisd(dst, as_Address(src)); ucomisd(dst, as_Address(src));
} }
@ -7262,12 +7584,12 @@ void MacroAssembler::verify_oop(Register reg, const char* s) {
} }
RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr,
Register tmp, Register tmp,
int offset) { int offset) {
intptr_t value = *delayed_value_addr; intptr_t value = *delayed_value_addr;
if (value != 0) if (value != 0)
return RegisterConstant(value + offset); return RegisterOrConstant(value + offset);
// load indirectly to solve generation ordering problem // load indirectly to solve generation ordering problem
movptr(tmp, ExternalAddress((address) delayed_value_addr)); movptr(tmp, ExternalAddress((address) delayed_value_addr));
@ -7283,7 +7605,84 @@ RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
if (offset != 0) if (offset != 0)
addptr(tmp, offset); addptr(tmp, offset);
return RegisterConstant(tmp); return RegisterOrConstant(tmp);
}
// registers on entry:
// - rax ('check' register): required MethodType
// - rcx: method handle
// - rdx, rsi, or ?: killable temp
void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
Register temp_reg,
Label& wrong_method_type) {
if (UseCompressedOops) unimplemented(); // field accesses must decode
// compare method type against that of the receiver
cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
jcc(Assembler::notEqual, wrong_method_type);
}
// A method handle has a "vmslots" field which gives the size of its
// argument list in JVM stack slots. This field is either located directly
// in every method handle, or else is indirectly accessed through the
// method handle's MethodType. This macro hides the distinction.
void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
Register temp_reg) {
if (UseCompressedOops) unimplemented(); // field accesses must decode
// load mh.type.form.vmslots
if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) {
// hoist vmslots into every mh to avoid dependent load chain
movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)));
} else {
Register temp2_reg = vmslots_reg;
movptr(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)));
movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
}
}
// registers on entry:
// - rcx: method handle
// - rdx: killable temp (interpreted only)
// - rax: killable temp (compiled only)
void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
assert(mh_reg == rcx, "caller must put MH object in rcx");
assert_different_registers(mh_reg, temp_reg);
if (UseCompressedOops) unimplemented(); // field accesses must decode
// pick out the interpreted side of the handler
movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg)));
// off we go...
jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes()));
// for the various stubs which take control at this point,
// see MethodHandles::generate_method_handle_stub
}
Address MacroAssembler::argument_address(RegisterOrConstant arg_slot,
int extra_slot_offset) {
// cf. TemplateTable::prepare_invoke(), if (load_receiver).
int stackElementSize = Interpreter::stackElementSize();
int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
#ifdef ASSERT
int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
assert(offset1 - offset == stackElementSize, "correct arithmetic");
#endif
Register scale_reg = noreg;
Address::ScaleFactor scale_factor = Address::no_scale;
if (arg_slot.is_constant()) {
offset += arg_slot.as_constant() * stackElementSize;
} else {
scale_reg = arg_slot.as_register();
scale_factor = Address::times(stackElementSize);
}
offset += wordSize; // return PC is on stack
return Address(rsp, scale_reg, scale_factor, offset);
} }
@ -7710,14 +8109,21 @@ void MacroAssembler::load_klass(Register dst, Register src) {
void MacroAssembler::load_prototype_header(Register dst, Register src) { void MacroAssembler::load_prototype_header(Register dst, Register src) {
#ifdef _LP64 #ifdef _LP64
if (UseCompressedOops) { if (UseCompressedOops) {
assert (Universe::heap() != NULL, "java heap should be initialized");
movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); 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 } else
#endif #endif
{ {
movptr(dst, Address(src, oopDesc::klass_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())); movptr(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
} }
} }
void MacroAssembler::store_klass(Register dst, Register src) { void MacroAssembler::store_klass(Register dst, Register src) {
@ -7760,11 +8166,20 @@ void MacroAssembler::store_heap_oop(Address dst, Register src) {
// Algorithm must match oop.inline.hpp encode_heap_oop. // Algorithm must match oop.inline.hpp encode_heap_oop.
void MacroAssembler::encode_heap_oop(Register r) { void MacroAssembler::encode_heap_oop(Register r) {
assert (UseCompressedOops, "should be compressed"); 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 #ifdef ASSERT
if (CheckCompressedOops) { if (CheckCompressedOops) {
Label ok; Label ok;
push(rscratch1); // cmpptr trashes rscratch1 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); jcc(Assembler::equal, ok);
stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); stop("MacroAssembler::encode_heap_oop: heap base corrupted?");
bind(ok); bind(ok);
@ -7780,6 +8195,7 @@ void MacroAssembler::encode_heap_oop(Register r) {
void MacroAssembler::encode_heap_oop_not_null(Register r) { void MacroAssembler::encode_heap_oop_not_null(Register r) {
assert (UseCompressedOops, "should be compressed"); assert (UseCompressedOops, "should be compressed");
assert (Universe::heap() != NULL, "java heap should be initialized");
#ifdef ASSERT #ifdef ASSERT
if (CheckCompressedOops) { if (CheckCompressedOops) {
Label ok; Label ok;
@ -7790,12 +8206,18 @@ void MacroAssembler::encode_heap_oop_not_null(Register r) {
} }
#endif #endif
verify_oop(r, "broken oop in encode_heap_oop_not_null"); verify_oop(r, "broken oop in encode_heap_oop_not_null");
subq(r, r12_heapbase); if (Universe::narrow_oop_base() != NULL) {
shrq(r, LogMinObjAlignmentInBytes); 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) { void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) {
assert (UseCompressedOops, "should be compressed"); assert (UseCompressedOops, "should be compressed");
assert (Universe::heap() != NULL, "java heap should be initialized");
#ifdef ASSERT #ifdef ASSERT
if (CheckCompressedOops) { if (CheckCompressedOops) {
Label ok; Label ok;
@ -7809,18 +8231,32 @@ void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) {
if (dst != src) { if (dst != src) {
movq(dst, src); movq(dst, src);
} }
subq(dst, r12_heapbase); if (Universe::narrow_oop_base() != NULL) {
shrq(dst, LogMinObjAlignmentInBytes); 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) { void MacroAssembler::decode_heap_oop(Register r) {
assert (UseCompressedOops, "should be compressed"); 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 #ifdef ASSERT
if (CheckCompressedOops) { if (CheckCompressedOops) {
Label ok; Label ok;
push(rscratch1); push(rscratch1);
cmpptr(r12_heapbase, cmpptr(r12_heapbase,
ExternalAddress((address)Universe::heap_base_addr())); ExternalAddress((address)Universe::narrow_oop_base_addr()));
jcc(Assembler::equal, ok); jcc(Assembler::equal, ok);
stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); stop("MacroAssembler::decode_heap_oop: heap base corrupted?");
bind(ok); bind(ok);
@ -7844,32 +8280,76 @@ void MacroAssembler::decode_heap_oop(Register r) {
void MacroAssembler::decode_heap_oop_not_null(Register r) { void MacroAssembler::decode_heap_oop_not_null(Register r) {
assert (UseCompressedOops, "should only be used for compressed headers"); 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) // Cannot assert, unverified entry point counts instructions (see .ad file)
// vtableStubs also counts instructions in pd_code_size_limit. // vtableStubs also counts instructions in pd_code_size_limit.
// Also do not verify_oop as this is called by verify_oop. // Also do not verify_oop as this is called by verify_oop.
assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); if (Universe::narrow_oop_base() == NULL) {
leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); 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) { void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) {
assert (UseCompressedOops, "should only be used for compressed headers"); 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) // Cannot assert, unverified entry point counts instructions (see .ad file)
// vtableStubs also counts instructions in pd_code_size_limit. // vtableStubs also counts instructions in pd_code_size_limit.
// Also do not verify_oop as this is called by verify_oop. // Also do not verify_oop as this is called by verify_oop.
assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); if (Universe::narrow_oop_shift() != 0) {
leaq(dst, Address(r12_heapbase, src, Address::times_8, 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) { 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); int oop_index = oop_recorder()->find_index(obj);
RelocationHolder rspec = oop_Relocation::spec(oop_index); 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() { void MacroAssembler::reinit_heapbase() {
if (UseCompressedOops) { if (UseCompressedOops) {
movptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr()));
} }
} }
#endif // _LP64 #endif // _LP64

View File

@ -212,7 +212,7 @@ class Address VALUE_OBJ_CLASS_SPEC {
"inconsistent address"); "inconsistent address");
} }
Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0) Address(Register base, RegisterOrConstant index, ScaleFactor scale = times_1, int disp = 0)
: _base (base), : _base (base),
_index(index.register_or_noreg()), _index(index.register_or_noreg()),
_scale(scale), _scale(scale),
@ -256,7 +256,7 @@ class Address VALUE_OBJ_CLASS_SPEC {
"inconsistent address"); "inconsistent address");
} }
Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp) Address(Register base, RegisterOrConstant index, ScaleFactor scale, ByteSize disp)
: _base (base), : _base (base),
_index(index.register_or_noreg()), _index(index.register_or_noreg()),
_scale(scale), _scale(scale),
@ -578,20 +578,25 @@ private:
// These are all easily abused and hence protected // 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 // 32BIT ONLY SECTION
#ifndef _LP64 #ifndef _LP64
// Make these disappear in 64bit mode since they would never be correct // 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(Register src1, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY
void cmp_literal32(Address 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 mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY
void push_literal32(int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY void push_literal32(int32_t imm32, RelocationHolder const& rspec); // 32BIT ONLY
#else #else
// 64BIT ONLY SECTION // 64BIT ONLY SECTION
void mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec); // 64BIT ONLY 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 #endif // _LP64
// These are unique in that we are ensured by the caller that the 32bit // These are unique in that we are ensured by the caller that the 32bit
@ -1063,15 +1068,23 @@ private:
LoadLoad = 1 << 0 LoadLoad = 1 << 0
}; };
// Serializes memory. // Serializes memory and blows flags
void membar(Membar_mask_bits order_constraint) { void membar(Membar_mask_bits order_constraint) {
// We only have to handle StoreLoad and LoadLoad if (os::is_MP()) {
if (order_constraint & StoreLoad) { // We only have to handle StoreLoad
// MFENCE subsumes LFENCE if (order_constraint & StoreLoad) {
mfence(); // All usable chips support "locked" instructions which suffice
} /* [jk] not needed currently: else if (order_constraint & LoadLoad) { // as barriers, and are much faster than the alternative of
lfence(); // using cpuid instruction. We use here a locked add [esp],0.
} */ // This is conveniently otherwise a no-op except for blowing
// flags.
// Any change to this code may need to revisit other places in
// the code where this idiom is used, in particular the
// orderAccess code.
lock();
addl(Address(rsp, 0), 0);// Assert the lock# signal here
}
}
} }
void mfence(); void mfence();
@ -1213,12 +1226,24 @@ private:
void orq(Register dst, Address src); void orq(Register dst, Address src);
void orq(Register dst, Register src); void orq(Register dst, Register src);
// SSE4.2 string instructions
void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
void pcmpestri(XMMRegister xmm1, Address src, int imm8);
void popl(Address dst); void popl(Address dst);
#ifdef _LP64 #ifdef _LP64
void popq(Address dst); void popq(Address dst);
#endif #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) // Prefetches (SSE, SSE2, 3DNOW only)
void prefetchnta(Address src); void prefetchnta(Address src);
@ -1239,6 +1264,10 @@ private:
// Shift Right Logical Quadword Immediate // Shift Right Logical Quadword Immediate
void psrlq(XMMRegister dst, int shift); void psrlq(XMMRegister dst, int shift);
// Logical Compare Double Quadword
void ptest(XMMRegister dst, XMMRegister src);
void ptest(XMMRegister dst, Address src);
// Interleave Low Bytes // Interleave Low Bytes
void punpcklbw(XMMRegister dst, XMMRegister src); void punpcklbw(XMMRegister dst, XMMRegister src);
@ -1647,6 +1676,9 @@ class MacroAssembler: public Assembler {
void decode_heap_oop_not_null(Register dst, Register src); void decode_heap_oop_not_null(Register dst, Register src);
void set_narrow_oop(Register dst, jobject obj); 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 // if heap base register is used - reinit it with the correct value
void reinit_heapbase(); void reinit_heapbase();
@ -1786,11 +1818,55 @@ class MacroAssembler: public Assembler {
// interface method calling // interface method calling
void lookup_interface_method(Register recv_klass, void lookup_interface_method(Register recv_klass,
Register intf_klass, Register intf_klass,
RegisterConstant itable_index, RegisterOrConstant itable_index,
Register method_result, Register method_result,
Register scan_temp, Register scan_temp,
Label& no_such_interface); 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,
RegisterOrConstant super_check_offset = RegisterOrConstant(-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);
// method handles (JSR 292)
void check_method_handle_type(Register mtype_reg, Register mh_reg,
Register temp_reg,
Label& wrong_method_type);
void load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
Register temp_reg);
void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
//---- //----
void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0 void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
@ -1833,9 +1909,9 @@ class MacroAssembler: public Assembler {
// stack overflow + shadow pages. Also, clobbers tmp // stack overflow + shadow pages. Also, clobbers tmp
void bang_stack_size(Register size, Register tmp); void bang_stack_size(Register size, Register tmp);
virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
Register tmp, Register tmp,
int offset); int offset);
// Support for serializing memory accesses between threads // Support for serializing memory accesses between threads
void serialize_memory(Register thread, Register tmp); void serialize_memory(Register thread, Register tmp);

View File

@ -1598,18 +1598,9 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
// get instance klass // get instance klass
__ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc))); __ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)));
// get super_check_offset // perform the fast part of the checking logic
__ movl(Rtmp1, Address(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes())); __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, stub->entry(), NULL);
// See if we get an immediate positive hit // call out-of-line instance of __ check_klass_subtype_slow_path(...):
__ 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);
__ push(klass_RInfo); __ push(klass_RInfo);
__ push(k_RInfo); __ push(k_RInfo);
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
@ -1735,17 +1726,9 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
} }
__ bind(done); __ bind(done);
} else { } else {
__ movl(Rtmp1, Address(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes())); // perform the fast part of the checking logic
// See if we get an immediate positive hit __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, &done, stub->entry(), NULL);
__ cmpptr(k_RInfo, Address(klass_RInfo, Rtmp1, Address::times_1)); // call out-of-line instance of __ check_klass_subtype_slow_path(...):
__ 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);
__ push(klass_RInfo); __ push(klass_RInfo);
__ push(k_RInfo); __ push(k_RInfo);
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
@ -1821,23 +1804,15 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
__ pop(dst); __ pop(dst);
__ jmp(done); __ jmp(done);
} }
} else { }
#else else // next block is unconditional if LP64:
{ // YUCK
#endif // LP64 #endif // LP64
{
assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers");
__ movl(dst, Address(k_RInfo, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes())); // perform the fast part of the checking logic
// See if we get an immediate positive hit __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, dst, &one, &zero, NULL);
__ cmpptr(k_RInfo, Address(klass_RInfo, dst, Address::times_1)); // call out-of-line instance of __ check_klass_subtype_slow_path(...):
__ 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);
__ push(klass_RInfo); __ push(klass_RInfo);
__ push(k_RInfo); __ push(k_RInfo);
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));

View File

@ -1354,6 +1354,13 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
case slow_subtype_check_id: 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 { enum layout {
rax_off, SLOT2(raxH_off) rax_off, SLOT2(raxH_off)
rcx_off, SLOT2(rcxH_off) rcx_off, SLOT2(rcxH_off)
@ -1361,9 +1368,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
rdi_off, SLOT2(rdiH_off) rdi_off, SLOT2(rdiH_off)
// saved_rbp_off, SLOT2(saved_rbpH_off) // saved_rbp_off, SLOT2(saved_rbpH_off)
return_off, SLOT2(returnH_off) return_off, SLOT2(returnH_off)
sub_off, SLOT2(subH_off) sup_k_off, SLOT2(sup_kH_off)
super_off, SLOT2(superH_off) klass_off, SLOT2(superH_off)
framesize framesize,
result_off = klass_off // deepest argument is also the return value
}; };
__ set_info("slow_subtype_check", dont_gc_arguments); __ set_info("slow_subtype_check", dont_gc_arguments);
@ -1373,19 +1381,14 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ push(rax); __ push(rax);
// This is called by pushing args and not with C abi // This is called by pushing args and not with C abi
__ movptr(rsi, Address(rsp, (super_off) * VMRegImpl::stack_slot_size)); // super __ movptr(rsi, Address(rsp, (klass_off) * VMRegImpl::stack_slot_size)); // subclass
__ movptr(rax, Address(rsp, (sub_off ) * VMRegImpl::stack_slot_size)); // sub __ movptr(rax, Address(rsp, (sup_k_off) * VMRegImpl::stack_slot_size)); // superclass
__ 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));
Label miss; Label miss;
__ repne_scan(); __ check_klass_subtype_slow_path(rsi, rax, rcx, rdi, NULL, &miss);
__ jcc(Assembler::notEqual, miss);
__ movptr(Address(rsi,sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()), rax); // fallthrough on success:
__ movptr(Address(rsp, (super_off) * VMRegImpl::stack_slot_size), 1); // result __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), 1); // result
__ pop(rax); __ pop(rax);
__ pop(rcx); __ pop(rcx);
__ pop(rsi); __ pop(rsi);
@ -1393,7 +1396,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ ret(0); __ ret(0);
__ bind(miss); __ 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(rax);
__ pop(rcx); __ pop(rcx);
__ pop(rsi); __ pop(rsi);

View File

@ -513,10 +513,11 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
// compute full expression stack limit // compute full expression stack limit
const Address size_of_stack (rbx, methodOopDesc::max_stack_offset()); const Address size_of_stack (rbx, methodOopDesc::max_stack_offset());
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_words();
__ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words __ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words
__ negptr(rdx); // so we can subtract in next step __ negptr(rdx); // so we can subtract in next step
// Allocate expression stack // Allocate expression stack
__ lea(rsp, Address(rsp, rdx, Address::times_ptr)); __ lea(rsp, Address(rsp, rdx, Address::times_ptr, -extra_stack));
__ movptr(STATE(_stack_limit), rsp); __ movptr(STATE(_stack_limit), rsp);
} }
@ -659,8 +660,9 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
// Always give one monitor to allow us to start interp if sync method. // Always give one monitor to allow us to start interp if sync method.
// Any additional monitors need a check when moving the expression stack // Any additional monitors need a check when moving the expression stack
const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize; const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
__ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words __ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words
__ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor)); __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), extra_stack + one_monitor));
__ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size)); __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
#ifdef ASSERT #ifdef ASSERT
@ -2185,6 +2187,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
case Interpreter::java_lang_math_sin : // fall thru case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru case Interpreter::java_lang_math_cos : // fall thru
@ -2224,7 +2227,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
const int overhead_size = sizeof(BytecodeInterpreter)/wordSize + const int overhead_size = sizeof(BytecodeInterpreter)/wordSize +
( frame::sender_sp_offset - frame::link_offset) + 2; ( frame::sender_sp_offset - frame::link_offset) + 2;
const int method_stack = (method->max_locals() + method->max_stack()) * const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
Interpreter::stackElementWords(); Interpreter::stackElementWords();
return overhead_size + method_stack + stub_code; return overhead_size + method_stack + stub_code;
} }
@ -2289,7 +2293,8 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
// Need +1 here because stack_base points to the word just above the first expr stack entry // Need +1 here because stack_base points to the word just above the first expr stack entry
// and stack_limit is supposed to point to the word just below the last expr stack entry. // and stack_limit is supposed to point to the word just below the last expr stack entry.
// See generate_compute_interpreter_state. // See generate_compute_interpreter_state.
to_fill->_stack_limit = stack_base - (method->max_stack() + 1); int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
to_fill->_stack_limit = stack_base - (method->max_stack() + extra_stack + 1);
to_fill->_monitor_base = (BasicObjectLock*) monitor_base; to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
to_fill->_self_link = to_fill; to_fill->_self_link = to_fill;
@ -2335,7 +2340,8 @@ int AbstractInterpreter::layout_activation(methodOop method,
monitor_size); monitor_size);
// Now with full size expression stack // Now with full size expression stack
int full_frame_size = short_frame_size + method->max_stack() * BytesPerWord; int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
int full_frame_size = short_frame_size + (method->max_stack() + extra_stack) * BytesPerWord;
// and now with only live portion of the expression stack // and now with only live portion of the expression stack
short_frame_size = short_frame_size + tempcount * BytesPerWord; short_frame_size = short_frame_size + tempcount * BytesPerWord;

View File

@ -60,6 +60,7 @@ define_pd_global(uintx, NewSize, 1024 * K);
define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1)); define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
#endif // AMD64 #endif // AMD64
define_pd_global(intx, InlineFrequencyCount, 100); define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000);
define_pd_global(intx, PreInflateSpin, 10); define_pd_global(intx, PreInflateSpin, 10);
define_pd_global(intx, StackYellowPages, 2); define_pd_global(intx, StackYellowPages, 2);

View File

@ -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. // 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 ) { void InterpreterMacroAssembler::gen_subtype_check( Register Rsub_klass, Label &ok_is_subtype ) {
assert( Rsub_klass != rax, "rax, holds superklass" ); assert( Rsub_klass != rax, "rax, holds superklass" );
assert( Rsub_klass != rcx, "rcx holds 2ndary super array length" ); assert( Rsub_klass != rcx, "used as a temp" );
assert( Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr" ); assert( Rsub_klass != rdi, "used as a temp, restored from locals" );
Label not_subtype, loop;
// Profile the not-null value's klass. // 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 // Do the check.
movl( rcx, Address(rax, sizeof(oopDesc) + Klass::super_check_offset_offset_in_bytes() ) ); check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx
// 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 );
// Check for immediate negative hit // Profile the failure of the check.
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_typecheck_failed(rcx); // blows rcx profile_typecheck_failed(rcx); // blows rcx
} }
@ -586,13 +555,18 @@ void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register
} }
// Jump to from_interpreted entry of a call unless single stepping is possible void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// in this thread in which case we must call the i2i entry
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
// set sender sp // set sender sp
lea(rsi, Address(rsp, wordSize)); lea(rsi, Address(rsp, wordSize));
// record last_sp // record last_sp
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi); movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi);
}
// Jump to from_interpreted entry of a call unless single stepping is possible
// in this thread in which case we must call the i2i entry
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
prepare_to_jump_from_interpreted();
if (JvmtiExport::can_post_interpreter_events()) { if (JvmtiExport::can_post_interpreter_events()) {
Label run_compiled_code; Label run_compiled_code;

View File

@ -161,6 +161,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
// jump to an invoked target // jump to an invoked target
void prepare_to_jump_from_interpreted();
void jump_from_interpreted(Register method, Register temp); void jump_from_interpreted(Register method, Register temp);
// Returning from interpreted functions // Returning from interpreted functions

View File

@ -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 != rcx, "rcx holds 2ndary super array length");
assert(Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr"); 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 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 // Do the check.
movl(rcx, Address(rax, sizeof(oopDesc) + check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx
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);
// Check for immediate negative hit // Profile the failure of the check.
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_typecheck_failed(rcx); // blows rcx profile_typecheck_failed(rcx); // blows rcx
} }
@ -603,13 +551,18 @@ void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point,
MacroAssembler::call_VM_leaf_base(entry_point, 3); MacroAssembler::call_VM_leaf_base(entry_point, 3);
} }
// Jump to from_interpreted entry of a call unless single stepping is possible void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// in this thread in which case we must call the i2i entry
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
// set sender sp // set sender sp
lea(r13, Address(rsp, wordSize)); lea(r13, Address(rsp, wordSize));
// record last_sp // record last_sp
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13); movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
}
// Jump to from_interpreted entry of a call unless single stepping is possible
// in this thread in which case we must call the i2i entry
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
prepare_to_jump_from_interpreted();
if (JvmtiExport::can_post_interpreter_events()) { if (JvmtiExport::can_post_interpreter_events()) {
Label run_compiled_code; Label run_compiled_code;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2008 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -176,6 +176,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void dispatch_via (TosState state, address* table); void dispatch_via (TosState state, address* table);
// jump to an invoked target // jump to an invoked target
void prepare_to_jump_from_interpreted();
void jump_from_interpreted(Register method, Register temp); void jump_from_interpreted(Register method, Register temp);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 1997-2007 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -32,6 +32,7 @@
address generate_normal_entry(bool synchronized); address generate_normal_entry(bool synchronized);
address generate_native_entry(bool synchronized); address generate_native_entry(bool synchronized);
address generate_abstract_entry(void); address generate_abstract_entry(void);
address generate_method_handle_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind); address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void); address generate_empty_entry(void);
address generate_accessor_entry(void); address generate_accessor_entry(void);

View File

@ -349,7 +349,7 @@ class SlowSignatureHandler
if (_num_args < Argument::n_float_register_parameters_c-1) { if (_num_args < Argument::n_float_register_parameters_c-1) {
*_reg_args++ = from_obj; *_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++; _num_args++;
} else { } else {
*_to++ = from_obj; *_to++ = from_obj;
@ -364,7 +364,7 @@ class SlowSignatureHandler
if (_num_args < Argument::n_float_register_parameters_c-1) { if (_num_args < Argument::n_float_register_parameters_c-1) {
*_reg_args++ = from_obj; *_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++; _num_args++;
} else { } else {
*_to++ = from_obj; *_to++ = from_obj;

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -201,11 +201,12 @@ address InterpreterGenerator::generate_abstract_entry(void) {
address entry_point = __ pc(); address entry_point = __ pc();
// abstract method entry // abstract method entry
// remove return address. Not really needed, since exception handling throws away expression stack
__ pop(rbx);
// adjust stack to what a normal return would do // pop return address, reset last_sp to NULL
__ mov(rsp, rsi); __ empty_expression_stack();
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
// throw exception // throw exception
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
// the call_VM checks for exception, so we should never return here. // the call_VM checks for exception, so we should never return here.
@ -214,6 +215,20 @@ address InterpreterGenerator::generate_abstract_entry(void) {
return entry_point; return entry_point;
} }
// Method handle invoker
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) {
return generate_abstract_entry();
}
address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm);
return entry_point;
}
// This method tells the deoptimizer how big an interpreted frame must be: // This method tells the deoptimizer how big an interpreted frame must be:
int AbstractInterpreter::size_activation(methodOop method, int AbstractInterpreter::size_activation(methodOop method,
int tempcount, int tempcount,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2008 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -294,6 +294,16 @@ address InterpreterGenerator::generate_abstract_entry(void) {
} }
// Method handle invoker
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
address InterpreterGenerator::generate_method_handle_entry(void) {
if (!EnableMethodHandles) {
return generate_abstract_entry();
}
return generate_abstract_entry(); //6815692//
}
// Empty method, generate a very fast return. // Empty method, generate a very fast return.
address InterpreterGenerator::generate_empty_entry(void) { address InterpreterGenerator::generate_empty_entry(void) {

File diff suppressed because it is too large Load Diff

View File

@ -2691,7 +2691,7 @@ void SharedRuntime::generate_deopt_blob() {
__ mov(rdi, rax); __ mov(rdi, rax);
Label noException; Label noException;
__ cmpl(r12, Deoptimization::Unpack_exception); // Was exception pending? __ cmpl(r14, Deoptimization::Unpack_exception); // Was exception pending?
__ jcc(Assembler::notEqual, noException); __ jcc(Assembler::notEqual, noException);
__ movptr(rax, Address(r15_thread, JavaThread::exception_oop_offset())); __ movptr(rax, Address(r15_thread, JavaThread::exception_oop_offset()));
// QQQ this is useless it was NULL above // QQQ this is useless it was NULL above

View File

@ -1310,81 +1310,51 @@ class StubGenerator: public StubCodeGenerator {
Address& super_check_offset_addr, Address& super_check_offset_addr,
Address& super_klass_addr, Address& super_klass_addr,
Register temp, Register temp,
Label* L_success_ptr, Label* L_failure_ptr) { Label* L_success, Label* L_failure) {
BLOCK_COMMENT("type_check:"); BLOCK_COMMENT("type_check:");
Label L_fallthrough; Label L_fallthrough;
bool fall_through_on_success = (L_success_ptr == NULL); #define LOCAL_JCC(assembler_con, label_ptr) \
if (fall_through_on_success) { if (label_ptr != NULL) __ jcc(assembler_con, *(label_ptr)); \
L_success_ptr = &L_fallthrough; else __ jcc(assembler_con, L_fallthrough) /*omit semi*/
} else {
L_failure_ptr = &L_fallthrough;
}
Label& L_success = *L_success_ptr;
Label& L_failure = *L_failure_ptr;
// 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); 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 + int sc_offset = (klassOopDesc::header_size() * HeapWordSize +
Klass::secondary_super_cache_offset_in_bytes()); 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) // if the pointers are equal, we are done (e.g., String[] elements)
__ cmpptr(sub_klass, super_klass_addr); __ cmpptr(sub_klass, super_klass_addr);
__ jcc(Assembler::equal, L_success); LOCAL_JCC(Assembler::equal, L_success);
// check the supertype display: // check the supertype display:
__ movl2ptr(temp, super_check_offset_addr); __ movl2ptr(temp, super_check_offset_addr);
Address super_check_addr(sub_klass, temp, Address::times_1, 0); Address super_check_addr(sub_klass, temp, Address::times_1, 0);
__ movptr(temp, super_check_addr); // load displayed supertype __ movptr(temp, super_check_addr); // load displayed supertype
__ cmpptr(temp, super_klass_addr); // test the super type __ 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 // if it was a primary super, we can just fail immediately
__ cmpl(super_check_offset_addr, sc_offset); __ 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. // The repne_scan instruction uses fixed registers, which will get spilled.
// This code is rarely used, so simplicity is a virtue here. // We happen to know this works best when super_klass is in rax.
inc_counter_np(SharedRuntime::_partial_subtype_ctr); Register super_klass = temp;
{ __ movptr(super_klass, super_klass_addr);
// The repne_scan instruction uses fixed registers, which we must spill. __ check_klass_subtype_slow_path(sub_klass, super_klass, noreg, noreg,
// (We need a couple more temps in any case.) L_success, L_failure);
__ push(rax);
__ push(rcx);
__ push(rdi);
assert_different_registers(sub_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 [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); __ bind(L_fallthrough);
if (L_success == NULL) { BLOCK_COMMENT("L_success:"); }
if (L_failure == NULL) { BLOCK_COMMENT("L_failure:"); }
#undef LOCAL_JCC
} }
// //
@ -2249,6 +2219,16 @@ class StubGenerator: public StubCodeGenerator {
// arraycopy stubs used by compilers // arraycopy stubs used by compilers
generate_arraycopy_stubs(); generate_arraycopy_stubs();
// generic method handle stubs
if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
ek < MethodHandles::_EK_LIMIT;
ek = MethodHandles::EntryKind(1 + (int)ek)) {
StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
MethodHandles::generate_method_handle_stub(_masm, ek);
}
}
} }

View File

@ -637,7 +637,7 @@ class StubGenerator: public StubCodeGenerator {
address generate_orderaccess_fence() { address generate_orderaccess_fence() {
StubCodeMark mark(this, "StubRoutines", "orderaccess_fence"); StubCodeMark mark(this, "StubRoutines", "orderaccess_fence");
address start = __ pc(); address start = __ pc();
__ mfence(); __ membar(Assembler::StoreLoad);
__ ret(0); __ ret(0);
return start; return start;
@ -2091,66 +2091,9 @@ class StubGenerator: public StubCodeGenerator {
Label L_miss; Label L_miss;
// a couple of useful fields in sub_klass: __ check_klass_subtype_fast_path(sub_klass, super_klass, noreg, &L_success, &L_miss, NULL,
int ss_offset = (klassOopDesc::header_size() * HeapWordSize + super_check_offset);
Klass::secondary_supers_offset_in_bytes()); __ check_klass_subtype_slow_path(sub_klass, super_klass, noreg, noreg, &L_success, NULL);
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);
// Fall through on failure! // Fall through on failure!
__ BIND(L_miss); __ BIND(L_miss);

View File

@ -92,6 +92,33 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
return entry; return entry;
} }
// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
// pc at TOS (just for debugging)
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
address entry = __ pc();
__ pop(rbx); // actual failing object is at TOS
__ pop(rax); // required type is at TOS+4
__ verify_oop(rbx);
__ verify_oop(rax);
// Various method handle types use interpreter registers as temps.
__ restore_bcp();
__ restore_locals();
// Expression stack must be empty before entering the VM for an exception.
__ empty_expression_stack();
__ empty_FPU_stack();
__ call_VM(noreg,
CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_WrongMethodTypeException),
// pass required type, failing object (or NULL)
rax, rbx);
return entry;
}
address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) { address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) {
assert(!pass_oop || message == NULL, "either oop or message but not both"); assert(!pass_oop || message == NULL, "either oop or message but not both");
address entry = __ pc(); address entry = __ pc();
@ -1370,6 +1397,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
case Interpreter::java_lang_math_sin : // fall thru case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru case Interpreter::java_lang_math_cos : // fall thru
@ -1400,7 +1428,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
// be sure to change this if you add/subtract anything to/from the overhead area // be sure to change this if you add/subtract anything to/from the overhead area
const int overhead_size = -frame::interpreter_frame_initial_sp_offset; const int overhead_size = -frame::interpreter_frame_initial_sp_offset;
const int method_stack = (method->max_locals() + method->max_stack()) * const int extra_stack = methodOopDesc::extra_stack_entries();
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
Interpreter::stackElementWords(); Interpreter::stackElementWords();
return overhead_size + method_stack + stub_code; return overhead_size + method_stack + stub_code;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2008 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -100,6 +100,26 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
return entry; return entry;
} }
// Arguments are: required type in rarg1, failing object (or NULL) in rarg2
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
address entry = __ pc();
__ pop(c_rarg2); // failing object is at TOS
__ pop(c_rarg1); // required type is at TOS+8
// expression stack must be empty before entering the VM if an
// exception happened
__ empty_expression_stack();
__ call_VM(noreg,
CAST_FROM_FN_PTR(address,
InterpreterRuntime::
throw_WrongMethodTypeException),
// pass required type, failing object (or NULL)
c_rarg1, c_rarg2);
return entry;
}
address TemplateInterpreterGenerator::generate_exception_handler_common( address TemplateInterpreterGenerator::generate_exception_handler_common(
const char* name, const char* message, bool pass_oop) { const char* name, const char* message, bool pass_oop) {
assert(!pass_oop || message == NULL, "either oop or message but not both"); assert(!pass_oop || message == NULL, "either oop or message but not both");
@ -1393,12 +1413,14 @@ address AbstractInterpreterGenerator::generate_method_entry(
case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break; case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break;
case Interpreter::java_lang_math_sin : break; case Interpreter::method_handle : entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();break;
case Interpreter::java_lang_math_cos : break;
case Interpreter::java_lang_math_tan : break; case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_abs : break; case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_log : break; case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_log10 : break; case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break; case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break;
default : ShouldNotReachHere(); break; default : ShouldNotReachHere(); break;
} }
@ -1422,7 +1444,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
-(frame::interpreter_frame_initial_sp_offset) + entry_size; -(frame::interpreter_frame_initial_sp_offset) + entry_size;
const int stub_code = frame::entry_frame_after_call_words; const int stub_code = frame::entry_frame_after_call_words;
const int method_stack = (method->max_locals() + method->max_stack()) * const int extra_stack = methodOopDesc::extra_stack_entries();
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
Interpreter::stackElementWords(); Interpreter::stackElementWords();
return (overhead_size + method_stack + stub_code); return (overhead_size + method_stack + stub_code);
} }

View File

@ -284,7 +284,7 @@ void VM_Version::get_processor_features() {
} }
char buf[256]; 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(), cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""), (supports_cmov() ? ", cmov" : ""),
@ -297,6 +297,7 @@ void VM_Version::get_processor_features() {
(supports_ssse3()? ", ssse3": ""), (supports_ssse3()? ", ssse3": ""),
(supports_sse4_1() ? ", sse4.1" : ""), (supports_sse4_1() ? ", sse4.1" : ""),
(supports_sse4_2() ? ", sse4.2" : ""), (supports_sse4_2() ? ", sse4.2" : ""),
(supports_popcnt() ? ", popcnt" : ""),
(supports_mmx_ext() ? ", mmxext" : ""), (supports_mmx_ext() ? ", mmxext" : ""),
(supports_3dnow() ? ", 3dnow" : ""), (supports_3dnow() ? ", 3dnow" : ""),
(supports_3dnow2() ? ", 3dnowext" : ""), (supports_3dnow2() ? ", 3dnowext" : ""),
@ -407,6 +408,18 @@ void VM_Version::get_processor_features() {
UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
} }
} }
if( supports_sse4_2() && UseSSE >= 4 ) {
if( FLAG_IS_DEFAULT(UseSSE42Intrinsics)) {
UseSSE42Intrinsics = true;
}
}
}
}
// Use population count instruction if available.
if (supports_popcnt()) {
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
UsePopCountInstruction = true;
} }
} }

View File

@ -70,7 +70,9 @@ public:
dca : 1, dca : 1,
sse4_1 : 1, sse4_1 : 1,
sse4_2 : 1, sse4_2 : 1,
: 11; : 2,
popcnt : 1,
: 8;
} bits; } bits;
}; };
@ -179,7 +181,8 @@ protected:
CPU_SSSE3 = (1 << 9), CPU_SSSE3 = (1 << 9),
CPU_SSE4A = (1 << 10), CPU_SSE4A = (1 << 10),
CPU_SSE4_1 = (1 << 11), CPU_SSE4_1 = (1 << 11),
CPU_SSE4_2 = (1 << 12) CPU_SSE4_2 = (1 << 12),
CPU_POPCNT = (1 << 13)
} cpuFeatureFlags; } cpuFeatureFlags;
// cpuid information block. All info derived from executing cpuid with // cpuid information block. All info derived from executing cpuid with
@ -290,6 +293,8 @@ protected:
result |= CPU_SSE4_1; result |= CPU_SSE4_1;
if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0) if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
result |= CPU_SSE4_2; result |= CPU_SSE4_2;
if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
result |= CPU_POPCNT;
return result; return result;
} }
@ -379,6 +384,7 @@ public:
static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; } static bool supports_ssse3() { return (_cpuFeatures & CPU_SSSE3)!= 0; }
static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 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_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; }
static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; }
// //
// AMD features // AMD features
// //

View File

@ -108,6 +108,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
} }
guarantee(__ pc() <= s->code_end(), "overflowed buffer"); guarantee(__ pc() <= s->code_end(), "overflowed buffer");
// shut the door on sizing bugs
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
s->set_exception_points(npe_addr, ame_addr); s->set_exception_points(npe_addr, ame_addr);
return s; return s;
@ -181,6 +184,9 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
} }
guarantee(__ pc() <= s->code_end(), "overflowed buffer"); guarantee(__ pc() <= s->code_end(), "overflowed buffer");
// shut the door on sizing bugs
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
s->set_exception_points(npe_addr, ame_addr); s->set_exception_points(npe_addr, ame_addr);
return s; return s;
@ -196,6 +202,41 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
// Itable stub size // Itable stub size
return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0);
} }
// In order to tune these parameters, run the JVM with VM options
// +PrintMiscellaneous and +WizardMode to see information about
// actual itable stubs. Look for lines like this:
// itable #1 at 0x5551212[65] left over: 3
// Reduce the constants so that the "left over" number is >=3
// for the common cases.
// Do not aim at a left-over number of zero, because a
// large vtable or itable index (> 16) will require a 32-bit
// immediate displacement instead of an 8-bit one.
//
// The JVM98 app. _202_jess has a megamorphic interface call.
// The itable code looks like this:
// Decoding VtableStub itbl[1]@1
// mov 0x4(%ecx),%esi
// mov 0xe8(%esi),%edi
// lea 0x130(%esi,%edi,4),%edi
// add $0x7,%edi
// and $0xfffffff8,%edi
// lea 0x4(%esi),%esi
// mov (%edi),%ebx
// cmp %ebx,%eax
// je success
// loop:
// test %ebx,%ebx
// je throw_icce
// add $0x8,%edi
// mov (%edi),%ebx
// cmp %ebx,%eax
// jne loop
// success:
// mov 0x4(%edi),%edi
// mov (%esi,%edi,1),%ebx
// jmp *0x44(%ebx)
// throw_icce:
// jmp throw_ICCE_entry
} }
int VtableStub::pd_code_alignment() { int VtableStub::pd_code_alignment() {

View File

@ -106,6 +106,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
} }
guarantee(__ pc() <= s->code_end(), "overflowed buffer"); guarantee(__ pc() <= s->code_end(), "overflowed buffer");
// shut the door on sizing bugs
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
s->set_exception_points(npe_addr, ame_addr); s->set_exception_points(npe_addr, ame_addr);
return s; return s;
@ -191,6 +194,9 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
} }
guarantee(__ pc() <= s->code_end(), "overflowed buffer"); guarantee(__ pc() <= s->code_end(), "overflowed buffer");
// shut the door on sizing bugs
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
s->set_exception_points(npe_addr, ame_addr); s->set_exception_points(npe_addr, ame_addr);
return s; return s;
@ -206,6 +212,39 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) + return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) +
(UseCompressedOops ? 32 : 0); // 2 leaqs (UseCompressedOops ? 32 : 0); // 2 leaqs
} }
// In order to tune these parameters, run the JVM with VM options
// +PrintMiscellaneous and +WizardMode to see information about
// actual itable stubs. Look for lines like this:
// itable #1 at 0x5551212[71] left over: 3
// Reduce the constants so that the "left over" number is >=3
// for the common cases.
// Do not aim at a left-over number of zero, because a
// large vtable or itable index (>= 32) will require a 32-bit
// immediate displacement instead of an 8-bit one.
//
// The JVM98 app. _202_jess has a megamorphic interface call.
// The itable code looks like this:
// Decoding VtableStub itbl[1]@12
// mov 0x8(%rsi),%r10
// mov 0x198(%r10),%r11d
// lea 0x218(%r10,%r11,8),%r11
// lea 0x8(%r10),%r10
// mov (%r11),%rbx
// cmp %rbx,%rax
// je success
// loop:
// test %rbx,%rbx
// je throw_icce
// add $0x10,%r11
// mov (%r11),%rbx
// cmp %rbx,%rax
// jne loop
// success:
// mov 0x8(%r11),%r11d
// mov (%r10,%r11,1),%rbx
// jmpq *0x60(%rbx)
// throw_icce:
// jmpq throw_ICCE_entry
} }
int VtableStub::pd_code_alignment() { int VtableStub::pd_code_alignment() {

View File

@ -1483,16 +1483,20 @@ encode %{
// main source block for now. In future, we can generalize this by // main source block for now. In future, we can generalize this by
// adding a syntax that specifies the sizes of fields in an order, // adding a syntax that specifies the sizes of fields in an order,
// so that the adlc can build the emit functions automagically // 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 secondary opcode
emit_opcode(cbuf,$secondary); enc_class OpcS %{
emit_opcode(cbuf, $secondary);
%} %}
enc_class Opcode(immI d8 ) %{ // Emit opcode // Emit opcode directly
emit_opcode(cbuf,$d8$$constant); enc_class Opcode(immI d8) %{
emit_opcode(cbuf, $d8$$constant);
%} %}
enc_class SizePrefix %{ enc_class SizePrefix %{
@ -1688,26 +1692,15 @@ encode %{
Register Reax = as_Register(EAX_enc); // super class Register Reax = as_Register(EAX_enc); // super class
Register Recx = as_Register(ECX_enc); // killed Register Recx = as_Register(ECX_enc); // killed
Register Resi = as_Register(ESI_enc); // sub class Register Resi = as_Register(ESI_enc); // sub class
Label hit, miss; Label miss;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
// Compare super with sub directly, since super is not in its own SSA. __ check_klass_subtype_slow_path(Resi, Reax, Recx, Redi,
// The compiler used to emit this test, but we fold it in here, NULL, &miss,
// to allow platform-specific tweaking on sparc. /*set_cond_codes:*/ true);
__ cmpptr(Reax, Resi); if ($primary) {
__ jcc(Assembler::equal, hit); __ xorptr(Redi, Redi);
#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);
__ bind(miss); __ bind(miss);
%} %}
@ -3701,12 +3694,16 @@ encode %{
} }
%} %}
enc_class enc_String_Compare() %{ enc_class enc_String_Compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
eAXRegI tmp3, eBXRegI tmp4, eCXRegI result) %{
Label ECX_GOOD_LABEL, LENGTH_DIFF_LABEL, Label ECX_GOOD_LABEL, LENGTH_DIFF_LABEL,
POP_LABEL, DONE_LABEL, CONT_LABEL, POP_LABEL, DONE_LABEL, CONT_LABEL,
WHILE_HEAD_LABEL; WHILE_HEAD_LABEL;
MacroAssembler masm(&cbuf); MacroAssembler masm(&cbuf);
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
// Get the first character position in both strings // Get the first character position in both strings
// [8] char array, [12] offset, [16] count // [8] char array, [12] offset, [16] count
int value_offset = java_lang_String::value_offset_in_bytes(); int value_offset = java_lang_String::value_offset_in_bytes();
@ -3724,7 +3721,6 @@ encode %{
// Compute the minimum of the string lengths(rsi) and the // Compute the minimum of the string lengths(rsi) and the
// difference of the string lengths (stack) // difference of the string lengths (stack)
if (VM_Version::supports_cmov()) { if (VM_Version::supports_cmov()) {
masm.movl(rdi, Address(rdi, count_offset)); masm.movl(rdi, Address(rdi, count_offset));
masm.movl(rsi, Address(rsi, count_offset)); masm.movl(rsi, Address(rsi, count_offset));
@ -3738,7 +3734,7 @@ encode %{
masm.movl(rsi, rdi); masm.movl(rsi, rdi);
masm.subl(rdi, rcx); masm.subl(rdi, rcx);
masm.push(rdi); masm.push(rdi);
masm.jcc(Assembler::lessEqual, ECX_GOOD_LABEL); masm.jccb(Assembler::lessEqual, ECX_GOOD_LABEL);
masm.movl(rsi, rcx); masm.movl(rsi, rcx);
// rsi holds min, rcx is unused // rsi holds min, rcx is unused
} }
@ -3763,7 +3759,7 @@ encode %{
Label LSkip2; Label LSkip2;
// Check if the strings start at same location // Check if the strings start at same location
masm.cmpptr(rbx,rax); masm.cmpptr(rbx,rax);
masm.jcc(Assembler::notEqual, LSkip2); masm.jccb(Assembler::notEqual, LSkip2);
// Check if the length difference is zero (from stack) // Check if the length difference is zero (from stack)
masm.cmpl(Address(rsp, 0), 0x0); masm.cmpl(Address(rsp, 0), 0x0);
@ -3773,9 +3769,52 @@ encode %{
masm.bind(LSkip2); masm.bind(LSkip2);
} }
// Shift rax, and rbx, to the end of the arrays, negate min // Advance to next character
masm.lea(rax, Address(rax, rsi, Address::times_2, 2)); masm.addptr(rax, 2);
masm.lea(rbx, Address(rbx, rsi, Address::times_2, 2)); masm.addptr(rbx, 2);
if (UseSSE42Intrinsics) {
// With SSE4.2, use double quad vector compare
Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
// Setup to compare 16-byte vectors
masm.movl(rdi, rsi);
masm.andl(rsi, 0xfffffff8); // rsi holds the vector count
masm.andl(rdi, 0x00000007); // rdi holds the tail count
masm.testl(rsi, rsi);
masm.jccb(Assembler::zero, COMPARE_TAIL);
masm.lea(rax, Address(rax, rsi, Address::times_2));
masm.lea(rbx, Address(rbx, rsi, Address::times_2));
masm.negl(rsi);
masm.bind(COMPARE_VECTORS);
masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2));
masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2));
masm.pxor(tmp1Reg, tmp2Reg);
masm.ptest(tmp1Reg, tmp1Reg);
masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
masm.addl(rsi, 8);
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
masm.jmpb(COMPARE_TAIL);
// Mismatched characters in the vectors
masm.bind(VECTOR_NOT_EQUAL);
masm.lea(rax, Address(rax, rsi, Address::times_2));
masm.lea(rbx, Address(rbx, rsi, Address::times_2));
masm.movl(rdi, 8);
// Compare tail (< 8 chars), or rescan last vectors to
// find 1st mismatched characters
masm.bind(COMPARE_TAIL);
masm.testl(rdi, rdi);
masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL);
masm.movl(rsi, rdi);
// Fallthru to tail compare
}
//Shift rax, and rbx, to the end of the arrays, negate min
masm.lea(rax, Address(rax, rsi, Address::times_2, 0));
masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0));
masm.negl(rsi); masm.negl(rsi);
// Compare the rest of the characters // Compare the rest of the characters
@ -3783,93 +3822,329 @@ encode %{
masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0)); masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0)); masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
masm.subl(rcx, rdi); masm.subl(rcx, rdi);
masm.jcc(Assembler::notZero, POP_LABEL); masm.jccb(Assembler::notZero, POP_LABEL);
masm.incrementl(rsi); masm.incrementl(rsi);
masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL); masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL);
// Strings are equal up to min length. Return the length difference. // Strings are equal up to min length. Return the length difference.
masm.bind(LENGTH_DIFF_LABEL); masm.bind(LENGTH_DIFF_LABEL);
masm.pop(rcx); masm.pop(rcx);
masm.jmp(DONE_LABEL); masm.jmpb(DONE_LABEL);
// Discard the stored length difference // Discard the stored length difference
masm.bind(POP_LABEL); masm.bind(POP_LABEL);
masm.addptr(rsp, 4); masm.addptr(rsp, 4);
// That's it // That's it
masm.bind(DONE_LABEL); masm.bind(DONE_LABEL);
%} %}
enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result) %{ enc_class enc_String_Equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP; eBXRegI tmp3, eCXRegI tmp4, eAXRegI result) %{
Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR;
MacroAssembler masm(&cbuf); MacroAssembler masm(&cbuf);
Register ary1Reg = as_Register($ary1$$reg); XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
Register ary2Reg = as_Register($ary2$$reg); XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
Register tmp1Reg = as_Register($tmp1$$reg);
Register tmp2Reg = as_Register($tmp2$$reg); int value_offset = java_lang_String::value_offset_in_bytes();
Register resultReg = as_Register($result$$reg); int offset_offset = java_lang_String::offset_offset_in_bytes();
int count_offset = java_lang_String::count_offset_in_bytes();
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
// does source == target string?
masm.cmpptr(rdi, rsi);
masm.jcc(Assembler::equal, RET_TRUE);
// get and compare counts
masm.movl(rcx, Address(rdi, count_offset));
masm.movl(rax, Address(rsi, count_offset));
masm.cmpl(rcx, rax);
masm.jcc(Assembler::notEqual, RET_FALSE);
masm.testl(rax, rax);
masm.jcc(Assembler::zero, RET_TRUE);
// get source string offset and value
masm.movptr(rbx, Address(rsi, value_offset));
masm.movl(rax, Address(rsi, offset_offset));
masm.leal(rsi, Address(rbx, rax, Address::times_2, base_offset));
// get compare string offset and value
masm.movptr(rbx, Address(rdi, value_offset));
masm.movl(rax, Address(rdi, offset_offset));
masm.leal(rdi, Address(rbx, rax, Address::times_2, base_offset));
// Set byte count
masm.shll(rcx, 1);
masm.movl(rax, rcx);
if (UseSSE42Intrinsics) {
// With SSE4.2, use double quad vector compare
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
// Compare 16-byte vectors
masm.andl(rcx, 0xfffffff0); // vector count (in bytes)
masm.andl(rax, 0x0000000e); // tail count (in bytes)
masm.testl(rcx, rcx);
masm.jccb(Assembler::zero, COMPARE_TAIL);
masm.lea(rdi, Address(rdi, rcx, Address::times_1));
masm.lea(rsi, Address(rsi, rcx, Address::times_1));
masm.negl(rcx);
masm.bind(COMPARE_WIDE_VECTORS);
masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1));
masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1));
masm.pxor(tmp1Reg, tmp2Reg);
masm.ptest(tmp1Reg, tmp1Reg);
masm.jccb(Assembler::notZero, RET_FALSE);
masm.addl(rcx, 16);
masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
masm.bind(COMPARE_TAIL);
masm.movl(rcx, rax);
// Fallthru to tail compare
}
// Compare 4-byte vectors
masm.andl(rcx, 0xfffffffc); // vector count (in bytes)
masm.andl(rax, 0x00000002); // tail char (in bytes)
masm.testl(rcx, rcx);
masm.jccb(Assembler::zero, COMPARE_CHAR);
masm.lea(rdi, Address(rdi, rcx, Address::times_1));
masm.lea(rsi, Address(rsi, rcx, Address::times_1));
masm.negl(rcx);
masm.bind(COMPARE_VECTORS);
masm.movl(rbx, Address(rdi, rcx, Address::times_1));
masm.cmpl(rbx, Address(rsi, rcx, Address::times_1));
masm.jccb(Assembler::notEqual, RET_FALSE);
masm.addl(rcx, 4);
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
// Compare trailing char (final 2 bytes), if any
masm.bind(COMPARE_CHAR);
masm.testl(rax, rax);
masm.jccb(Assembler::zero, RET_TRUE);
masm.load_unsigned_short(rbx, Address(rdi, 0));
masm.load_unsigned_short(rcx, Address(rsi, 0));
masm.cmpl(rbx, rcx);
masm.jccb(Assembler::notEqual, RET_FALSE);
masm.bind(RET_TRUE);
masm.movl(rax, 1); // return true
masm.jmpb(DONE);
masm.bind(RET_FALSE);
masm.xorl(rax, rax); // return false
masm.bind(DONE);
%}
enc_class enc_String_IndexOf(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2,
eCXRegI tmp3, eDXRegI tmp4, eBXRegI result) %{
// SSE4.2 version
Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE;
MacroAssembler masm(&cbuf);
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
// Get the first character position in both strings
// [8] char array, [12] offset, [16] count
int value_offset = java_lang_String::value_offset_in_bytes();
int offset_offset = java_lang_String::offset_offset_in_bytes();
int count_offset = java_lang_String::count_offset_in_bytes();
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
// Get counts for string and substr
masm.movl(rdx, Address(rsi, count_offset));
masm.movl(rax, Address(rdi, count_offset));
// Check for substr count > string count
masm.cmpl(rax, rdx);
masm.jcc(Assembler::greater, RET_NEG_ONE);
// Start the indexOf operation
// Get start addr of string
masm.movptr(rbx, Address(rsi, value_offset));
masm.movl(rcx, Address(rsi, offset_offset));
masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset));
masm.push(rsi);
// Get start addr of substr
masm.movptr(rbx, Address(rdi, value_offset));
masm.movl(rcx, Address(rdi, offset_offset));
masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset));
masm.push(rdi);
masm.push(rax);
masm.jmpb(PREP_FOR_SCAN);
// Substr count saved at sp
// Substr saved at sp+4
// String saved at sp+8
// Prep to load substr for scan
masm.bind(LOAD_SUBSTR);
masm.movptr(rdi, Address(rsp, 4));
masm.movl(rax, Address(rsp, 0));
// Load substr
masm.bind(PREP_FOR_SCAN);
masm.movdqu(tmp1Reg, Address(rdi, 0));
masm.addl(rdx, 8); // prime the loop
masm.subptr(rsi, 16);
// Scan string for substr in 16-byte vectors
masm.bind(SCAN_TO_SUBSTR);
masm.subl(rdx, 8);
masm.addptr(rsi, 16);
masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
masm.jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0
masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0
// Fallthru: found a potential substr
// Make sure string is still long enough
masm.subl(rdx, rcx);
masm.cmpl(rdx, rax);
masm.jccb(Assembler::negative, RET_NOT_FOUND);
// Compute start addr of substr
masm.lea(rsi, Address(rsi, rcx, Address::times_2));
masm.movptr(rbx, rsi);
// Compare potential substr
masm.addl(rdx, 8); // prime the loop
masm.addl(rax, 8);
masm.subptr(rsi, 16);
masm.subptr(rdi, 16);
// Scan 16-byte vectors of string and substr
masm.bind(SCAN_SUBSTR);
masm.subl(rax, 8);
masm.subl(rdx, 8);
masm.addptr(rsi, 16);
masm.addptr(rdi, 16);
masm.movdqu(tmp1Reg, Address(rdi, 0));
masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0
masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0
// Compute substr offset
masm.movptr(rsi, Address(rsp, 8));
masm.subptr(rbx, rsi);
masm.shrl(rbx, 1);
masm.jmpb(CLEANUP);
masm.bind(RET_NEG_ONE);
masm.movl(rbx, -1);
masm.jmpb(DONE);
masm.bind(RET_NOT_FOUND);
masm.movl(rbx, -1);
masm.bind(CLEANUP);
masm.addptr(rsp, 12);
masm.bind(DONE);
%}
enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2,
eBXRegI tmp3, eDXRegI tmp4, eAXRegI result) %{
Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
MacroAssembler masm(&cbuf);
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
Register ary1Reg = as_Register($ary1$$reg);
Register ary2Reg = as_Register($ary2$$reg);
Register tmp3Reg = as_Register($tmp3$$reg);
Register tmp4Reg = as_Register($tmp4$$reg);
Register resultReg = as_Register($result$$reg);
int length_offset = arrayOopDesc::length_offset_in_bytes(); int length_offset = arrayOopDesc::length_offset_in_bytes();
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
// Check the input args // Check the input args
masm.cmpl(ary1Reg, ary2Reg); masm.cmpptr(ary1Reg, ary2Reg);
masm.jcc(Assembler::equal, TRUE_LABEL); masm.jcc(Assembler::equal, TRUE_LABEL);
masm.testl(ary1Reg, ary1Reg); masm.testptr(ary1Reg, ary1Reg);
masm.jcc(Assembler::zero, FALSE_LABEL); masm.jcc(Assembler::zero, FALSE_LABEL);
masm.testl(ary2Reg, ary2Reg); masm.testptr(ary2Reg, ary2Reg);
masm.jcc(Assembler::zero, FALSE_LABEL); masm.jcc(Assembler::zero, FALSE_LABEL);
// Check the lengths // Check the lengths
masm.movl(tmp2Reg, Address(ary1Reg, length_offset)); masm.movl(tmp4Reg, Address(ary1Reg, length_offset));
masm.movl(resultReg, Address(ary2Reg, length_offset)); masm.movl(resultReg, Address(ary2Reg, length_offset));
masm.cmpl(tmp2Reg, resultReg); masm.cmpl(tmp4Reg, resultReg);
masm.jcc(Assembler::notEqual, FALSE_LABEL); masm.jcc(Assembler::notEqual, FALSE_LABEL);
masm.testl(resultReg, resultReg); masm.testl(resultReg, resultReg);
masm.jcc(Assembler::zero, TRUE_LABEL); masm.jcc(Assembler::zero, TRUE_LABEL);
// Get the number of 4 byte vectors to compare // Load array addrs
masm.shrl(resultReg, 1); masm.lea(ary1Reg, Address(ary1Reg, base_offset));
masm.lea(ary2Reg, Address(ary2Reg, base_offset));
// Check for odd-length arrays // Set byte count
masm.andl(tmp2Reg, 1); masm.shll(tmp4Reg, 1);
masm.testl(tmp2Reg, tmp2Reg); masm.movl(resultReg, tmp4Reg);
masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
// Compare 2-byte "tail" at end of arrays if (UseSSE42Intrinsics) {
masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset)); // With SSE4.2, use double quad vector compare
masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset)); Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
masm.cmpl(tmp1Reg, tmp2Reg); // Compare 16-byte vectors
masm.jcc(Assembler::notEqual, FALSE_LABEL); masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes)
masm.andl(resultReg, 0x0000000e); // tail count (in bytes)
masm.testl(tmp4Reg, tmp4Reg);
masm.jccb(Assembler::zero, COMPARE_TAIL);
masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
masm.negl(tmp4Reg);
masm.bind(COMPARE_WIDE_VECTORS);
masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
masm.pxor(tmp1Reg, tmp2Reg);
masm.ptest(tmp1Reg, tmp1Reg);
masm.jccb(Assembler::notZero, FALSE_LABEL);
masm.addl(tmp4Reg, 16);
masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
masm.bind(COMPARE_TAIL);
masm.movl(tmp4Reg, resultReg);
// Fallthru to tail compare
}
// Compare 4-byte vectors
masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes)
masm.andl(resultReg, 0x00000002); // tail char (in bytes)
masm.testl(tmp4Reg, tmp4Reg);
masm.jccb(Assembler::zero, COMPARE_CHAR);
masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
masm.negl(tmp4Reg);
masm.bind(COMPARE_VECTORS);
masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
masm.jccb(Assembler::notEqual, FALSE_LABEL);
masm.addl(tmp4Reg, 4);
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
// Compare trailing char (final 2 bytes), if any
masm.bind(COMPARE_CHAR);
masm.testl(resultReg, resultReg); masm.testl(resultReg, resultReg);
masm.jcc(Assembler::zero, TRUE_LABEL); masm.jccb(Assembler::zero, TRUE_LABEL);
masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0));
// Setup compare loop masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0));
masm.bind(COMPARE_LOOP_HDR); masm.cmpl(tmp3Reg, tmp4Reg);
// Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays masm.jccb(Assembler::notEqual, FALSE_LABEL);
masm.leal(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
masm.leal(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
masm.negl(resultReg);
// 4-byte-wide compare loop
masm.bind(COMPARE_LOOP);
masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0));
masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0));
masm.cmpl(ary1Reg, ary2Reg);
masm.jcc(Assembler::notEqual, FALSE_LABEL);
masm.increment(resultReg);
masm.jcc(Assembler::notZero, COMPARE_LOOP);
masm.bind(TRUE_LABEL); masm.bind(TRUE_LABEL);
masm.movl(resultReg, 1); // return true masm.movl(resultReg, 1); // return true
masm.jmp(DONE_LABEL); masm.jmpb(DONE);
masm.bind(FALSE_LABEL); masm.bind(FALSE_LABEL);
masm.xorl(resultReg, resultReg); // return false masm.xorl(resultReg, resultReg); // return false
// That's it // That's it
masm.bind(DONE_LABEL); masm.bind(DONE);
%} %}
enc_class enc_pop_rdx() %{ enc_class enc_pop_rdx() %{
@ -4295,24 +4570,6 @@ encode %{
emit_opcode(cbuf, 0xC8 + $src2$$reg); emit_opcode(cbuf, 0xC8 + $src2$$reg);
%} %}
enc_class enc_membar_acquire %{
// Doug Lea believes this is not needed with current Sparcs and TSO.
// MacroAssembler masm(&cbuf);
// masm.membar();
%}
enc_class enc_membar_release %{
// Doug Lea believes this is not needed with current Sparcs and TSO.
// MacroAssembler masm(&cbuf);
// masm.membar();
%}
enc_class enc_membar_volatile %{
MacroAssembler masm(&cbuf);
masm.membar(Assembler::Membar_mask_bits(Assembler::StoreLoad |
Assembler::StoreStore));
%}
// Atomically load the volatile long // Atomically load the volatile long
enc_class enc_loadL_volatile( memory mem, stackSlotL dst ) %{ enc_class enc_loadL_volatile( memory mem, stackSlotL dst ) %{
emit_opcode(cbuf,0xDF); emit_opcode(cbuf,0xDF);
@ -6387,6 +6644,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/Store/Move Instructions---------------------------------------
//----------Load Instructions-------------------------------------------------- //----------Load Instructions--------------------------------------------------
// Load Byte (8bit signed) // Load Byte (8bit signed)
@ -7444,9 +7762,9 @@ instruct membar_acquire() %{
ins_cost(400); ins_cost(400);
size(0); size(0);
format %{ "MEMBAR-acquire" %} format %{ "MEMBAR-acquire ! (empty encoding)" %}
ins_encode( enc_membar_acquire ); ins_encode();
ins_pipe(pipe_slow); ins_pipe(empty);
%} %}
instruct membar_acquire_lock() %{ instruct membar_acquire_lock() %{
@ -7465,9 +7783,9 @@ instruct membar_release() %{
ins_cost(400); ins_cost(400);
size(0); size(0);
format %{ "MEMBAR-release" %} format %{ "MEMBAR-release ! (empty encoding)" %}
ins_encode( enc_membar_release ); ins_encode( );
ins_pipe(pipe_slow); ins_pipe(empty);
%} %}
instruct membar_release_lock() %{ instruct membar_release_lock() %{
@ -7481,12 +7799,22 @@ instruct membar_release_lock() %{
ins_pipe(empty); ins_pipe(empty);
%} %}
instruct membar_volatile() %{ instruct membar_volatile(eFlagsReg cr) %{
match(MemBarVolatile); match(MemBarVolatile);
effect(KILL cr);
ins_cost(400); ins_cost(400);
format %{ "MEMBAR-volatile" %} format %{
ins_encode( enc_membar_volatile ); $$template
if (os::is_MP()) {
$$emit$$"LOCK ADDL [ESP + #0], 0\t! membar_volatile"
} else {
$$emit$$"MEMBAR-volatile ! (empty encoding)"
}
%}
ins_encode %{
__ membar(Assembler::StoreLoad);
%}
ins_pipe(pipe_slow); ins_pipe(pipe_slow);
%} %}
@ -12028,11 +12356,8 @@ instruct Repl2F_immXF0(regXD dst, immXF0 zero) %{
ins_pipe( fpu_reg_reg ); ins_pipe( fpu_reg_reg );
%} %}
// ======================================================================= // =======================================================================
// fast clearing of an array // fast clearing of an array
instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
match(Set dummy (ClearArray cnt base)); match(Set dummy (ClearArray cnt base));
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
@ -12046,24 +12371,48 @@ instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlag
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
instruct string_compare(eDIRegP str1, eSIRegP str2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result, eFlagsReg cr) %{ instruct string_compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
eAXRegI tmp3, eBXRegI tmp4, eCXRegI result, eFlagsReg cr) %{
match(Set result (StrComp str1 str2)); match(Set result (StrComp str1 str2));
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL cr); effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
//ins_cost(300); //ins_cost(300);
format %{ "String Compare $str1,$str2 -> $result // KILL EAX, EBX" %} format %{ "String Compare $str1,$str2 -> $result // KILL EAX, EBX" %}
ins_encode( enc_String_Compare() ); ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
ins_pipe( pipe_slow );
%}
// fast string equals
instruct string_equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
eBXRegI tmp3, eCXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
match(Set result (StrEquals str1 str2));
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
format %{ "String Equals $str1,$str2 -> $result // KILL EBX, ECX" %}
ins_encode( enc_String_Equals(tmp1, tmp2, str1, str2, tmp3, tmp4, result) );
ins_pipe( pipe_slow );
%}
instruct string_indexof(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2,
eCXRegI tmp3, eDXRegI tmp4, eBXRegI result, eFlagsReg cr) %{
predicate(UseSSE42Intrinsics);
match(Set result (StrIndexOf str1 str2));
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
format %{ "String IndexOf $str1,$str2 -> $result // KILL EAX, ECX, EDX" %}
ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
// fast array equals // fast array equals
instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result, eFlagsReg cr) %{ instruct array_equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, eBXRegI tmp3,
eDXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
match(Set result (AryEq ary1 ary2)); match(Set result (AryEq ary1 ary2));
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr); effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
//ins_cost(300); //ins_cost(300);
format %{ "Array Equals $ary1,$ary2 -> $result // KILL EAX, EBX" %} format %{ "Array Equals $ary1,$ary2 -> $result // KILL EBX, EDX" %}
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) ); ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) );
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
@ -12501,15 +12850,12 @@ instruct partialSubtypeCheck( eDIRegP result, eSIRegP sub, eAXRegP super, eCXReg
effect( KILL rcx, KILL cr ); effect( KILL rcx, KILL cr );
ins_cost(1100); // slightly larger than the next version ins_cost(1100); // slightly larger than the next version
format %{ "CMPL EAX,ESI\n\t" format %{ "MOV EDI,[$sub+Klass::secondary_supers]\n\t"
"JEQ,s hit\n\t"
"MOV EDI,[$sub+Klass::secondary_supers]\n\t"
"MOV ECX,[EDI+arrayKlass::length]\t# length to scan\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" "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" "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" "JNE,s miss\t\t# Missed: EDI not-zero\n\t"
"MOV [$sub+Klass::secondary_super_cache],$super\t# Hit: update cache\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" "XOR $result,$result\t\t Hit: EDI zero\n\t"
"miss:\t" %} "miss:\t" %}
@ -12523,9 +12869,7 @@ instruct partialSubtypeCheck_vs_Zero( eFlagsReg cr, eSIRegP sub, eAXRegP super,
effect( KILL rcx, KILL result ); effect( KILL rcx, KILL result );
ins_cost(1000); ins_cost(1000);
format %{ "CMPL EAX,ESI\n\t" format %{ "MOV EDI,[$sub+Klass::secondary_supers]\n\t"
"JEQ,s miss\t# Actually a hit; we are done.\n\t"
"MOV EDI,[$sub+Klass::secondary_supers]\n\t"
"MOV ECX,[EDI+arrayKlass::length]\t# length to scan\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" "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" "REPNE SCASD\t# Scan *EDI++ for a match with EAX while CX-- != 0\n\t"

File diff suppressed because it is too large Load Diff

View File

@ -1518,21 +1518,51 @@ const char* os::dll_file_extension() { return ".so"; }
const char* os::get_temp_directory() { return "/tmp/"; } const char* os::get_temp_directory() { return "/tmp/"; }
void os::dll_build_name( static bool file_exists(const char* filename) {
char* buffer, size_t buflen, const char* pname, const char* fname) { struct stat statbuf;
// copied from libhpi if (filename == NULL || strlen(filename) == 0) {
return false;
}
return os::stat(filename, &statbuf) == 0;
}
void os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0; const size_t pnamelen = pname ? strlen(pname) : 0;
/* Quietly truncate on buffer overflow. Should be an error. */ // Quietly truncate on buffer overflow. Should be an error.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
*buffer = '\0'; *buffer = '\0';
return; return;
} }
if (pnamelen == 0) { if (pnamelen == 0) {
sprintf(buffer, "lib%s.so", fname); snprintf(buffer, buflen, "lib%s.so", fname);
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
for (int i = 0 ; i < n ; i++) {
// Really shouldn't be NULL, but check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
if (file_exists(buffer)) {
break;
}
}
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else { } else {
sprintf(buffer, "%s/lib%s.so", pname, fname); snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
} }
} }
@ -2269,15 +2299,16 @@ void linux_wrap_code(char* base, size_t size) {
// All it does is to check if there are enough free pages // All it does is to check if there are enough free pages
// left at the time of mmap(). This could be a potential // left at the time of mmap(). This could be a potential
// problem. // problem.
bool os::commit_memory(char* addr, size_t size) { bool os::commit_memory(char* addr, size_t size, bool exec) {
uintptr_t res = (uintptr_t) ::mmap(addr, size, int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
PROT_READ|PROT_WRITE|PROT_EXEC, uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
return res != (uintptr_t) MAP_FAILED; return res != (uintptr_t) MAP_FAILED;
} }
bool os::commit_memory(char* addr, size_t size, size_t alignment_hint) { bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
return commit_memory(addr, size); bool exec) {
return commit_memory(addr, size, exec);
} }
void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
@ -2417,8 +2448,7 @@ os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory;
unsigned long* os::Linux::_numa_all_nodes; unsigned long* os::Linux::_numa_all_nodes;
bool os::uncommit_memory(char* addr, size_t size) { bool os::uncommit_memory(char* addr, size_t size) {
return ::mmap(addr, size, return ::mmap(addr, size, PROT_NONE,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0) MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0)
!= MAP_FAILED; != MAP_FAILED;
} }
@ -2441,7 +2471,9 @@ static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) {
flags |= MAP_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); flags, -1, 0);
if (addr != MAP_FAILED) { if (addr != MAP_FAILED) {
@ -2582,7 +2614,9 @@ bool os::large_page_init() {
#define SHM_HUGETLB 04000 #define SHM_HUGETLB 04000
#endif #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"); assert(UseLargePages, "only for large pages");
key_t key = IPC_PRIVATE; key_t key = IPC_PRIVATE;

View File

@ -249,6 +249,10 @@ int generateJvmOffsets(GEN_variant gen_variant) {
printf("\n"); printf("\n");
GEN_OFFS(NarrowOopStruct, _base);
GEN_OFFS(NarrowOopStruct, _shift);
printf("\n");
GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header)); GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header));
GEN_SIZE(oopDesc); GEN_SIZE(oopDesc);
GEN_SIZE(constantPoolOopDesc); GEN_SIZE(constantPoolOopDesc);

View File

@ -46,7 +46,10 @@ extern pointer __JvmOffsets;
extern pointer __1cJCodeCacheF_heap_; extern pointer __1cJCodeCacheF_heap_;
extern pointer __1cIUniverseP_methodKlassObj_; extern pointer __1cIUniverseP_methodKlassObj_;
extern pointer __1cIUniverseO_collectedHeap_; 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 __1cHnmethodG__vtbl_;
extern pointer __1cKBufferBlobG__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_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t))
#define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_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_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 SAME(x) x
#define copyin_offset(JVM_CONST) JVM_CONST = \ #define copyin_offset(JVM_CONST) JVM_CONST = \
@ -132,6 +136,9 @@ dtrace:helper:ustack:
copyin_offset(SIZE_oopDesc); copyin_offset(SIZE_oopDesc);
copyin_offset(SIZE_constantPoolOopDesc); copyin_offset(SIZE_constantPoolOopDesc);
copyin_offset(OFFSET_NarrowOopStruct_base);
copyin_offset(OFFSET_NarrowOopStruct_shift);
/* /*
* The PC to translate is in arg0. * The PC to translate is in arg0.
*/ */
@ -151,9 +158,19 @@ dtrace:helper:ustack:
this->Universe_methodKlassOop = copyin_ptr(&``__1cIUniverseP_methodKlassObj_); this->Universe_methodKlassOop = copyin_ptr(&``__1cIUniverseP_methodKlassObj_);
this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_); this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_);
this->Universe_heap_base = copyin_ptr(&``__1cIUniverseK_heap_base_);
/* Reading volatile values */ /* 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 + this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address +
OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
@ -295,7 +312,7 @@ dtrace:helper:ustack:
dtrace:helper:ustack: dtrace:helper:ustack:
/!this->done && this->vtbl == this->BufferBlob_vtbl && /!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/ this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/
{ {
MARK_LINE; MARK_LINE;
@ -306,7 +323,7 @@ this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/
dtrace:helper:ustack: dtrace:helper:ustack:
/!this->done && this->vtbl == this->BufferBlob_vtbl && /!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/ this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/
{ {
MARK_LINE; 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 * Read compressed pointer and decode heap oop, same as oop.inline.hpp
*/ */
this->cklass = copyin_uint32(this->methodOopPtr + OFFSET_oopDesc_metadata); this->cklass = copyin_uint32(this->methodOopPtr + OFFSET_oopDesc_metadata);
this->klass = (uint64_t)((uintptr_t)this->Universe_heap_base + this->klass = (uint64_t)((uintptr_t)this->Universe_narrow_oop_base +
((uintptr_t)this->cklass << 3)); ((uintptr_t)this->cklass << this->Universe_narrow_oop_shift));
this->methodOop = this->klass == this->Universe_methodKlassOop; this->methodOop = this->klass == this->Universe_methodKlassOop;
this->done = !this->methodOop; this->done = !this->methodOop;
} }

View File

@ -146,13 +146,17 @@ struct jvm_agent {
uint64_t BufferBlob_vtbl; uint64_t BufferBlob_vtbl;
uint64_t RuntimeStub_vtbl; uint64_t RuntimeStub_vtbl;
uint64_t Use_Compressed_Oops_address;
uint64_t Universe_methodKlassObj_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 CodeCache_heap_address;
uint64_t Universe_heap_base_address;
/* Volatiles */ /* Volatiles */
uint8_t Use_Compressed_Oops;
uint64_t Universe_methodKlassObj; 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_low;
uint64_t CodeCache_high; uint64_t CodeCache_high;
uint64_t CodeCache_segmap_low; uint64_t CodeCache_segmap_low;
@ -279,8 +283,11 @@ static int parse_vmstructs(jvm_agent_t* J) {
if (strcmp("_methodKlassObj", vmp->fieldName) == 0) { if (strcmp("_methodKlassObj", vmp->fieldName) == 0) {
J->Universe_methodKlassObj_address = vmp->address; J->Universe_methodKlassObj_address = vmp->address;
} }
if (strcmp("_heap_base", vmp->fieldName) == 0) { if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
J->Universe_heap_base_address = vmp->address; 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); CHECK_FAIL(err);
@ -298,14 +305,39 @@ static int parse_vmstructs(jvm_agent_t* J) {
return -1; 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) { static int read_volatiles(jvm_agent_t* J) {
uint64_t ptr; uint64_t ptr;
int err; 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); err = read_pointer(J, J->Universe_methodKlassObj_address, &J->Universe_methodKlassObj);
CHECK_FAIL(err); 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); 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 + err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
OFFSET_VirtualSpace_low, &J->CodeCache_low); OFFSET_VirtualSpace_low, &J->CodeCache_low);
CHECK_FAIL(err); CHECK_FAIL(err);
@ -374,19 +406,6 @@ static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
return -1; 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) { static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
psaddr_t sym_addr; psaddr_t sym_addr;
int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &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) { static int is_methodOop(jvm_agent_t* J, uint64_t methodOopPtr) {
uint64_t klass; uint64_t klass;
int err; int err;
// If heap_base is nonnull, this was a compressed oop. // If UseCompressedOops, this was a compressed oop.
if (J->Universe_heap_base != NULL) { if (J->Use_Compressed_Oops != 0) {
uint32_t cklass; uint32_t cklass;
err = read_compressed_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, err = read_compressed_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata,
&cklass); &cklass);
// decode heap oop, same as oop.inline.hpp // decode heap oop, same as oop.inline.hpp
klass = (uint64_t)((uintptr_t)J->Universe_heap_base + klass = (uint64_t)((uintptr_t)J->Universe_narrow_oop_base +
((uintptr_t)cklass << 3)); ((uintptr_t)cklass << J->Universe_narrow_oop_shift));
} else { } else {
err = read_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, &klass); err = read_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, &klass);
} }

View File

@ -1827,21 +1827,51 @@ const char* os::dll_file_extension() { return ".so"; }
const char* os::get_temp_directory() { return "/tmp/"; } const char* os::get_temp_directory() { return "/tmp/"; }
void os::dll_build_name( static bool file_exists(const char* filename) {
char* buffer, size_t buflen, const char* pname, const char* fname) { struct stat statbuf;
// copied from libhpi if (filename == NULL || strlen(filename) == 0) {
return false;
}
return os::stat(filename, &statbuf) == 0;
}
void os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0; const size_t pnamelen = pname ? strlen(pname) : 0;
/* Quietly truncate on buffer overflow. Should be an error. */ // Quietly truncate on buffer overflow. Should be an error.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
*buffer = '\0'; *buffer = '\0';
return; return;
} }
if (pnamelen == 0) { if (pnamelen == 0) {
sprintf(buffer, "lib%s.so", fname); snprintf(buffer, buflen, "lib%s.so", fname);
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
for (int i = 0 ; i < n ; i++) {
// really shouldn't be NULL but what the heck, check can't hurt
if (pelements[i] == NULL || strlen(pelements[i]) == 0) {
continue; // skip the empty path values
}
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
if (file_exists(buffer)) {
break;
}
}
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else { } else {
sprintf(buffer, "%s/lib%s.so", pname, fname); snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
} }
} }
@ -2623,15 +2653,16 @@ int os::vm_allocation_granularity() {
return page_size; 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; size_t size = bytes;
return return
NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot);
PROT_READ | PROT_WRITE | PROT_EXEC);
} }
bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint) { bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint,
if (commit_memory(addr, bytes)) { bool exec) {
if (commit_memory(addr, bytes, exec)) {
if (UseMPSS && alignment_hint > (size_t)vm_page_size()) { if (UseMPSS && alignment_hint > (size_t)vm_page_size()) {
// If the large page size has been set and the VM // If the large page size has been set and the VM
// is using large pages, use the large page size // is using large pages, use the large page size
@ -3220,7 +3251,9 @@ bool os::Solaris::set_mpss_range(caddr_t start, size_t bytes, size_t align) {
return true; 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"); assert(UseLargePages && UseISM, "only for ISM large pages");
size_t size = bytes; size_t size = bytes;
@ -4451,6 +4484,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_suspend_mutator;
int_fnP_thread_t os::Solaris::_thr_continue_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 // (Static) wrappers for the liblgrp API
os::Solaris::lgrp_home_func_t os::Solaris::_lgrp_home; os::Solaris::lgrp_home_func_t os::Solaris::_lgrp_home;
os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init; os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init;
@ -4465,16 +4501,19 @@ os::Solaris::lgrp_cookie_t os::Solaris::_lgrp_cookie = 0;
// (Static) wrapper for meminfo() call. // (Static) wrapper for meminfo() call.
os::Solaris::meminfo_func_t os::Solaris::_meminfo = 0; os::Solaris::meminfo_func_t os::Solaris::_meminfo = 0;
static address resolve_symbol(const char *name) { static address resolve_symbol_lazy(const char* name) {
address addr; address addr = (address) dlsym(RTLD_DEFAULT, name);
addr = (address) dlsym(RTLD_DEFAULT, name);
if(addr == NULL) { if(addr == NULL) {
// RTLD_DEFAULT was not defined on some early versions of 2.5.1 // RTLD_DEFAULT was not defined on some early versions of 2.5.1
addr = (address) dlsym(RTLD_NEXT, name); 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; return addr;
} }
@ -4673,15 +4712,26 @@ bool os::Solaris::liblgrp_init() {
} }
void os::Solaris::misc_sym_init() { void os::Solaris::misc_sym_init() {
address func = (address)dlsym(RTLD_DEFAULT, "meminfo"); address func;
if(func == NULL) {
func = (address) dlsym(RTLD_NEXT, "meminfo"); // 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) { if (func != NULL) {
os::Solaris::set_meminfo(CAST_TO_FN_PTR(meminfo_func_t, func)); 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 // Symbol doesn't exist in Solaris 8 pset.h
#ifndef PS_MYID #ifndef PS_MYID
#define PS_MYID -3 #define PS_MYID -3
@ -4716,6 +4766,10 @@ void os::init(void) {
Solaris::initialize_system_info(); 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); int fd = open("/dev/zero", O_RDWR);
if (fd < 0) { if (fd < 0) {
fatal1("os::init: cannot open /dev/zero (%s)", strerror(errno)); fatal1("os::init: cannot open /dev/zero (%s)", strerror(errno));
@ -4857,7 +4911,6 @@ jint os::init_2(void) {
} }
} }
Solaris::misc_sym_init();
Solaris::signal_sets_init(); Solaris::signal_sets_init();
Solaris::init_signal_mem(); Solaris::init_signal_mem();
Solaris::install_signal_handlers(); Solaris::install_signal_handlers();

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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_OS /* what's available to operating system */
} lgrp_view_t; } 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_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 lgrp_cookie_t (*lgrp_init_func_t)(lgrp_view_t view);
typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie); typedef int (*lgrp_fini_func_t)(lgrp_cookie_t cookie);
@ -87,6 +89,8 @@ class Solaris {
const uint_t info_req[], int info_count, const uint_t info_req[], int info_count,
uint64_t outdata[], uint_t validity[]); uint64_t outdata[], uint_t validity[]);
static getisax_func_t _getisax;
static lgrp_home_func_t _lgrp_home; static lgrp_home_func_t _lgrp_home;
static lgrp_init_func_t _lgrp_init; static lgrp_init_func_t _lgrp_init;
static lgrp_fini_func_t _lgrp_fini; static lgrp_fini_func_t _lgrp_fini;
@ -283,6 +287,9 @@ class Solaris {
} }
static lgrp_cookie_t lgrp_cookie() { return _lgrp_cookie; } 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 void set_meminfo(meminfo_func_t func) { _meminfo = func; }
static int meminfo (const uint64_t inaddr[], int addr_count, static int meminfo (const uint64_t inaddr[], int addr_count,
const uint_t info_req[], int info_count, const uint_t info_req[], int info_count,

View File

@ -1004,26 +1004,61 @@ const char * os::get_temp_directory()
} }
} }
void os::dll_build_name(char *holder, size_t holderlen, static bool file_exists(const char* filename) {
const char* pname, const char* fname) if (filename == NULL || strlen(filename) == 0) {
{ return false;
// copied from libhpi }
const size_t pnamelen = pname ? strlen(pname) : 0; return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; }
/* Quietly truncates on buffer overflow. Should be an error. */ void os::dll_build_name(char *buffer, size_t buflen,
if (pnamelen + strlen(fname) + 10 > holderlen) { const char* pname, const char* fname) {
*holder = '\0'; // Copied from libhpi
return; const size_t pnamelen = pname ? strlen(pname) : 0;
} const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
if (pnamelen == 0) { // Quietly truncates on buffer overflow. Should be an error.
sprintf(holder, "%s.dll", fname); if (pnamelen + strlen(fname) + 10 > buflen) {
} else if (c == ':' || c == '\\') { *buffer = '\0';
sprintf(holder, "%s%s.dll", pname, fname); return;
} else { }
sprintf(holder, "%s\\%s.dll", pname, fname);
if (pnamelen == 0) {
jio_snprintf(buffer, buflen, "%s.dll", fname);
} else if (c == ':' || c == '\\') {
jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname);
} else if (strchr(pname, *os::path_separator()) != NULL) {
int n;
char** pelements = split_path(pname, &n);
for (int i = 0 ; i < n ; i++) {
char* path = pelements[i];
// Really shouldn't be NULL, but check can't hurt
size_t plen = (path == NULL) ? 0 : strlen(path);
if (plen == 0) {
continue; // skip the empty path values
}
const char lastchar = path[plen - 1];
if (lastchar == ':' || lastchar == '\\') {
jio_snprintf(buffer, buflen, "%s%s.dll", path, fname);
} else {
jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname);
}
if (file_exists(buffer)) {
break;
}
} }
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
FREE_C_HEAP_ARRAY(char, pelements[i]);
}
}
if (pelements != NULL) {
FREE_C_HEAP_ARRAY(char*, pelements);
}
} else {
jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname);
}
} }
// Needs to be in os specific directory because windows requires another // Needs to be in os specific directory because windows requires another
@ -2189,7 +2224,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) { if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) {
addr = (address)((uintptr_t)addr & addr = (address)((uintptr_t)addr &
(~((uintptr_t)os::vm_page_size() - (uintptr_t)1))); (~((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; return EXCEPTION_CONTINUE_EXECUTION;
} }
else else
@ -2565,8 +2601,7 @@ char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
assert((size_t)addr % os::vm_allocation_granularity() == 0, assert((size_t)addr % os::vm_allocation_granularity() == 0,
"reserve alignment"); "reserve alignment");
assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size"); assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size");
char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE);
PAGE_EXECUTE_READWRITE);
assert(res == NULL || addr == NULL || addr == res, assert(res == NULL || addr == NULL || addr == res,
"Unexpected address from reserve."); "Unexpected address from reserve.");
return res; return res;
@ -2595,7 +2630,7 @@ bool os::can_execute_large_page_memory() {
return true; 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 (UseLargePagesIndividualAllocation) {
if (TracePageSizes && Verbose) { if (TracePageSizes && Verbose) {
@ -2615,10 +2650,10 @@ char* os::reserve_memory_special(size_t bytes) {
"use -XX:-UseLargePagesIndividualAllocation to turn off"); "use -XX:-UseLargePagesIndividualAllocation to turn off");
return NULL; return NULL;
} }
p_buf = (char *) VirtualAlloc(NULL, p_buf = (char *) VirtualAlloc(addr,
size_of_reserve, // size of Reserve size_of_reserve, // size of Reserve
MEM_RESERVE, MEM_RESERVE,
PAGE_EXECUTE_READWRITE); PAGE_READWRITE);
// If reservation failed, return NULL // If reservation failed, return NULL
if (p_buf == NULL) return NULL; if (p_buf == NULL) return NULL;
@ -2659,7 +2694,13 @@ char* os::reserve_memory_special(size_t bytes) {
p_new = (char *) VirtualAlloc(next_alloc_addr, p_new = (char *) VirtualAlloc(next_alloc_addr,
bytes_to_rq, bytes_to_rq,
MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, 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) { if (p_new == NULL) {
@ -2688,10 +2729,12 @@ char* os::reserve_memory_special(size_t bytes) {
} else { } else {
// normal policy just allocate it all at once // normal policy just allocate it all at once
DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
char * res = (char *)VirtualAlloc(NULL, char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_READWRITE);
bytes, if (res != NULL && exec) {
flag, DWORD oldprot;
PAGE_EXECUTE_READWRITE); // Windows doc says to use VirtualProtect to get execute permissions
VirtualProtect(res, bytes, PAGE_EXECUTE_READWRITE, &oldprot);
}
return res; return res;
} }
} }
@ -2703,7 +2746,7 @@ bool os::release_memory_special(char* base, size_t bytes) {
void os::print_statistics() { 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) { if (bytes == 0) {
// Don't bother the OS with noops. // Don't bother the OS with noops.
return true; return true;
@ -2712,11 +2755,19 @@ bool os::commit_memory(char* addr, size_t bytes) {
assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks"); 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 // Don't attempt to print anything if the OS call fails. We're
// probably low on resources, so the print itself may cause crashes. // 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) { bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
return commit_memory(addr, size); bool exec) {
return commit_memory(addr, size, exec);
} }
bool os::uncommit_memory(char* addr, size_t bytes) { bool os::uncommit_memory(char* addr, size_t bytes) {
@ -2750,7 +2801,7 @@ bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
// Strange enough, but on Win32 one can change protection only for committed // 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 // 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"); fatal("cannot commit protection page");
} }
// One cannot use os::guard_memory() here, as on Win32 guard page // One cannot use os::guard_memory() here, as on Win32 guard page
@ -3248,10 +3299,10 @@ jint os::init_2(void) {
#endif #endif
if (!UseMembar) { 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"); 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"); guarantee( return_page != NULL, "Commit Failed for memory serialize page");
os::set_memory_serialize_page( mem_serialize_page ); os::set_memory_serialize_page( mem_serialize_page );

View File

@ -30,5 +30,7 @@
define_pd_global(uintx, JVMInvokeMethodSlack, 12288); define_pd_global(uintx, JVMInvokeMethodSlack, 12288);
define_pd_global(intx, CompilerThreadStackSize, 0); 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 // Only used on 64 bit Windows platforms
define_pd_global(bool, UseVectoredExceptions, false); define_pd_global(bool, UseVectoredExceptions, false);

View File

@ -29,13 +29,11 @@
static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint);
static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong);
static jint (*atomic_add_func) (jint, volatile jint*); static jint (*atomic_add_func) (jint, volatile jint*);
static void (*fence_func) ();
static jint atomic_xchg_bootstrap (jint, volatile jint*); static jint atomic_xchg_bootstrap (jint, volatile jint*);
static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint);
static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong);
static jint atomic_add_bootstrap (jint, volatile jint*); static jint atomic_add_bootstrap (jint, volatile jint*);
static void fence_bootstrap ();
static void setup_fpu() {} static void setup_fpu() {}

Some files were not shown because too many files have changed in this diff Show More