diff --git a/.hgtags b/.hgtags
index 7e5d08a0b80..1cd85cdd1a5 100644
--- a/.hgtags
+++ b/.hgtags
@@ -96,3 +96,4 @@ a4e6aa1f45ad23a6f083ed98d970b5006ea4d292 jdk7-b116
4951967a61b4dbbf514828879f57bd1a0d4b420b jdk7-b119
8c840d3ab24f8d0f422b991638acb44b6ab1d98c jdk7-b120
0ce0a2c3a6926677dc507839a820ab6625541e5a jdk7-b121
+6f09ea1c034f087916d2a8cf0d22be768400118f jdk7-b122
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 9180b32f19c..86759295812 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -96,3 +96,4 @@ a12a9e78df8a9d534da0b4a244ed68f0de0bd58e jdk7-b118
661360bef6ccad6c119f067f5829b207de80c936 jdk7-b119
366ff0b6d2151595629806b033e2e1497e3a55d4 jdk7-b120
2c2d4f88637b488014c37e1a2eb401f68bca8838 jdk7-b121
+f1591eed71f64f6eba79fb7426f5616cc4dfea73 jdk7-b122
diff --git a/README b/README
index 5dd05f46abe..eef68df24a7 100644
--- a/README
+++ b/README
@@ -26,6 +26,6 @@ Simple Build Instructions:
gnumake all
The resulting JDK image should be found in build/*/j2sdk-image
-where gnumake is GNU make 3.78.1 or newer, /usr/bin/make on Linux and
+where gnumake is GNU make 3.81 or newer, /usr/bin/make on Linux and
/usr/sfw/bin/gmake or /opt/sfw/bin/gmake on Solaris.
diff --git a/README-builds.html b/README-builds.html
index 81ada58e303..1c2504c4dc5 100644
--- a/README-builds.html
+++ b/README-builds.html
@@ -524,7 +524,7 @@
A few notes about using GNU make:
- In general, you need GNU make version 3.78.1 or newer.
+ In general, you need GNU make version 3.81 or newer.
Place the location of the GNU make binary in the PATH.
diff --git a/corba/.hgtags b/corba/.hgtags
index de24085cb76..331d411b743 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -96,3 +96,4 @@ fa502e4834dac2176499cc1f44794d5dc32a11b9 jdk7-b117
39829414ae31a0080578a49b751899edd518cd7d jdk7-b119
cff5a173ec1e89013359e804a3e31736ef6fb462 jdk7-b120
2cc9f32992101732b23730b737740e64ebc5fa89 jdk7-b121
+1523a060032c8a5b7840198da8911abeff88118f jdk7-b122
diff --git a/corba/make/common/shared/Platform.gmk b/corba/make/common/shared/Platform.gmk
index e1bb4466531..07d0b505d27 100644
--- a/corba/make/common/shared/Platform.gmk
+++ b/corba/make/common/shared/Platform.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -383,7 +383,7 @@ endif
REQUIRED_ZIP_VER = 2.2
REQUIRED_UNZIP_VER = 5.12
-REQUIRED_MAKE_VER = 3.78
+REQUIRED_MAKE_VER = 3.81
# Unix type settings (same for all unix platforms)
ifneq ($(PLATFORM), windows)
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java b/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java
index da369f9c365..0c7844325cd 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/encoding/BufferManagerWriteStream.java
@@ -30,12 +30,14 @@ import com.sun.corba.se.impl.orbutil.ORBConstants;
import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
import com.sun.corba.se.impl.protocol.giopmsgheaders.FragmentMessage;
+import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
import com.sun.corba.se.impl.encoding.BufferManagerWrite;
import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
import com.sun.corba.se.impl.encoding.CDROutputObject;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.pept.transport.Connection;
import com.sun.corba.se.pept.encoding.OutputObject;
+import org.omg.CORBA.SystemException;
/**
* Streaming buffer manager.
@@ -66,7 +68,13 @@ public class BufferManagerWriteStream extends BufferManagerWrite
// Set the fragment's moreFragments field to true
MessageBase.setFlag(bbwi.byteBuffer, Message.MORE_FRAGMENTS_BIT);
- sendFragment(false);
+ try {
+ sendFragment(false);
+ } catch(SystemException se){
+ orb.getPIHandler().invokeClientPIEndingPoint(
+ ReplyMessage.SYSTEM_EXCEPTION, se);
+ throw se;
+ }
// Reuse the old buffer
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java b/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java
index 09eb3d2ea2e..a8f55670d4e 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/io/ObjectStreamClass.java
@@ -85,6 +85,9 @@ public class ObjectStreamClass implements java.io.Serializable {
private static Hashtable translatedFields;
+ /** true if represents enum type */
+ private boolean isEnum;
+
private static final Bridge bridge =
(Bridge)AccessController.doPrivileged(
new PrivilegedAction() {
@@ -359,6 +362,7 @@ public class ObjectStreamClass implements java.io.Serializable {
}
name = cl.getName();
+ isEnum = Enum.class.isAssignableFrom(cl);
superclass = superdesc;
serializable = serial;
if (!forProxyClass) {
@@ -401,7 +405,8 @@ public class ObjectStreamClass implements java.io.Serializable {
if (!serializable ||
externalizable ||
forProxyClass ||
- name.equals("java.lang.String")) {
+ name.equals("java.lang.String") ||
+ isEnum) {
fields = NO_FIELDS;
} else if (serializable) {
/* Ask for permission to override field access checks.
@@ -502,7 +507,7 @@ public class ObjectStreamClass implements java.io.Serializable {
*
* NonSerializable classes have a serialVerisonUID of 0L.
*/
- if (isNonSerializable()) {
+ if (isNonSerializable() || isEnum) {
suid = 0L;
} else {
// Lookup special Serializable members using reflection.
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java
index b7564e716e4..d906afef923 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/AOMEntry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,10 @@ import com.sun.corba.se.spi.orbutil.fsm.StateEngineFactory ;
import com.sun.corba.se.impl.orbutil.concurrent.Mutex ;
import com.sun.corba.se.impl.orbutil.concurrent.CondVar ;
+import org.omg.CORBA.SystemException ;
+
+import org.omg.PortableServer.POAPackage.ObjectAlreadyActive ;
+
/** AOMEntry represents a Servant or potential Servant in the ActiveObjectMap.
* It may be in several states to allow for long incarnate or etherealize operations.
* The methods on this class mostly represent input symbols to the state machine
@@ -121,6 +125,12 @@ public class AOMEntry extends FSMImpl {
}
} ;
+ private static Action oaaAction = new ActionBase( "throwObjectAlreadyActive" ) {
+ public void doIt( FSM fsm, Input in ) {
+ throw new RuntimeException( new ObjectAlreadyActive() ) ;
+ }
+ } ;
+
private static Guard waitGuard = new GuardBase( "wait" ) {
public Guard.Result evaluate( FSM fsm, Input in ) {
AOMEntry entry = (AOMEntry)fsm ;
@@ -173,19 +183,23 @@ public class AOMEntry extends FSMImpl {
engine.add( INCARN, START_ETH, waitGuard, null, INCARN ) ;
engine.add( INCARN, INC_DONE, null, VALID ) ;
engine.add( INCARN, INC_FAIL, decrementAction, INVALID ) ;
+ engine.add( INCARN, ACTIVATE, oaaAction, INCARN ) ;
engine.add( VALID, ENTER, incrementAction, VALID ) ;
engine.add( VALID, EXIT, decrementAction, VALID ) ;
engine.add( VALID, START_ETH, greaterZeroGuard, null, ETHP ) ;
engine.add( VALID, START_ETH, zeroGuard, null, ETH ) ;
+ engine.add( VALID, ACTIVATE, oaaAction, VALID ) ;
engine.add( ETHP, ENTER, waitGuard, null, ETHP ) ;
engine.add( ETHP, START_ETH, null, ETHP ) ;
engine.add( ETHP, EXIT, greaterOneGuard, decrementAction, ETHP ) ;
engine.add( ETHP, EXIT, oneGuard, decrementAction, ETH ) ;
+ engine.add( ETHP, ACTIVATE, oaaAction, ETHP ) ;
engine.add( ETH, START_ETH, null, ETH ) ;
engine.add( ETH, ETH_DONE, null, DESTROYED ) ;
+ engine.add( ETH, ACTIVATE, oaaAction, ETH ) ;
engine.add( ETH, ENTER, waitGuard, null, ETH ) ;
engine.setDefault( DESTROYED, throwIllegalStateExceptionAction, DESTROYED ) ;
@@ -217,7 +231,17 @@ public class AOMEntry extends FSMImpl {
public void etherealizeComplete() { doIt( ETH_DONE ) ; }
public void incarnateComplete() { doIt( INC_DONE ) ; }
public void incarnateFailure() { doIt( INC_FAIL ) ; }
- public void activateObject() { doIt( ACTIVATE ) ; }
+ public void activateObject() throws ObjectAlreadyActive {
+ try {
+ doIt( ACTIVATE ) ;
+ } catch (RuntimeException exc) {
+ Throwable thr = exc.getCause() ;
+ if (thr instanceof ObjectAlreadyActive)
+ throw (ObjectAlreadyActive)thr ;
+ else
+ throw exc ;
+ }
+ }
public void enter() { doIt( ENTER ) ; }
public void exit() { doIt( EXIT ) ; }
}
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java
index b396ac5227d..1bc9130e109 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorBase_R.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -107,13 +107,9 @@ public abstract class POAPolicyMediatorBase_R extends POAPolicyMediatorBase {
throw new ServantAlreadyActive();
ActiveObjectMap.Key key = new ActiveObjectMap.Key( id ) ;
- // Note that this can't happen for system assigned IDs since the
- // POA never hands out the same ID. However, we make this redundant
- // check here to share the code.
- if (activeObjectMap.containsKey(key))
- throw new ObjectAlreadyActive() ;
-
AOMEntry entry = activeObjectMap.get( key ) ;
+
+ // Check for an ObjectAlreadyActive error
entry.activateObject() ;
activateServant( key, entry, servant ) ;
}
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java
index 0bdd1072128..65d8246f7ad 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -245,7 +245,14 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
// All access to resolver, localResolver, and urlOperation must be protected using
// resolverLock. Do not hold the ORBImpl lock while accessing
// resolver, or deadlocks may occur.
- private Object resolverLock ;
+ // Note that we now have separate locks for each resolver type. This is due
+ // to bug 6980681 and 6238477, which was caused by a deadlock while resolving a
+ // corbaname: URL that contained a reference to the same ORB as the
+ // ORB making the call to string_to_object. This caused a deadlock between the
+ // client thread holding the single lock for access to the urlOperation,
+ // and the server thread handling the client is_a request waiting on the
+ // same lock to access the localResolver.
+
// Used for resolver_initial_references and list_initial_services
private Resolver resolver ;
@@ -255,8 +262,14 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
// Converts strings to object references for resolvers and string_to_object
private Operation urlOperation ;
+ private final Object urlOperationLock = new java.lang.Object() ;
private CorbaServerRequestDispatcher insNamingDelegate ;
+ // resolverLock must be used for all access to either resolver or
+ // localResolver, since it is possible for the resolver to indirectly
+ // refer to the localResolver. Also used to protect access to
+ // insNamingDelegate.
+ private final Object resolverLock = new Object() ;
private TaggedComponentFactoryFinder taggedComponentFactoryFinder ;
@@ -396,7 +409,6 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
}
};
- resolverLock = new java.lang.Object() ;
requestDispatcherRegistry = new RequestDispatcherRegistryImpl(
this, ORBConstants.DEFAULT_SCID);
@@ -832,7 +844,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
if (str == null)
throw wrapper.nullParam() ;
- synchronized (resolverLock) {
+ synchronized (urlOperationLock) {
org.omg.CORBA.Object obj = (org.omg.CORBA.Object)op.operate( str ) ;
return obj ;
}
@@ -1778,7 +1790,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
*/
public void setURLOperation( Operation stringToObject )
{
- synchronized (resolverLock) {
+ synchronized (urlOperationLock) {
urlOperation = stringToObject ;
}
}
@@ -1788,7 +1800,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
*/
public Operation getURLOperation()
{
- synchronized (resolverLock) {
+ synchronized (urlOperationLock) {
return urlOperation ;
}
}
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/orbutil/resources/sunorb_pt_BR.properties b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/resources/sunorb_pt_BR.properties
new file mode 100644
index 00000000000..17b104b8e2f
--- /dev/null
+++ b/corba/src/share/classes/com/sun/corba/se/impl/orbutil/resources/sunorb_pt_BR.properties
@@ -0,0 +1,107 @@
+
+# Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+orbd.usage=Uso: {0} \n\nem que inclui:\n -port porta de ativa\u00e7\u00e3o na qual o ORBD deve ser iniciado, padr\u00e3o 1049 (opcional)\n -defaultdb diret\u00f3rio dos arquivos ORBD, padr\u00e3o "./orb.db" (opcional)\n -serverid id do servidor para ORBD, padr\u00e3o 1 (opcional)\n -ORBInitialPort porta inicial (necess\u00e1rio)\n -ORBInitialHost nome de host inicial (necess\u00e1rio)\n
+
+servertool.usage=Uso: {0} \n\nem que inclui:\n -ORBInitialPort porta inicial (necess\u00e1rio)\n -ORBInitialHost nome de host inicial (necess\u00e1rio)\n
+servertool.banner=\n\nBem-vindo a ferramenta de servidor IDL Java \ninsira os comandos no prompt \n
+servertool.shorthelp=\n\n\tComandos dispon\u00edveis: \n\t------------------- \n
+servertool.baddef=Servidor mal definido: {0}
+servertool.nosuchserver=\tservidor n\u00e3o encontrado.
+servertool.helddown=\to servidor est\u00e1 em espera.
+servertool.nosuchorb=\tORB inv\u00e1lido.
+servertool.serverup=\to servidor j\u00e1 est\u00e1 ativo.
+servertool.appname=\tapplicationName - {0}
+servertool.name=\tname - {0}
+servertool.classpath=\tclasspath - {0}
+servertool.args=\targs - {0}
+servertool.vmargs=\tvmargs - {0}
+servertool.serverid=\tserver id - {0}
+servertool.servernotrunning=\to servidor n\u00e3o est\u00e1 em execu\u00e7\u00e3o.
+servertool.register=\n\n\tregister -server \n\t -applicationName \n\t -classpath \n\t -args \n\t -vmargs \n
+servertool.register1=registra um servidor ativ\u00e1vel
+servertool.register2=\tservidor registrado (serverid = {0}).
+servertool.register3=\tservidor registrado, mas em espera (serverid = {0}).
+servertool.register4=\tservidor j\u00e1 registrado (serverid = {0}).
+
+servertool.unregister=\n\tunregister [ -serverid | -applicationName ] \n
+servertool.unregister1=cancela o registro de um servidor registrado
+servertool.unregister2=\tservidor n\u00e3o registrado.
+
+servertool.locate=\n\tlocate [ -serverid | -applicationName ] [ <-endpointType ] \n
+servertool.locate1=localiza portas de tipo espec\u00edfico para um servidor registrado
+servertool.locate2=\n\n\tNome do host {0} \n\n\t\tPorta\t\tTipo de porta\t\tId do ORB\n\t\t----\t\t---------\t\t------\n
+servertool.locateorb=\n\tlocateperorb [ -serverid | -applicationName ] [ -orbid ]\n
+servertool.locateorb1=localiza portas para um orb espec\u00edfico de servidor registrado
+servertool.locateorb2=\n\n\tNome do host {0} \n\n\t\tPorta\t\tTipo de porta\t\tId do ORB\n\t\t----\t\t--------\t\t------\n
+servertool.getserverid=\n\tgetserverid [ -applicationName ] \n
+servertool.getserverid1=retorna o id do servidor de um applicationName
+servertool.getserverid2=\tID do servidor de applicationName {0} \u00e9 {1}
+
+servertool.list=\n\tlist\n
+servertool.list1=lista todos os servidores registrados
+servertool.list2=\n\tId do servidor\tNome de classe do servidor\t\tAplicativo do servidor\n\t---------\t-----------------\t\t------------------\n
+servertool.listactive=\n\tlistactive
+servertool.listactive1=lista os servidores atualmente ativos
+servertool.listappnames=\tlistappnames\n
+servertool.listappnames1=lista os applicationNames atualmente definidos
+servertool.listappnames2=applicationNames do servidor atualmente definidos:
+
+servertool.shutdown=\n\tshutdown [ -serverid | -applicationName ]\n
+servertool.shutdown1=desliga um servidor registrado
+servertool.shutdown2=\tservidor desligado com \u00eaxito.
+servertool.startserver=\n\tstartup [ -serverid | -applicationName ]\n
+servertool.startserver1=inicia um servidor registrado
+servertool.startserver2=\tservidor iniciado com \u00eaxito.
+
+servertool.quit=\n\tquit\n
+servertool.quit1=sai desta ferramenta
+
+servertool.help=\thelp\n\tOR\n\thelp \n
+servertool.help1=obt\u00e9m ajuda
+
+servertool.orbidmap=\tUso: orblist [ -serverid | -applicationName ]\n
+servertool.orbidmap1=lista de nomes de orb e seus mapeamentos
+servertool.orbidmap2=\n\tId de ORB\t\tNome de ORB\n\t------\t\t--------\n
+pnameserv.success=NameServer persistente iniciado com \u00eaxito
+
+
+bootstrap.usage=Uso: {0} \n\nem que inclui:\n -ORBInitialPort porta inicial (necess\u00e1rio)\n -InitialServicesFile arquivo que cont\u00e9m a lista de servi\u00e7os iniciais (necess\u00e1rio)\n
+bootstrap.success=configurando porta para {0} e lendo servi\u00e7os de {1}
+bootstrap.filenotreadable=o arquivo {0} n\u00e3o \u00e9 leg\u00edvel
+bootstrap.filenotfound=arquivo {0} n\u00e3o encontrado
+bootstrap.exception=exce\u00e7\u00e3o capturada ao salvar as propriedades no arquivo {0}: Exce\u00e7\u00e3o {1}
+
+tnameserv.exception=uma exce\u00e7\u00e3o capturada ao iniciar o servi\u00e7o de inicializa\u00e7\u00e3o na porta {0}
+tnameserv.usage=tente usar outra porta com os argumentos de linha de comando -ORBInitialPort
+tnameserv.invalidhostoption=ORBInitialHost n\u00e3o \u00e9 uma op\u00e7\u00e3o v\u00e1lida para NameService
+tnameserv.orbinitialport0=ORBInitialPort 0 n\u00e3o \u00e9 uma op\u00e7\u00e3o v\u00e1lida para NameService
+tnameserv.hs1=Contexto de nomea\u00e7\u00e3o inicial:\n{0}
+tnameserv.hs2=TransientNameServer: definindo porta para as refer\u00eancias de objeto iniciais: {0}
+tnameserv.hs3=Pronto.
+
+orbd.commfailure=\nFalha ao iniciar ORBD porque ORBinitialPort j\u00e1 est\u00e1 em uso
+orbd.internalexception=\nFalha ao iniciar ORBD devido a uma exce\u00e7\u00e3o interna. \nPoss\u00edveis causas: \n1. ORBInitialPort especificado ou ORBActivationPort j\u00e1 em uso \n2. Sem permiss\u00e3o de grava\u00e7\u00e3o para gravar orb.db
+
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java
index 5c7555f3c70..7728a677ecd 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/protocol/CorbaClientRequestDispatcherImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,9 +122,6 @@ public class CorbaClientRequestDispatcherImpl
implements
ClientRequestDispatcher
{
- // Used for locking
- private Object lock = new Object();
-
public OutputObject beginRequest(Object self, String opName,
boolean isOneWay, ContactInfo contactInfo)
{
@@ -151,7 +148,8 @@ public class CorbaClientRequestDispatcherImpl
// This locking is done so that multiple connections are not created
// for the same endpoint
- synchronized (lock) {
+ //6929137 - Synchronized on contactInfo to avoid blocking across multiple endpoints
+ synchronized (contactInfo) {
if (contactInfo.isConnectionBased()) {
if (contactInfo.shouldCacheConnection()) {
connection = (CorbaConnection)
@@ -256,7 +254,7 @@ public class CorbaClientRequestDispatcherImpl
registerWaiter(messageMediator);
// Do connection reclaim now
- synchronized (lock) {
+ synchronized (contactInfo) {
if (contactInfo.isConnectionBased()) {
if (contactInfo.shouldCacheConnection()) {
OutboundConnectionCache connectionCache =
@@ -387,11 +385,15 @@ public class CorbaClientRequestDispatcherImpl
boolean retry =
getContactInfoListIterator(orb)
.reportException(messageMediator.getContactInfo(), e);
- if (retry) {
- // Must run interceptor end point before retrying.
- Exception newException =
+
+ //Bug 6382377: must not lose exception in PI
+
+ // Must run interceptor end point before retrying.
+ Exception newException =
orb.getPIHandler().invokeClientPIEndingPoint(
- ReplyMessage.SYSTEM_EXCEPTION, e);
+ ReplyMessage.SYSTEM_EXCEPTION, e);
+
+ if (retry) {
if (newException == e) {
continueOrThrowSystemOrRemarshal(messageMediator,
new RemarshalException());
@@ -400,6 +402,14 @@ public class CorbaClientRequestDispatcherImpl
newException);
}
} else {
+ if (newException instanceof RuntimeException){
+ throw (RuntimeException)newException;
+ }
+ else if (newException instanceof RemarshalException)
+ {
+ throw (RemarshalException)newException;
+ }
+
// NOTE: Interceptor ending point will run in releaseReply.
throw e;
}
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java
index d8608f21ab5..0cbce53ffc1 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaConnectionCacheBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@ import com.sun.corba.se.pept.transport.ConnectionCache;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.spi.orb.ORB;
+import com.sun.corba.se.spi.transport.CorbaConnection;
import com.sun.corba.se.spi.transport.CorbaConnectionCache;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
@@ -87,6 +88,14 @@ public abstract class CorbaConnectionCacheBase
}
}
+ public void close() {
+ synchronized (backingStore()) {
+ for (Object obj : values()) {
+ ((CorbaConnection)obj).closeConnectionResources() ;
+ }
+ }
+ }
+
public long numberOfIdleConnections()
{
long count = 0;
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java
index 5f56b560a95..fae2d157969 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaTransportManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@ import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.CompletionStatus;
import com.sun.corba.se.pept.transport.Acceptor;
+import com.sun.corba.se.pept.transport.ConnectionCache;
import com.sun.corba.se.pept.transport.ByteBufferPool;
import com.sun.corba.se.pept.transport.ContactInfo;
import com.sun.corba.se.pept.transport.InboundConnectionCache;
@@ -49,6 +50,8 @@ import com.sun.corba.se.spi.ior.ObjectAdapterId;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.transport.CorbaAcceptor;
import com.sun.corba.se.spi.transport.CorbaTransportManager;
+import com.sun.corba.se.pept.transport.Connection;
+import com.sun.corba.se.pept.transport.ConnectionCache;
// REVISIT - impl/poa specific:
import com.sun.corba.se.impl.oa.poa.Policies;
@@ -182,6 +185,12 @@ public class CorbaTransportManagerImpl
if (orb.transportDebugFlag) {
dprint(".close->");
}
+ for (Object cc : outboundConnectionCaches.values()) {
+ ((ConnectionCache)cc).close() ;
+ }
+ for (Object cc : inboundConnectionCaches.values()) {
+ ((ConnectionCache)cc).close() ;
+ }
getSelector(0).close();
} finally {
if (orb.transportDebugFlag) {
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java
index 8686439b84f..1c60088a7a3 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@ import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
import java.util.Iterator;
import java.util.List;
@@ -66,7 +67,7 @@ public class SelectorImpl
private List deferredRegistrations;
private List interestOpsList;
private HashMap listenerThreads;
- private HashMap readerThreads;
+ private Map readerThreads;
private boolean selectorStarted;
private boolean closed;
private ORBUtilSystemException wrapper ;
@@ -81,7 +82,7 @@ public class SelectorImpl
deferredRegistrations = new ArrayList();
interestOpsList = new ArrayList();
listenerThreads = new HashMap();
- readerThreads = new HashMap();
+ readerThreads = java.util.Collections.synchronizedMap(new HashMap());
closed = false;
wrapper = ORBUtilSystemException.get(orb,CORBALogDomains.RPC_TRANSPORT);
}
@@ -178,8 +179,13 @@ public class SelectorImpl
}
if (eventHandler.shouldUseSelectThreadToWait()) {
- SelectionKey selectionKey = eventHandler.getSelectionKey();
- selectionKey.cancel();
+ SelectionKey selectionKey ;
+ synchronized(deferredRegistrations) {
+ selectionKey = eventHandler.getSelectionKey();
+ }
+ if (selectionKey != null) {
+ selectionKey.cancel();
+ }
selector.wakeup();
return;
}
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java
index e294067184e..913cd903755 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java
@@ -811,6 +811,7 @@ public class SocketOrChannelConnectionImpl
dprint(".close: " + this, e);
}
}
+ closeConnectionResources();
} finally {
if (orb.transportDebugFlag) {
dprint(".close<-: " + this);
@@ -818,6 +819,28 @@ public class SocketOrChannelConnectionImpl
}
}
+ public void closeConnectionResources() {
+ if (orb.transportDebugFlag) {
+ dprint(".closeConnectionResources->: " + this);
+ }
+ Selector selector = orb.getTransportManager().getSelector(0);
+ selector.unregisterForEvent(this);
+ try {
+ if (socketChannel != null)
+ socketChannel.close() ;
+ if (socket != null && !socket.isClosed())
+ socket.close() ;
+ } catch (IOException e) {
+ if (orb.transportDebugFlag) {
+ dprint( ".closeConnectionResources: " + this, e ) ;
+ }
+ }
+ if (orb.transportDebugFlag) {
+ dprint(".closeConnectionResources<-: " + this);
+ }
+ }
+
+
public Acceptor getAcceptor()
{
return acceptor;
diff --git a/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java b/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java
index d5bee7d927f..ac926d063c0 100644
--- a/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java
+++ b/corba/src/share/classes/com/sun/corba/se/pept/transport/ConnectionCache.java
@@ -41,6 +41,12 @@ public interface ConnectionCache
public long numberOfBusyConnections();
public boolean reclaim();
+
+ /** Close all connections in the connection cache.
+ * This is used as a final cleanup, and will result
+ * in abrupt termination of any pending communications.
+ */
+ public void close();
}
// End of file.
diff --git a/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java b/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java
index b0e3f6f04dc..c7ec1ac0aa1 100644
--- a/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java
+++ b/corba/src/share/classes/com/sun/corba/se/spi/transport/CorbaConnection.java
@@ -163,6 +163,10 @@ public interface CorbaConnection
// REVISIT - MessageMediator parameter?
public void serverRequestProcessingBegins();
public void serverRequestProcessingEnds();
+
+ /** Clean up all connection resources. Used when shutting down an ORB.
+ */
+ public void closeConnectionResources();
}
// End of file.
diff --git a/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java b/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java
index 3efe5609535..c305ada5b24 100644
--- a/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java
+++ b/corba/src/share/classes/com/sun/tools/corba/se/idl/toJavaPortable/Stub.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -344,17 +344,27 @@ public class Stub implements AuxGen
stream.println (" String str = s.readUTF ();");
stream.println (" String[] args = null;");
stream.println (" java.util.Properties props = null;");
- stream.println (" org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init (args, props).string_to_object (str);");
+ stream.println (" org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);");
+ stream.println (" try {");
+ stream.println (" org.omg.CORBA.Object obj = orb.string_to_object (str);");
stream.println (" org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();");
stream.println (" _set_delegate (delegate);");
+ stream.println (" } finally {");
+ stream.println (" orb.destroy() ;");
+ stream.println (" }");
stream.println (" }");
stream.println ();
stream.println (" private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException");
stream.println (" {");
stream.println (" String[] args = null;");
stream.println (" java.util.Properties props = null;");
- stream.println (" String str = org.omg.CORBA.ORB.init (args, props).object_to_string (this);");
+ stream.println (" org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init (args, props);");
+ stream.println (" try {");
+ stream.println (" String str = orb.object_to_string (this);");
stream.println (" s.writeUTF (str);");
+ stream.println (" } finally {");
+ stream.println (" orb.destroy() ;");
+ stream.println (" }");
stream.println (" }");
}
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index a8553547e22..b92574b671c 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -134,4 +134,5 @@ bdbc48857210a509b3c50a3291ecb9dd6a72e016 jdk7-b115
5484e7c53fa7da5e869902437ee08a9ae10c1c69 jdk7-b119
f5603a6e50422046ebc0d2f1671d55cb8f1bf1e9 jdk7-b120
3f3653ab7af8dc1ddb9fa75dad56bf94f89e81a8 jdk7-b121
+3a548dc9cb456110ca8fc1514441a8c3bda0014d jdk7-b122
5484e7c53fa7da5e869902437ee08a9ae10c1c69 hs20-b03
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
index 967f8a4f100..9cf6122c761 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,15 +99,8 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
long typeEntrySizeOffset;
long typeEntryArrayStride;
- typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
- typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
- typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
- typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
- typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
- typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
- typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
-
- // Fetch the address of the VMTypeEntry*
+ // Fetch the address of the VMTypeEntry*. We get this symbol first
+ // and try to use it to make sure that symbol lookup is working.
Address entryAddr = lookupInProcess("gHotSpotVMTypes");
// System.err.println("gHotSpotVMTypes address = " + entryAddr);
// Dereference this once to get the pointer to the first VMTypeEntry
@@ -118,6 +111,14 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue");
}
+ typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
+ typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
+ typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
+ typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
+ typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
+ typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
+ typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
+
// Start iterating down it until we find an entry with no name
Address typeNameAddr = null;
do {
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java
index b2c988224fd..d29a626598b 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,10 +122,14 @@ public class COFFFileParser {
private MemoizedObject[] sectionHeaders;
private MemoizedObject[] symbols;
+ // Init stringTable at decl time since other fields init'ed in the
+ // constructor need the String Table.
private MemoizedObject stringTable = new MemoizedObject() {
public Object computeValue() {
+ // the String Table follows the Symbol Table
int ptr = getPointerToSymbolTable();
if (ptr == 0) {
+ // no Symbol Table so no String Table
return new StringTable(0);
} else {
return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols());
@@ -140,6 +144,8 @@ public class COFFFileParser {
timeDateStamp = readInt();
pointerToSymbolTable = readInt();
numberOfSymbols = readInt();
+ // String Table can be accessed at this point because
+ // pointerToSymbolTable and numberOfSymbols fields are set.
sizeOfOptionalHeader = readShort();
characteristics = readShort();
@@ -222,6 +228,8 @@ public class COFFFileParser {
private MemoizedObject windowsSpecificFields;
private MemoizedObject dataDirectories;
+ // We use an offset of 2 because OptionalHeaderStandardFieldsImpl doesn't
+ // include the 'magic' field.
private static final int STANDARD_FIELDS_OFFSET = 2;
private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28;
private static final int PE32_DATA_DIRECTORIES_OFFSET = 96;
@@ -288,7 +296,7 @@ public class COFFFileParser {
private int sizeOfUninitializedData;
private int addressOfEntryPoint;
private int baseOfCode;
- private int baseOfData;
+ private int baseOfData; // only set in PE32
OptionalHeaderStandardFieldsImpl(int offset,
boolean isPE32Plus) {
@@ -301,7 +309,8 @@ public class COFFFileParser {
sizeOfUninitializedData = readInt();
addressOfEntryPoint = readInt();
baseOfCode = readInt();
- if (isPE32Plus) {
+ if (!isPE32Plus) {
+ // only available in PE32
baseOfData = readInt();
}
}
@@ -433,7 +442,10 @@ public class COFFFileParser {
if (dir.getRVA() == 0 || dir.getSize() == 0) {
return null;
}
- return new ExportDirectoryTableImpl(rvaToFileOffset(dir.getRVA()), dir.getSize());
+ // ExportDirectoryTableImpl needs both the RVA and the
+ // RVA converted to a file offset.
+ return new
+ ExportDirectoryTableImpl(dir.getRVA(), dir.getSize());
}
};
@@ -526,6 +538,7 @@ public class COFFFileParser {
}
class ExportDirectoryTableImpl implements ExportDirectoryTable {
+ private int exportDataDirRVA;
private int offset;
private int size;
@@ -548,8 +561,9 @@ public class COFFFileParser {
private MemoizedObject exportOrdinalTable;
private MemoizedObject exportAddressTable;
- ExportDirectoryTableImpl(int offset, int size) {
- this.offset = offset;
+ ExportDirectoryTableImpl(int exportDataDirRVA, int size) {
+ this.exportDataDirRVA = exportDataDirRVA;
+ offset = rvaToFileOffset(exportDataDirRVA);
this.size = size;
seek(offset);
exportFlags = readInt();
@@ -595,6 +609,7 @@ public class COFFFileParser {
exportOrdinalTable = new MemoizedObject() {
public Object computeValue() {
+ // number of ordinals is same as the number of name pointers
short[] ordinals = new short[getNumberOfNamePointers()];
seek(rvaToFileOffset(getOrdinalTableRVA()));
for (int i = 0; i < ordinals.length; i++) {
@@ -608,14 +623,18 @@ public class COFFFileParser {
public Object computeValue() {
int[] addresses = new int[getNumberOfAddressTableEntries()];
seek(rvaToFileOffset(getExportAddressTableRVA()));
- // Must make two passes to avoid rvaToFileOffset
- // destroying seek() position
+ // The Export Address Table values are a union of two
+ // possible values:
+ // Export RVA - The address of the exported symbol when
+ // loaded into memory, relative to the image base.
+ // This value doesn't get converted into a file offset.
+ // Forwarder RVA - The pointer to a null-terminated ASCII
+ // string in the export section. This value gets
+ // converted into a file offset because we have to
+ // fetch the string.
for (int i = 0; i < addresses.length; i++) {
addresses[i] = readInt();
}
- for (int i = 0; i < addresses.length; i++) {
- addresses[i] = rvaToFileOffset(addresses[i]);
- }
return addresses;
}
};
@@ -648,11 +667,12 @@ public class COFFFileParser {
public boolean isExportAddressForwarder(short ordinal) {
int addr = getExportAddress(ordinal);
- return ((offset <= addr) && (addr < (offset + size)));
+ return ((exportDataDirRVA <= addr) &&
+ (addr < (exportDataDirRVA + size)));
}
public String getExportAddressForwarder(short ordinal) {
- seek(getExportAddress(ordinal));
+ seek(rvaToFileOffset(getExportAddress(ordinal)));
return readCString();
}
@@ -3371,10 +3391,17 @@ public class COFFFileParser {
throw new COFFException(e);
}
// Look up in string table
+ // FIXME: this index value is assumed to be in the valid range
name = getStringTable().get(index);
} else {
try {
- name = new String(tmpName, US_ASCII);
+ int length = 0;
+ // find last non-NULL
+ for (; length < tmpName.length && tmpName[length] != '\0';) {
+ length++;
+ }
+ // don't include NULL chars in returned name String
+ name = new String(tmpName, 0, length, US_ASCII);
} catch (UnsupportedEncodingException e) {
throw new COFFException(e);
}
@@ -3487,6 +3514,7 @@ public class COFFFileParser {
tmpName[5] << 16 |
tmpName[6] << 8 |
tmpName[7]);
+ // FIXME: stringOffset is assumed to be in the valid range
name = getStringTable().getAtOffset(stringOffset);
}
@@ -3698,12 +3726,13 @@ public class COFFFileParser {
StringTable(int offset) {
if (offset == 0) {
+ // no String Table
strings = new COFFString[0];
return;
}
seek(offset);
- int length = readInt();
+ int length = readInt(); // length includes itself
byte[] data = new byte[length - 4];
int numBytesRead = readBytes(data);
if (numBytesRead != data.length) {
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java
index ec563f1d626..fd9d39aa5c5 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,35 +37,48 @@ public class DumpExports {
String filename = args[0];
COFFFile file = COFFFileParser.getParser().parse(filename);
- ExportDirectoryTable exports =
- file.getHeader().
- getOptionalHeader().
- getDataDirectories().
- getExportDirectoryTable();
+
+ // get common point for both things we want to dump
+ OptionalHeaderDataDirectories dataDirs = file.getHeader().getOptionalHeader().
+ getDataDirectories();
+
+ // dump the header data directory for the Export Table:
+ DataDirectory dir = dataDirs.getExportTable();
+ System.out.println("Export table: RVA = " + dir.getRVA() + "/0x" +
+ Integer.toHexString(dir.getRVA()) + ", size = " + dir.getSize() + "/0x" +
+ Integer.toHexString(dir.getSize()));
+
+ System.out.println(file.getHeader().getNumberOfSections() + " sections in file");
+ for (int i = 1; i <= file.getHeader().getNumberOfSections(); i++) {
+ SectionHeader sec = file.getHeader().getSectionHeader(i);
+ System.out.println(" Section " + i + ":");
+ System.out.println(" Name = '" + sec.getName() + "'");
+ System.out.println(" VirtualSize = " + sec.getSize() + "/0x" +
+ Integer.toHexString(sec.getSize()));
+ System.out.println(" VirtualAddress = " + sec.getVirtualAddress() + "/0x" +
+ Integer.toHexString(sec.getVirtualAddress()));
+ System.out.println(" SizeOfRawData = " + sec.getSizeOfRawData() + "/0x" +
+ Integer.toHexString(sec.getSizeOfRawData()));
+ System.out.println(" PointerToRawData = " + sec.getPointerToRawData() + "/0x" +
+ Integer.toHexString(sec.getPointerToRawData()));
+ }
+
+ ExportDirectoryTable exports = dataDirs.getExportDirectoryTable();
if (exports == null) {
System.out.println("No exports found.");
} else {
- System.out.println(file.getHeader().getNumberOfSections() + " sections in file");
- for (int i = 0; i < file.getHeader().getNumberOfSections(); i++) {
- System.out.println(" Section " + i + ": " + file.getHeader().getSectionHeader(1 + i).getName());
- }
-
- DataDirectory dir = file.getHeader().getOptionalHeader().getDataDirectories().getExportTable();
- System.out.println("Export table: RVA = 0x" + Integer.toHexString(dir.getRVA()) +
- ", size = 0x" + Integer.toHexString(dir.getSize()));
-
System.out.println("DLL name: " + exports.getDLLName());
System.out.println("Time/date stamp 0x" + Integer.toHexString(exports.getTimeDateStamp()));
System.out.println("Major version 0x" + Integer.toHexString(exports.getMajorVersion() & 0xFFFF));
System.out.println("Minor version 0x" + Integer.toHexString(exports.getMinorVersion() & 0xFFFF));
- System.out.println(exports.getNumberOfNamePointers() + " functions found");
+ System.out.println(exports.getNumberOfNamePointers() + " exports found");
for (int i = 0; i < exports.getNumberOfNamePointers(); i++) {
- System.out.println(" 0x" +
- Integer.toHexString(exports.getExportAddress(exports.getExportOrdinal(i))) +
- " " +
- (exports.isExportAddressForwarder(exports.getExportOrdinal(i)) ?
- ("Forwarded to " + exports.getExportAddressForwarder(exports.getExportOrdinal(i))) :
- exports.getExportName(i)));
+ short ordinal = exports.getExportOrdinal(i);
+ System.out.print("[" + i + "] '" + exports.getExportName(i) + "': [" +
+ ordinal + "] = 0x" + Integer.toHexString(exports.getExportAddress(ordinal)));
+ System.out.println(exports.isExportAddressForwarder(ordinal)
+ ? " Forwarded to '" + exports.getExportAddressForwarder(ordinal) + "'"
+ : "");
}
}
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java
index 6f026838d58..e6f42df3ac9 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,8 +42,8 @@ public class TestParser {
COFFHeader header = file.getHeader();
int numSections = header.getNumberOfSections();
System.out.println(numSections + " sections detected.");
- for (int i = 0; i < numSections; i++) {
- SectionHeader secHeader = header.getSectionHeader(1 + i);
+ for (int i = 1; i <= numSections; i++) {
+ SectionHeader secHeader = header.getSectionHeader(i);
System.out.println(secHeader.getName());
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java
index 53141a6d2d1..3e5a6aa96b6 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -506,7 +506,6 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
throw new DebuggerException("Unimplemented");
}
- private static String DTFWHome;
private static String imagePath;
private static String symbolPath;
private static boolean useNativeLookup;
@@ -514,81 +513,143 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
static {
/*
- * sawindbg.dll depends on dbgeng.dll which
- * itself depends on dbghelp.dll. dbgeng.dll and dbghelp.dll.
- * On systems newer than Windows 2000, these two .dlls are
- * in the standard system directory so we will find them there.
- * On Windows 2000 and earlier, these files do not exist.
- * The user must download Debugging Tools For Windows (DTFW)
- * and install it in order to use SA.
+ * sawindbg.dll depends on dbgeng.dll which itself depends on
+ * dbghelp.dll. We have to make sure that the dbgeng.dll and
+ * dbghelp.dll that we load are compatible with each other. We
+ * load both of those libraries from the same directory based
+ * on the theory that co-located libraries are compatible.
*
- * We have to make sure we use the two files from the same directory
- * in case there are more than one copy on the system because
- * one version of dbgeng.dll might not be compatible with a
- * different version of dbghelp.dll.
- * We first look for them in the directory pointed at by
- * env. var. DEBUGGINGTOOLSFORWINDOWS, next in the default
- * installation dir for DTFW, and lastly in the standard
- * system directory. We expect that that we will find
- * them in the standard system directory on all systems
- * newer than Windows 2000.
+ * On Windows 2000 and earlier, dbgeng.dll and dbghelp.dll were
+ * not included as part of the standard system directory. On
+ * systems newer than Windows 2000, dbgeng.dll and dbghelp.dll
+ * are included in the standard system directory. However, the
+ * versions included in the standard system directory may not
+ * be able to handle symbol information for the newer compilers.
+ *
+ * We search for and explicitly load the libraries using the
+ * following directory search order:
+ *
+ * - java.home/bin (same as $JAVA_HOME/jre/bin)
+ * - dir named by DEBUGGINGTOOLSFORWINDOWS environment variable
+ * - various "Debugging Tools For Windows" program directories
+ * - the system directory ($SYSROOT/system32)
+ *
+ * If SA is invoked with -Dsun.jvm.hotspot.loadLibrary.DEBUG=1,
+ * then debug messages about library loading are printed to
+ * System.err.
*/
- String dirName = null;
- DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
- if (DTFWHome == null) {
- // See if we have the files in the default location.
- String sysRoot = System.getenv("SYSTEMROOT");
- DTFWHome = sysRoot + File.separator +
- ".." + File.separator + "Program Files" +
- File.separator + "Debugging Tools For Windows";
- }
+ String dbgengPath = null;
+ String dbghelpPath = null;
+ String sawindbgPath = null;
+ List searchList = new ArrayList();
+
+ boolean loadLibraryDEBUG =
+ System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null;
{
- String dbghelp = DTFWHome + File.separator + "dbghelp.dll";
- String dbgeng = DTFWHome + File.separator + "dbgeng.dll";
- File fhelp = new File(dbghelp);
- File feng = new File(dbgeng);
- if (fhelp.exists() && feng.exists()) {
- // found both, we are happy.
- // NOTE: The order of loads is important! If we load dbgeng.dll
- // first, then the dependency - dbghelp.dll - will be loaded
- // from usual DLL search thereby defeating the purpose!
- System.load(dbghelp);
- System.load(dbgeng);
- } else if (! fhelp.exists() && ! feng.exists()) {
- // neither exist. We will ignore this dir and assume
- // they are in the system dir.
- DTFWHome = null;
- } else {
- // one exists but not the other
- //System.err.println("Error: Both files dbghelp.dll and dbgeng.dll "
- // "must exist in directory " + DTFWHome);
- throw new UnsatisfiedLinkError("Both files dbghelp.dll and " +
- "dbgeng.dll must exist in " +
- "directory " + DTFWHome);
- }
- }
- if (DTFWHome == null) {
- // The files better be in the system dir.
- String sysDir = System.getenv("SYSTEMROOT") +
- File.separator + "system32";
+ // First place to search is co-located with sawindbg.dll in
+ // $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre):
+ searchList.add(System.getProperty("java.home") + File.separator + "bin");
+ sawindbgPath = (String) searchList.get(0) + File.separator +
+ "sawindbg.dll";
- File feng = new File(sysDir + File.separator + "dbgeng.dll");
- if (!feng.exists()) {
- throw new UnsatisfiedLinkError("File dbgeng.dll does not exist in " +
- sysDir + ". Please search microsoft.com " +
- "for Debugging Tools For Windows, and " +
- "either download it to the default " +
- "location, or download it to a custom " +
- "location and set environment variable " +
- " DEBUGGINGTOOLSFORWINDOWS " +
- "to the pathname of that location.");
+ // second place to search is specified by an environment variable:
+ String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
+ if (DTFWHome != null) {
+ searchList.add(DTFWHome);
}
+
+ // The third place to search is the install directory for the
+ // "Debugging Tools For Windows" package; so far there are three
+ // name variations that we know of:
+ String sysRoot = System.getenv("SYSTEMROOT");
+ DTFWHome = sysRoot + File.separator + ".." + File.separator +
+ "Program Files" + File.separator + "Debugging Tools For Windows";
+ searchList.add(DTFWHome);
+ searchList.add(DTFWHome + " (x86)");
+ searchList.add(DTFWHome + " (x64)");
+
+ // The last place to search is the system directory:
+ searchList.add(sysRoot + File.separator + "system32");
}
+ for (int i = 0; i < searchList.size(); i++) {
+ File dir = new File((String) searchList.get(i));
+ if (!dir.exists()) {
+ if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: '" + searchList.get(i) +
+ "': directory does not exist.");
+ }
+ // this search directory doesn't exist so skip it
+ continue;
+ }
+
+ dbgengPath = (String) searchList.get(i) + File.separator + "dbgeng.dll";
+ dbghelpPath = (String) searchList.get(i) + File.separator + "dbghelp.dll";
+
+ File feng = new File(dbgengPath);
+ File fhelp = new File(dbghelpPath);
+ if (feng.exists() && fhelp.exists()) {
+ // both files exist so we have a match
+ break;
+ }
+
+ // At least one of the files does not exist; no warning if both
+ // don't exist. If just one doesn't exist then we don't check
+ // loadLibraryDEBUG because we have a mis-configured system.
+ if (feng.exists()) {
+ System.err.println("WARNING: found '" + dbgengPath +
+ "' but did not find '" + dbghelpPath + "'; ignoring '" +
+ dbgengPath + "'.");
+ } else if (fhelp.exists()) {
+ System.err.println("WARNING: found '" + dbghelpPath +
+ "' but did not find '" + dbgengPath + "'; ignoring '" +
+ dbghelpPath + "'.");
+ } else if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: searched '" + searchList.get(i) +
+ "': dbgeng.dll and dbghelp.dll were not found.");
+ }
+ dbgengPath = null;
+ dbghelpPath = null;
+ }
+
+ if (dbgengPath == null || dbghelpPath == null) {
+ // at least one of the files wasn't found anywhere we searched
+ String mesg = null;
+
+ if (dbgengPath == null && dbghelpPath == null) {
+ mesg = "dbgeng.dll and dbghelp.dll cannot be found. ";
+ } else if (dbgengPath == null) {
+ mesg = "dbgeng.dll cannot be found (dbghelp.dll was found). ";
+ } else {
+ mesg = "dbghelp.dll cannot be found (dbgeng.dll was found). ";
+ }
+ throw new UnsatisfiedLinkError(mesg +
+ "Please search microsoft.com for 'Debugging Tools For Windows', " +
+ "and either download it to the default location, or download it " +
+ "to a custom location and set environment variable " +
+ "'DEBUGGINGTOOLSFORWINDOWS' to the pathname of that location.");
+ }
+
+ // NOTE: The order of loads is important! If we load dbgeng.dll
+ // first, then the dependency - dbghelp.dll - will be loaded
+ // from usual DLL search thereby defeating the purpose!
+ if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: loading '" + dbghelpPath + "'.");
+ }
+ System.load(dbghelpPath);
+ if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: loading '" + dbgengPath + "'.");
+ }
+ System.load(dbgengPath);
+
// Now, load sawindbg.dll
- System.loadLibrary("sawindbg");
+ if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: loading '" + sawindbgPath + "'.");
+ }
+ System.load(sawindbgPath);
+
// where do I find '.exe', '.dll' files?
imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath");
if (imagePath == null) {
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java
index fb7727a7cc3..31cc2a956e1 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java
@@ -60,10 +60,7 @@ public class ConstantPool extends Oop implements ClassConstants {
headerSize = type.getSize();
elementSize = 0;
// fetch constants:
- MULTI_OPERAND_COUNT_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_multi_operand_count_offset").intValue();
- MULTI_OPERAND_BASE_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_multi_operand_base_offset").intValue();
INDY_BSM_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_bsm_offset").intValue();
- INDY_NT_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_nt_offset").intValue();
INDY_ARGC_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argc_offset").intValue();
INDY_ARGV_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argv_offset").intValue();
}
@@ -83,10 +80,7 @@ public class ConstantPool extends Oop implements ClassConstants {
private static long headerSize;
private static long elementSize;
- private static int MULTI_OPERAND_COUNT_OFFSET;
- private static int MULTI_OPERAND_BASE_OFFSET;
private static int INDY_BSM_OFFSET;
- private static int INDY_NT_OFFSET;
private static int INDY_ARGC_OFFSET;
private static int INDY_ARGV_OFFSET;
@@ -296,20 +290,23 @@ public class ConstantPool extends Oop implements ClassConstants {
}
/** Lookup for multi-operand (InvokeDynamic) entries. */
- public int[] getMultiOperandsAt(int i) {
+ public short[] getBootstrapSpecifierAt(int i) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool");
}
- int pos = this.getIntAt(i);
- int countPos = pos + MULTI_OPERAND_COUNT_OFFSET; // == pos-1
- int basePos = pos + MULTI_OPERAND_BASE_OFFSET; // == pos
- if (countPos < 0) return null; // safety first
+ if (getTagAt(i).value() == JVM_CONSTANT_InvokeDynamicTrans)
+ return null;
+ int bsmSpec = extractLowShortFromInt(this.getIntAt(i));
TypeArray operands = getOperands();
if (operands == null) return null; // safety first
- int length = operands.getIntAt(countPos);
- int[] values = new int[length];
- for (int j = 0; j < length; j++) {
- values[j] = operands.getIntAt(basePos+j);
+ int basePos = VM.getVM().buildIntFromShorts(operands.getShortAt(bsmSpec * 2 + 0),
+ operands.getShortAt(bsmSpec * 2 + 1));
+ int argv = basePos + INDY_ARGV_OFFSET;
+ int argc = operands.getShortAt(basePos + INDY_ARGC_OFFSET);
+ int endPos = argv + argc;
+ short[] values = new short[endPos - basePos];
+ for (int j = 0; j < values.length; j++) {
+ values[j] = operands.getShortAt(basePos+j);
}
return values;
}
@@ -334,6 +331,7 @@ public class ConstantPool extends Oop implements ClassConstants {
case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle";
case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType";
case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic";
+ case JVM_CONSTANT_InvokeDynamicTrans: return "JVM_CONSTANT_InvokeDynamic/transitional";
case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";
case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
@@ -393,6 +391,7 @@ public class ConstantPool extends Oop implements ClassConstants {
case JVM_CONSTANT_MethodHandle:
case JVM_CONSTANT_MethodType:
case JVM_CONSTANT_InvokeDynamic:
+ case JVM_CONSTANT_InvokeDynamicTrans:
visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
break;
}
@@ -556,19 +555,16 @@ public class ConstantPool extends Oop implements ClassConstants {
break;
}
+ case JVM_CONSTANT_InvokeDynamicTrans:
case JVM_CONSTANT_InvokeDynamic: {
dos.writeByte(cpConstType);
- int[] values = getMultiOperandsAt(ci);
- for (int vn = 0; vn < values.length; vn++) {
- dos.writeShort(values[vn]);
- }
- int bootstrapMethodIndex = values[INDY_BSM_OFFSET];
- int nameAndTypeIndex = values[INDY_NT_OFFSET];
- int argumentCount = values[INDY_ARGC_OFFSET];
- assert(INDY_ARGV_OFFSET + argumentCount == values.length);
- if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bootstrapMethodIndex
- + ", N&T = " + nameAndTypeIndex
- + ", argc = " + argumentCount);
+ int value = getIntAt(ci);
+ short bsmIndex = (short) extractLowShortFromInt(value);
+ short nameAndTypeIndex = (short) extractHighShortFromInt(value);
+ dos.writeShort(bsmIndex);
+ dos.writeShort(nameAndTypeIndex);
+ if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bsmIndex
+ + ", N&T = " + nameAndTypeIndex);
break;
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java
index c0780918398..494f1765f13 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java
@@ -321,13 +321,16 @@ public class ClassWriter implements /* imports */ ClassConstants
break;
}
+ case JVM_CONSTANT_InvokeDynamicTrans:
case JVM_CONSTANT_InvokeDynamic: {
dos.writeByte(cpConstType);
- int[] values = cpool.getMultiOperandsAt(ci);
- for (int vn = 0; vn < values.length; vn++) {
- dos.writeShort(values[vn]);
- }
- if (DEBUG) debugMessage("CP[" + ci + "] = INDY indexes = " + Arrays.toString(values));
+ int value = cpool.getIntAt(ci);
+ short bsmIndex = (short) extractLowShortFromInt(value);
+ short nameAndTypeIndex = (short) extractHighShortFromInt(value);
+ dos.writeShort(bsmIndex);
+ dos.writeShort(nameAndTypeIndex);
+ if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " +
+ bsmIndex + ", N&T = " + nameAndTypeIndex);
break;
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
index 49c101fe6a0..979d80b3062 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
@@ -30,6 +30,7 @@ import sun.jvm.hotspot.asm.*;
import sun.jvm.hotspot.asm.sparc.*;
import sun.jvm.hotspot.asm.x86.*;
import sun.jvm.hotspot.asm.ia64.*;
+import sun.jvm.hotspot.asm.amd64.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.debugger.*;
@@ -198,6 +199,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
cpuHelper = new SPARCHelper();
} else if (cpu.equals("x86")) {
cpuHelper = new X86Helper();
+ } else if (cpu.equals("amd64")) {
+ cpuHelper = new AMD64Helper();
} else if (cpu.equals("ia64")) {
cpuHelper = new IA64Helper();
} else {
@@ -460,7 +463,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
return buf.toString();
}
- private String genListOfShort(int[] values) {
+ private String genListOfShort(short[] values) {
+ if (values == null || values.length == 0) return "";
Formatter buf = new Formatter(genHTML);
buf.append('[');
for (int i = 0; i < values.length; i++) {
@@ -594,9 +598,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
buf.cell(Integer.toString(cpool.getIntAt(index)));
break;
+ case JVM_CONSTANT_InvokeDynamicTrans:
case JVM_CONSTANT_InvokeDynamic:
buf.cell("JVM_CONSTANT_InvokeDynamic");
- buf.cell(genListOfShort(cpool.getMultiOperandsAt(index)));
+ buf.cell(genLowHighShort(cpool.getIntAt(index)) +
+ genListOfShort(cpool.getBootstrapSpecifierAt(index)));
break;
default:
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java
index 849531da1a5..1ee547be39c 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java
@@ -40,7 +40,7 @@ public class ConstantTag {
private static int JVM_CONSTANT_NameAndType = 12;
private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292
private static int JVM_CONSTANT_MethodType = 16; // JSR 292
- // static int JVM_CONSTANT_InvokeDynamicTrans = 17; // JSR 292, only occurs in old class files
+ private static int JVM_CONSTANT_InvokeDynamicTrans = 17; // JSR 292, only occurs in old class files
private static int JVM_CONSTANT_InvokeDynamic = 18; // JSR 292
private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization
private static int JVM_CONSTANT_UnresolvedClass = 100; // Temporary tag until actual use
@@ -67,6 +67,8 @@ public class ConstantTag {
this.tag = tag;
}
+ public int value() { return tag; }
+
public boolean isKlass() { return tag == JVM_CONSTANT_Class; }
public boolean isField () { return tag == JVM_CONSTANT_Fieldref; }
public boolean isMethod() { return tag == JVM_CONSTANT_Methodref; }
@@ -81,6 +83,7 @@ public class ConstantTag {
public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; }
public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; }
public boolean isInvokeDynamic() { return tag == JVM_CONSTANT_InvokeDynamic; }
+ public boolean isInvokeDynamicTrans() { return tag == JVM_CONSTANT_InvokeDynamicTrans; }
public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; }
diff --git a/hotspot/make/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make
index a3edb07fc94..4ba1f0e74b4 100644
--- a/hotspot/make/linux/makefiles/buildtree.make
+++ b/hotspot/make/linux/makefiles/buildtree.make
@@ -124,7 +124,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS))
BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \
- env.sh env.csh .dbxrc test_gamma
+ env.sh env.csh jdkpath.sh .dbxrc test_gamma
BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
@@ -318,6 +318,13 @@ env.csh: env.sh
sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
) > $@
+jdkpath.sh: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo "JDK=${JAVA_HOME}"; \
+ ) > $@
+
.dbxrc: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make
index 6ab3f738c2e..653da7de6a7 100644
--- a/hotspot/make/linux/makefiles/vm.make
+++ b/hotspot/make/linux/makefiles/vm.make
@@ -168,7 +168,9 @@ endif
# Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE.
define findsrc
- $(notdir $(shell find $(1) \( -name \*.c -o -name \*.cpp -o -name \*.s \) -a \! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \) ))
+ $(notdir $(shell find $(1)/. ! -name . -prune \
+ -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \
+ -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \)))
endef
Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e)))
diff --git a/hotspot/make/solaris/makefiles/buildtree.make b/hotspot/make/solaris/makefiles/buildtree.make
index c0c7831e02f..9a1e5fd96d4 100644
--- a/hotspot/make/solaris/makefiles/buildtree.make
+++ b/hotspot/make/solaris/makefiles/buildtree.make
@@ -117,7 +117,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS))
BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \
- env.ksh env.csh .dbxrc test_gamma
+ env.ksh env.csh jdkpath.sh .dbxrc test_gamma
BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
@@ -314,6 +314,13 @@ env.csh: env.ksh
sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
) > $@
+jdkpath.sh: $(BUILDTREE_MAKE)
+ @echo Creating $@ ...
+ $(QUIETLY) ( \
+ $(BUILDTREE_COMMENT); \
+ echo "JDK=${JAVA_HOME}"; \
+ ) > $@
+
.dbxrc: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make
index 6e5e59b7416..93d8396faa9 100644
--- a/hotspot/make/solaris/makefiles/vm.make
+++ b/hotspot/make/solaris/makefiles/vm.make
@@ -184,7 +184,9 @@ endif
# Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE.
define findsrc
- $(notdir $(shell find $(1) \( -name \*.c -o -name \*.cpp -o -name \*.s \) -a \! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \) ))
+ $(notdir $(shell find $(1)/. ! -name . -prune \
+ -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \
+ -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \)))
endef
Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e)))
diff --git a/hotspot/make/windows/build_vm_def.sh b/hotspot/make/windows/build_vm_def.sh
index 5eae61ce390..9c9593b4a7f 100644
--- a/hotspot/make/windows/build_vm_def.sh
+++ b/hotspot/make/windows/build_vm_def.sh
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,9 @@ fi
echo "EXPORTS" > vm1.def
AWK="$MKS_HOME/awk.exe"
+if [ ! -e $AWK ]; then
+ AWK="$MKS_HOME/gawk.exe"
+fi
GREP="$MKS_HOME/grep.exe"
SORT="$MKS_HOME/sort.exe"
UNIQ="$MKS_HOME/uniq.exe"
@@ -57,7 +60,7 @@ if [ "x$1" != "x" ]; then
LINK_VER="$1"
fi
-if [ "x$LINK_VER" != "x800" -a "x$LINK_VER" != "x900" ]; then
+if [ "x$LINK_VER" != "x800" -a "x$LINK_VER" != "x900" -a "x$LINK_VER" != "x1000" ]; then
$DUMPBIN /symbols *.obj | "$GREP" "??_7.*@@6B@" | "$GREP" -v "type_info" | "$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
diff --git a/hotspot/make/windows/create.bat b/hotspot/make/windows/create.bat
index f291a0c562d..4592d8becfe 100644
--- a/hotspot/make/windows/create.bat
+++ b/hotspot/make/windows/create.bat
@@ -36,6 +36,20 @@ REM
REM Note: Running this batch file from the Windows command shell requires
REM that "grep" be accessible on the PATH. An MKS install does this.
REM
+
+cl 2>NUL >NUL
+if %errorlevel% == 0 goto nexttest
+echo Make sure cl.exe is in your PATH before running this script.
+goto end
+
+:nexttest
+grep -V 2>NUL >NUL
+if %errorlevel% == 0 goto testit
+echo Make sure grep.exe is in your PATH before running this script. Either cygwin or MKS should work.
+goto end
+
+
+:testit
cl 2>&1 | grep "IA-64" >NUL
if %errorlevel% == 0 goto isia64
cl 2>&1 | grep "AMD64" >NUL
@@ -44,37 +58,40 @@ set ARCH=x86
set BUILDARCH=i486
set Platform_arch=x86
set Platform_arch_model=x86_32
-goto end
+goto done
:amd64
set ARCH=x86
set BUILDARCH=amd64
set Platform_arch=x86
set Platform_arch_model=x86_64
-goto end
+goto done
:isia64
set ARCH=ia64
set BUILDARCH=ia64
set Platform_arch=ia64
set Platform_arch_model=ia64
-:end
+:done
setlocal
if "%1" == "" goto usage
-if not "%4" == "" goto usage
+if not "%2" == "" goto usage
+
+REM Set HotSpotWorkSpace to the directy two steps above this script
+for %%i in ("%~dp0..") do ( set HotSpotWorkSpace=%%~dpi)
+set HotSpotBuildRoot=%HotSpotWorkSpace%build
+set HotSpotBuildSpace=%HotSpotBuildRoot%\vs
+set HotSpotJDKDist=%1
-set HotSpotWorkSpace=%1
-set HotSpotBuildSpace=%2
-set HotSpotJDKDist=%3
REM figure out MSC version
for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i
echo **************************************************************
-set ProjectFile=vm.vcproj
+set ProjectFile=jvm.vcproj
if "%MSC_VER%" == "1200" (
-set ProjectFile=vm.dsp
+set ProjectFile=jvm.dsp
echo Will generate VC6 project {unsupported}
) else (
if "%MSC_VER%" == "1400" (
@@ -83,10 +100,16 @@ echo Will generate VC8 {Visual Studio 2005}
if "%MSC_VER%" == "1500" (
echo Will generate VC9 {Visual Studio 2008}
) else (
+if "%MSC_VER%" == "1600" (
+echo Detected Visual Studio 2010, but
+echo will generate VC9 {Visual Studio 2008}
+echo Use conversion wizard in VS 2010.
+) else (
echo Will generate VC7 project {Visual Studio 2003 .NET}
)
)
)
+)
echo %ProjectFile%
echo **************************************************************
@@ -118,6 +141,8 @@ goto usage
:test3
if not "%HOTSPOTMKSHOME%" == "" goto makedir
+if exist c:\cygwin\bin set HOTSPOTMKSHOME=c:\cygwin\bin
+if not "%HOTSPOTMKSHOME%" == "" goto makedir
echo Warning: please set variable HOTSPOTMKSHOME to place where
echo your MKS/Cygwin installation is
echo.
@@ -133,21 +158,24 @@ echo HotSpotJDKDist=%HotSpotJDKDist%
REM This is now safe to do.
:copyfiles
for /D %%i in (compiler1, compiler2, tiered, core, kernel) do (
-if NOT EXIST %HotSpotBuildSpace%\%%i mkdir %HotSpotBuildSpace%\%%i
-copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\ > NUL
+if NOT EXIST %HotSpotBuildSpace%\%%i\generated mkdir %HotSpotBuildSpace%\%%i\generated
+copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\generated > NUL
)
REM force regneration of ProjectFile
if exist %HotSpotBuildSpace%\%ProjectFile% del %HotSpotBuildSpace%\%ProjectFile%
for /D %%i in (compiler1, compiler2, tiered, core, kernel) do (
-
-echo # Generated file! > %HotSpotBuildSpace%\%%i\local.make
+echo -- %%i --
+echo # Generated file! > %HotSpotBuildSpace%\%%i\local.make
echo # Changing a variable below and then deleting %ProjectFile% will cause >> %HotSpotBuildSpace%\%%i\local.make
echo # %ProjectFile% to be regenerated with the new values. Changing the >> %HotSpotBuildSpace%\%%i\local.make
-echo # version requires rerunning create.bat. >> %HotSpotBuildSpace%\%%i\local.make
+echo # version requires rerunning create.bat. >> %HotSpotBuildSpace%\%%i\local.make
echo. >> %HotSpotBuildSpace%\%%i\local.make
+echo Variant=%%i >> %HotSpotBuildSpace%\%%i\local.make
+echo WorkSpace=%HotSpotWorkSpace% >> %HotSpotBuildSpace%\%%i\local.make
echo HOTSPOTWORKSPACE=%HotSpotWorkSpace% >> %HotSpotBuildSpace%\%%i\local.make
+echo HOTSPOTBUILDROOT=%HotSpotBuildRoot% >> %HotSpotBuildSpace%\%%i\local.make
echo HOTSPOTBUILDSPACE=%HotSpotBuildSpace% >> %HotSpotBuildSpace%\%%i\local.make
echo HOTSPOTJDKDIST=%HotSpotJDKDist% >> %HotSpotBuildSpace%\%%i\local.make
echo ARCH=%ARCH% >> %HotSpotBuildSpace%\%%i\local.make
@@ -155,42 +183,35 @@ echo BUILDARCH=%BUILDARCH% >> %HotSpotBuildSpace%\%%i\local.m
echo Platform_arch=%Platform_arch% >> %HotSpotBuildSpace%\%%i\local.make
echo Platform_arch_model=%Platform_arch_model% >> %HotSpotBuildSpace%\%%i\local.make
-pushd %HotSpotBuildSpace%\%%i
+for /D %%j in (debug, fastdebug, product) do (
+if NOT EXIST %HotSpotBuildSpace%\%%i\%%j mkdir %HotSpotBuildSpace%\%%i\%%j
+)
+
+pushd %HotSpotBuildSpace%\%%i\generated
nmake /nologo
popd
)
-pushd %HotSpotBuildSpace%
+pushd %HotSpotBuildRoot%
-echo # Generated file! > local.make
-echo # Changing a variable below and then deleting %ProjectFile% will cause >> local.make
-echo # %ProjectFile% to be regenerated with the new values. Changing the >> local.make
-echo # version requires rerunning create.bat. >> local.make
-echo. >> local.make
-echo HOTSPOTWORKSPACE=%HotSpotWorkSpace% >> local.make
-echo HOTSPOTBUILDSPACE=%HotSpotBuildSpace% >> local.make
-echo HOTSPOTJDKDIST=%HotSpotJDKDist% >> local.make
-echo ARCH=%ARCH% >> local.make
-echo BUILDARCH=%BUILDARCH% >> local.make
-echo Platform_arch=%Platform_arch% >> local.make
-echo Platform_arch_model=%Platform_arch_model% >> local.make
-
-nmake /nologo /F %HotSpotWorkSpace%/make/windows/projectfiles/common/Makefile %HotSpotBuildSpace%/%ProjectFile%
+REM It doesn't matter which variant we use here, "compiler1" is as good as any of the others - we need the common variables
+nmake /nologo /F %HotSpotWorkSpace%/make/windows/projectfiles/common/Makefile LOCAL_MAKE=%HotSpotBuildSpace%\compiler1\local.make %HotSpotBuildRoot%/%ProjectFile%
popd
goto end
:usage
-echo Usage: create HotSpotWorkSpace HotSpotBuildSpace HotSpotJDKDist
+echo Usage: create HotSpotJDKDist
echo.
-echo This is the interactive build setup script (as opposed to the batch
-echo build execution script). It creates HotSpotBuildSpace if necessary,
-echo copies the appropriate files out of HotSpotWorkSpace into it, and
+echo This is the VS build setup script (as opposed to the batch
+echo build execution script). It creates a build directory if necessary,
+echo copies the appropriate files out of the workspace into it, and
echo builds and runs ProjectCreator in it. This has the side-effect of creating
echo the %ProjectFile% file in the build space, which is then used in Visual C++.
-echo The HotSpotJDKDist defines place where JVM binaries should be placed.
+echo.
+echo The HotSpotJDKDist defines the JDK that should be used when running the JVM.
echo Environment variable FORCE_MSC_VER allows to override MSVC version autodetection.
echo.
echo NOTE that it is now NOT safe to modify any of the files in the build
diff --git a/hotspot/make/windows/create_obj_files.sh b/hotspot/make/windows/create_obj_files.sh
index 61729a8ab7c..52ae0bb785c 100644
--- a/hotspot/make/windows/create_obj_files.sh
+++ b/hotspot/make/windows/create_obj_files.sh
@@ -107,8 +107,12 @@ case "${Platform_arch_model}" in
"x86_64") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} *x86_32*" ;;
esac
+# Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE.
function findsrc {
- $FIND ${1} \( -name \*.c -o -name \*.cpp -o -name \*.s \) -a \! \( -name ${Src_Files_EXCLUDE// / -o -name } \) | sed 's/.*\/\(.*\)/\1/';
+ $FIND ${1}/. ! -name . -prune \
+ -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \
+ -a \! \( -name ${Src_Files_EXCLUDE// / -o -name } \) \
+ | sed 's/.*\/\(.*\)/\1/';
}
Src_Files=
diff --git a/hotspot/make/windows/makefiles/adlc.make b/hotspot/make/windows/makefiles/adlc.make
index b3ba4110fb7..d03e73373ea 100644
--- a/hotspot/make/windows/makefiles/adlc.make
+++ b/hotspot/make/windows/makefiles/adlc.make
@@ -22,7 +22,6 @@
#
#
-!include $(WorkSpace)/make/windows/makefiles/compile.make
# Rules for building adlc.exe
@@ -46,15 +45,7 @@ ADLCFLAGS=-q -T -D_LP64
ADLCFLAGS=-q -T -U_LP64
!endif
-CPP_FLAGS=$(CPP_FLAGS) \
- /D TARGET_OS_FAMILY_windows \
- /D TARGET_ARCH_$(Platform_arch) \
- /D TARGET_ARCH_MODEL_$(Platform_arch_model) \
- /D TARGET_OS_ARCH_windows_$(Platform_arch) \
- /D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model) \
- /D TARGET_COMPILER_visCPP
-
-CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
+ADLC_CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
CPP_INCLUDE_DIRS=\
/I "..\generated" \
@@ -92,10 +83,10 @@ GENERATED_NAMES_IN_DIR=\
$(AdlcOutDir)\dfa_$(Platform_arch_model).cpp
{$(WorkSpace)\src\share\vm\adlc}.cpp.obj::
- $(CPP) $(CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $<
+ $(CPP) $(ADLC_CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $<
{$(WorkSpace)\src\share\vm\opto}.cpp.obj::
- $(CPP) $(CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $<
+ $(CPP) $(ADLC_CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $<
adlc.exe: main.obj adlparse.obj archDesc.obj arena.obj dfa.obj dict2.obj filebuff.obj \
forms.obj formsopt.obj formssel.obj opcodes.obj output_c.obj output_h.obj
diff --git a/hotspot/make/windows/makefiles/compile.make b/hotspot/make/windows/makefiles/compile.make
index a4cfd742e9b..47d924418b2 100644
--- a/hotspot/make/windows/makefiles/compile.make
+++ b/hotspot/make/windows/makefiles/compile.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -80,6 +80,20 @@ CPP_FLAGS=$(CPP_FLAGS) /D "IA32"
CPP=ARCH_ERROR
!endif
+CPP_FLAGS=$(CPP_FLAGS) /D "WIN32" /D "_WINDOWS"
+
+# Must specify this for sharedRuntimeTrig.cpp
+CPP_FLAGS=$(CPP_FLAGS) /D "VM_LITTLE_ENDIAN"
+
+# Used for platform dispatching
+CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_FAMILY_windows
+CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_$(Platform_arch)
+CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_MODEL_$(Platform_arch_model)
+CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_windows_$(Platform_arch)
+CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model)
+CPP_FLAGS=$(CPP_FLAGS) /D TARGET_COMPILER_visCPP
+
+
# MSC_VER is a 4 digit number that tells us what compiler is being used
# and is generated when the local.make file is created by build.make
# via the script get_msc_ver.sh
diff --git a/hotspot/make/windows/makefiles/debug.make b/hotspot/make/windows/makefiles/debug.make
index fba050de5d2..32d4f46e91d 100644
--- a/hotspot/make/windows/makefiles/debug.make
+++ b/hotspot/make/windows/makefiles/debug.make
@@ -26,7 +26,6 @@ HS_INTERNAL_NAME=jvm
HS_FNAME=$(HS_INTERNAL_NAME).dll
AOUT=$(HS_FNAME)
SAWINDBG=sawindbg.dll
-LAUNCHER_NAME=hotspot.exe
GENERATED=../generated
# Allow the user to turn off precompiled headers from the command line.
@@ -34,7 +33,7 @@ GENERATED=../generated
BUILD_PCH_FILE=_build_pch_file.obj
!endif
-default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
!include ../local.make
!include compile.make
@@ -49,8 +48,10 @@ HS_BUILD_ID=$(HS_BUILD_VER)-debug
# Force resources to be rebuilt every time
$(Res_Files): FORCE
-$(AOUT): $(Res_Files) $(Obj_Files)
+vm.def: $(Obj_Files)
sh $(WorkSpace)/make/windows/build_vm_def.sh
+
+$(AOUT): $(Res_Files) $(Obj_Files) vm.def
$(LINK) @<<
$(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files)
<<
diff --git a/hotspot/make/windows/makefiles/fastdebug.make b/hotspot/make/windows/makefiles/fastdebug.make
index 053ca8cabec..b9e828b7483 100644
--- a/hotspot/make/windows/makefiles/fastdebug.make
+++ b/hotspot/make/windows/makefiles/fastdebug.make
@@ -26,7 +26,6 @@ HS_INTERNAL_NAME=jvm
HS_FNAME=$(HS_INTERNAL_NAME).dll
AOUT=$(HS_FNAME)
SAWINDBG=sawindbg.dll
-LAUNCHER_NAME=hotspot.exe
GENERATED=../generated
# Allow the user to turn off precompiled headers from the command line.
@@ -34,7 +33,7 @@ GENERATED=../generated
BUILD_PCH_FILE=_build_pch_file.obj
!endif
-default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
!include ../local.make
!include compile.make
@@ -49,8 +48,10 @@ HS_BUILD_ID=$(HS_BUILD_VER)-fastdebug
# Force resources to be rebuilt every time
$(Res_Files): FORCE
-$(AOUT): $(Res_Files) $(Obj_Files)
+vm.def: $(Obj_Files)
sh $(WorkSpace)/make/windows/build_vm_def.sh
+
+$(AOUT): $(Res_Files) $(Obj_Files) vm.def
$(LINK) @<<
$(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files)
<<
diff --git a/hotspot/make/windows/makefiles/generated.make b/hotspot/make/windows/makefiles/generated.make
index 904f12363b6..d5add4b030f 100644
--- a/hotspot/make/windows/makefiles/generated.make
+++ b/hotspot/make/windows/makefiles/generated.make
@@ -51,6 +51,7 @@ classes/ProjectCreator.class: $(ProjectCreatorSources)
!if ("$(Variant)" == "compiler2") || ("$(Variant)" == "tiered")
+!include $(WorkSpace)/make/windows/makefiles/compile.make
!include $(WorkSpace)/make/windows/makefiles/adlc.make
!endif
diff --git a/hotspot/make/windows/makefiles/launcher.make b/hotspot/make/windows/makefiles/launcher.make
index 4afdb177a52..ddee8e2139b 100644
--- a/hotspot/make/windows/makefiles/launcher.make
+++ b/hotspot/make/windows/makefiles/launcher.make
@@ -22,7 +22,8 @@
#
#
-LAUNCHER_FLAGS=$(ARCHFLAG) \
+
+LAUNCHER_FLAGS=$(CPP_FLAGS) $(ARCHFLAG) \
/D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
/D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
/D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
@@ -32,9 +33,11 @@ LAUNCHER_FLAGS=$(ARCHFLAG) \
/D _CRT_SECURE_NO_DEPRECATE \
/D LINK_INTO_LIBJVM \
/I $(WorkSpace)\src\os\windows\launcher \
- /I $(WorkSpace)\src\share\tools\launcher
-
-CPP_FLAGS=$(CPP_FLAGS) $(LAUNCHER_FLAGS)
+ /I $(WorkSpace)\src\share\tools\launcher \
+ /I $(WorkSpace)\src\share\vm\prims \
+ /I $(WorkSpace)\src\share\vm \
+ /I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \
+ /I $(WorkSpace)\src\os\windows\vm
LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console
@@ -46,22 +49,23 @@ BUFFEROVERFLOWLIB = bufferoverflowU.lib
LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB)
!endif
-LAUNCHERDIR = $(GAMMADIR)/src/os/windows/launcher
-LAUNCHERDIR_SHARE = $(GAMMADIR)/src/share/tools/launcher
+LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher
+LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher
OUTDIR = launcher
{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj:
- -mkdir $(OUTDIR)
- $(CPP) $(CPP_FLAGS) /c /Fo$@ $<
+ -mkdir $(OUTDIR) 2>NUL >NUL
+ $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $<
{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj:
- -mkdir $(OUTDIR)
- $(CPP) $(CPP_FLAGS) /c /Fo$@ $<
+ -mkdir $(OUTDIR) 2>NUL >NUL
+ $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $<
$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h
-$(LAUNCHER_NAME): $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj
- $(LINK) $(LINK_FLAGS) /out:$@ $**
+launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj
+ echo $(JAVA_HOME) > jdkpath.txt
+ $(LINK) $(LINK_FLAGS) /out:hotspot.exe $**
diff --git a/hotspot/make/windows/makefiles/product.make b/hotspot/make/windows/makefiles/product.make
index dab1e8485b4..182f1f2518c 100644
--- a/hotspot/make/windows/makefiles/product.make
+++ b/hotspot/make/windows/makefiles/product.make
@@ -25,7 +25,6 @@
HS_INTERNAL_NAME=jvm
HS_FNAME=$(HS_INTERNAL_NAME).dll
AOUT=$(HS_FNAME)
-LAUNCHER_NAME=hotspot.exe
GENERATED=../generated
# Allow the user to turn off precompiled headers from the command line.
@@ -33,7 +32,7 @@ GENERATED=../generated
BUILD_PCH_FILE=_build_pch_file.obj
!endif
-default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
!include ../local.make
!include compile.make
@@ -59,8 +58,10 @@ $(AOUT): $(Res_Files) $(Obj_Files)
$(LINK_FLAGS) /out:$@ /implib:$*.lib $(Obj_Files) $(Res_Files)
<<
!else
-$(AOUT): $(Res_Files) $(Obj_Files)
+vm.def: $(Obj_Files)
sh $(WorkSpace)/make/windows/build_vm_def.sh
+
+$(AOUT): $(Res_Files) $(Obj_Files) vm.def
$(LINK) @<<
$(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files)
<<
diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make
index 608cf804d42..1dc307f9545 100644
--- a/hotspot/make/windows/makefiles/projectcreator.make
+++ b/hotspot/make/windows/makefiles/projectcreator.make
@@ -84,11 +84,12 @@ ProjectCreatorIDEOptions=\
-buildBase $(HOTSPOTBUILDSPACE)\%f\%b \
-startAt src \
-compiler $(VcVersion) \
- -projectFileName $(HOTSPOTBUILDSPACE)\$(ProjectFile) \
+ -projectFileName $(HOTSPOTBUILDROOT)\$(ProjectFile) \
-jdkTargetRoot $(HOTSPOTJDKDIST) \
-define ALIGN_STACK_FRAMES \
-define VM_LITTLE_ENDIAN \
-prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \
+ -postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \
-ignoreFile jsig.c \
-ignoreFile jvmtiEnvRecommended.cpp \
-ignoreFile jvmtiEnvStub.cpp \
diff --git a/hotspot/make/windows/makefiles/rules.make b/hotspot/make/windows/makefiles/rules.make
index 6a6b379d95d..431ff3ecb85 100644
--- a/hotspot/make/windows/makefiles/rules.make
+++ b/hotspot/make/windows/makefiles/rules.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@ BOOT_TARGET_CLASS_VERSION=6
JAVAC_FLAGS=-g -encoding ascii
BOOTSTRAP_JAVAC_FLAGS=$(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION)
-ProjectFile=vm.vcproj
+ProjectFile=jvm.vcproj
!if "$(MSC_VER)" == "1200"
@@ -63,6 +63,11 @@ VcVersion=VC8
VcVersion=VC9
+!elseif "$(MSC_VER)" == "1600"
+
+# for compatibility - we don't yet have a ProjectCreator for VC10
+VcVersion=VC9
+
!else
VcVersion=VC7
diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make
index a91a70fc461..69ff1a7e780 100644
--- a/hotspot/make/windows/makefiles/vm.make
+++ b/hotspot/make/windows/makefiles/vm.make
@@ -71,22 +71,11 @@ CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_TARGET=\"$(BUILD_FLAVOR)\""
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\""
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\""
-CPP_FLAGS=$(CPP_FLAGS) /D "WIN32" /D "_WINDOWS" $(CPP_INCLUDE_DIRS)
-
-# Must specify this for sharedRuntimeTrig.cpp
-CPP_FLAGS=$(CPP_FLAGS) /D "VM_LITTLE_ENDIAN"
+CPP_FLAGS=$(CPP_FLAGS) $(CPP_INCLUDE_DIRS)
# Define that so jni.h is on correct side
CPP_FLAGS=$(CPP_FLAGS) /D "_JNI_IMPLEMENTATION_"
-# Used for platform dispatching
-CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_FAMILY_windows
-CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_$(Platform_arch)
-CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_MODEL_$(Platform_arch_model)
-CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_windows_$(Platform_arch)
-CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model)
-CPP_FLAGS=$(CPP_FLAGS) /D TARGET_COMPILER_visCPP
-
!if "$(BUILDARCH)" == "ia64"
STACK_SIZE="/STACK:1048576,262144"
!else
@@ -104,6 +93,8 @@ AGCT_EXPORT=/export:AsyncGetCallTrace
!endif
!endif
+# If you modify exports below please do the corresponding changes in
+# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java
LINK_FLAGS=$(LINK_FLAGS) $(STACK_SIZE) /subsystem:windows /dll /base:0x8000000 \
/export:JNI_GetDefaultJavaVMInitArgs \
/export:JNI_CreateJavaVM \
diff --git a/hotspot/make/windows/projectfiles/common/Makefile b/hotspot/make/windows/projectfiles/common/Makefile
index b1a9eceeb4e..8d55b9097f9 100644
--- a/hotspot/make/windows/projectfiles/common/Makefile
+++ b/hotspot/make/windows/projectfiles/common/Makefile
@@ -22,7 +22,10 @@
#
#
-!include local.make
+!ifdef LOCAL_MAKE
+!include $(LOCAL_MAKE)
+!endif
+
WorkSpace=$(HOTSPOTWORKSPACE)
@@ -34,11 +37,18 @@ BootStrapDir=$(BOOTDIR)
!else
!ifdef JAVA_HOME
BootStrapDir=$(JAVA_HOME)
+!else
+!ifdef HOTSPOTJDKDIST
+BootStrapDir=$(HOTSPOTJDKDIST)
+!endif
!endif
!endif
!endif
+
+
!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/projectcreator.make
+!include $(WorkSpace)/make/windows/makefiles/compile.make
# Pick up rules for building JVMTI (JSR-163)
JvmtiOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\jvmtifiles
@@ -56,6 +66,9 @@ Platform=$(HOTSPOTWORKSPACE)/make/windows/platform_$(BUILDARCH)
!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/adlc.make
!endif
+HS_INTERNAL_NAME=jvm
+!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/launcher.make
+
default:: $(AdditionalTargets) $(JvmtiGeneratedFiles)
!include $(HOTSPOTWORKSPACE)/make/hotspot_version
@@ -97,7 +110,7 @@ ProjectCreatorIDEOptions = $(ProjectCreatorIDEOptions) \
-define JRE_RELEASE_VERSION=\\\"$(JRE_RELEASE_VERSION)\\\" \
-define HOTSPOT_VM_DISTRO=\\\"$(HOTSPOT_VM_DISTRO)\\\"
-$(HOTSPOTBUILDSPACE)/$(ProjectFile): local.make $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class
+$(HOTSPOTBUILDROOT)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class
@$(RUN_JAVA) -Djava.class.path=$(HOTSPOTBUILDSPACE)/classes ProjectCreator WinGammaPlatform$(VcVersion) $(ProjectCreatorIDEOptions)
clean:
diff --git a/hotspot/make/windows/projectfiles/compiler1/Makefile b/hotspot/make/windows/projectfiles/compiler1/Makefile
index 83c3897f735..183a27647dd 100644
--- a/hotspot/make/windows/projectfiles/compiler1/Makefile
+++ b/hotspot/make/windows/projectfiles/compiler1/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,6 @@
#
#
-Variant=compiler1
-!include local.make
+!include ../local.make
!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile
diff --git a/hotspot/make/windows/projectfiles/compiler1/vm.def b/hotspot/make/windows/projectfiles/compiler1/vm.def
index 7811a1fc9bb..b450e81fd01 100644
--- a/hotspot/make/windows/projectfiles/compiler1/vm.def
+++ b/hotspot/make/windows/projectfiles/compiler1/vm.def
@@ -2,6 +2,6 @@
; This .DEF file is a placeholder for one which is automatically
; generated during the build process. See
; make\windows\build_vm_def.sh and
-; make\windows\makefiles\makedeps.make (esp. the "-prelink"
+; make\windows\makefiles\projectcreator.make (esp. the "-prelink"
; options).
;
diff --git a/hotspot/make/windows/projectfiles/compiler2/Makefile b/hotspot/make/windows/projectfiles/compiler2/Makefile
index 1380b489487..1df97d232a8 100644
--- a/hotspot/make/windows/projectfiles/compiler2/Makefile
+++ b/hotspot/make/windows/projectfiles/compiler2/Makefile
@@ -22,8 +22,7 @@
#
#
-Variant=compiler2
-!include local.make
+!include ../local.make
AdlcOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\adfiles
AdditionalTargets=$(AdlcOutDir)\ad_$(Platform_arch_model).cpp $(AdlcOutDir)\dfa_$(Platform_arch_model).cpp
diff --git a/hotspot/make/windows/projectfiles/compiler2/vm.def b/hotspot/make/windows/projectfiles/compiler2/vm.def
index 7811a1fc9bb..b450e81fd01 100644
--- a/hotspot/make/windows/projectfiles/compiler2/vm.def
+++ b/hotspot/make/windows/projectfiles/compiler2/vm.def
@@ -2,6 +2,6 @@
; This .DEF file is a placeholder for one which is automatically
; generated during the build process. See
; make\windows\build_vm_def.sh and
-; make\windows\makefiles\makedeps.make (esp. the "-prelink"
+; make\windows\makefiles\projectcreator.make (esp. the "-prelink"
; options).
;
diff --git a/hotspot/make/windows/projectfiles/core/Makefile b/hotspot/make/windows/projectfiles/core/Makefile
index 27ea55ff1a2..5b23a8467cb 100644
--- a/hotspot/make/windows/projectfiles/core/Makefile
+++ b/hotspot/make/windows/projectfiles/core/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,6 @@
#
#
-Variant=core
-!include local.make
+!include ../local.make
!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile
diff --git a/hotspot/make/windows/projectfiles/core/vm.def b/hotspot/make/windows/projectfiles/core/vm.def
index 7811a1fc9bb..b450e81fd01 100644
--- a/hotspot/make/windows/projectfiles/core/vm.def
+++ b/hotspot/make/windows/projectfiles/core/vm.def
@@ -2,6 +2,6 @@
; This .DEF file is a placeholder for one which is automatically
; generated during the build process. See
; make\windows\build_vm_def.sh and
-; make\windows\makefiles\makedeps.make (esp. the "-prelink"
+; make\windows\makefiles\projectcreator.make (esp. the "-prelink"
; options).
;
diff --git a/hotspot/make/windows/projectfiles/kernel/Makefile b/hotspot/make/windows/projectfiles/kernel/Makefile
index ae89a2e77c6..bb231fca6c8 100644
--- a/hotspot/make/windows/projectfiles/kernel/Makefile
+++ b/hotspot/make/windows/projectfiles/kernel/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2010 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,6 @@
#
#
-Variant=kernel
-!include local.make
+!include ../local.make
!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile
diff --git a/hotspot/make/windows/projectfiles/kernel/vm.def b/hotspot/make/windows/projectfiles/kernel/vm.def
index 7811a1fc9bb..b450e81fd01 100644
--- a/hotspot/make/windows/projectfiles/kernel/vm.def
+++ b/hotspot/make/windows/projectfiles/kernel/vm.def
@@ -2,6 +2,6 @@
; This .DEF file is a placeholder for one which is automatically
; generated during the build process. See
; make\windows\build_vm_def.sh and
-; make\windows\makefiles\makedeps.make (esp. the "-prelink"
+; make\windows\makefiles\projectcreator.make (esp. the "-prelink"
; options).
;
diff --git a/hotspot/make/windows/projectfiles/tiered/Makefile b/hotspot/make/windows/projectfiles/tiered/Makefile
index e2a8c97c98e..5398cb99d46 100644
--- a/hotspot/make/windows/projectfiles/tiered/Makefile
+++ b/hotspot/make/windows/projectfiles/tiered/Makefile
@@ -22,8 +22,7 @@
#
#
-Variant=tiered
-!include local.make
+!include ../local.make
AdlcOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\adfiles
AdditionalTargets=$(AdlcOutDir)\ad_$(Platform_arch_model).cpp $(AdlcOutDir)\dfa_$(Platform_arch_model).cpp
diff --git a/hotspot/make/windows/projectfiles/tiered/vm.def b/hotspot/make/windows/projectfiles/tiered/vm.def
index 7811a1fc9bb..b450e81fd01 100644
--- a/hotspot/make/windows/projectfiles/tiered/vm.def
+++ b/hotspot/make/windows/projectfiles/tiered/vm.def
@@ -2,6 +2,6 @@
; This .DEF file is a placeholder for one which is automatically
; generated during the build process. See
; make\windows\build_vm_def.sh and
-; make\windows\makefiles\makedeps.make (esp. the "-prelink"
+; make\windows\makefiles\projectcreator.make (esp. the "-prelink"
; options).
;
diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp
index 901931fb79f..8512afcba95 100644
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp
@@ -909,10 +909,10 @@ void MacroAssembler::verify_thread() {
#if defined(COMPILER2) && !defined(_LP64)
// Save & restore possible 64-bit Long arguments in G-regs
sllx(L0,32,G2); // Move old high G1 bits high in G2
- sllx(G1, 0,G1); // Clear current high G1 bits
+ srl(G1, 0,G1); // Clear current high G1 bits
or3 (G1,G2,G1); // Recover 64-bit G1
sllx(L6,32,G2); // Move old high G4 bits high in G2
- sllx(G4, 0,G4); // Clear current high G4 bits
+ srl(G4, 0,G4); // Clear current high G4 bits
or3 (G4,G2,G4); // Recover 64-bit G4
#endif
restore(O0, 0, G2_thread);
@@ -1443,6 +1443,45 @@ void MacroAssembler::set64(jlong value, Register d, Register tmp) {
}
}
+int MacroAssembler::size_of_set64(jlong value) {
+ v9_dep();
+
+ int hi = (int)(value >> 32);
+ int lo = (int)(value & ~0);
+ int count = 0;
+
+ // (Matcher::isSimpleConstant64 knows about the following optimizations.)
+ if (Assembler::is_simm13(lo) && value == lo) {
+ count++;
+ } else if (hi == 0) {
+ count++;
+ if (low10(lo) != 0)
+ count++;
+ }
+ else if (hi == -1) {
+ count += 2;
+ }
+ else if (lo == 0) {
+ if (Assembler::is_simm13(hi)) {
+ count++;
+ } else {
+ count++;
+ if (low10(hi) != 0)
+ count++;
+ }
+ count++;
+ }
+ else {
+ count += 2;
+ if (low10(hi) != 0)
+ count++;
+ if (low10(lo) != 0)
+ count++;
+ count += 2;
+ }
+ return count;
+}
+
// compute size in bytes of sparc frame, given
// number of extraWords
int MacroAssembler::total_frame_size_in_bytes(int extraWords) {
diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
index f6ff1bde4e0..ae4357edd76 100644
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
@@ -1621,6 +1621,10 @@ public:
void sub( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); }
void sub( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
+
+ // Note: offset is added to s2.
+ inline void sub(Register s1, RegisterOrConstant s2, Register d, int offset = 0);
+
void subcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); }
void subcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
void subc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); }
@@ -1798,6 +1802,7 @@ class MacroAssembler: public Assembler {
// branches that use right instruction for v8 vs. v9
inline void br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none );
inline void br( Condition c, bool a, Predict p, Label& L );
+
inline void fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none );
inline void fb( Condition c, bool a, Predict p, Label& L );
@@ -1894,6 +1899,9 @@ public:
void patchable_set(intptr_t value, Register d);
void set64(jlong value, Register d, Register tmp);
+ // Compute size of set64.
+ static int size_of_set64(jlong value);
+
// sign-extend 32 to 64
inline void signx( Register s, Register d ) { sra( s, G0, d); }
inline void signx( Register d ) { sra( d, G0, d); }
diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp
index 4dfeb191d1b..106aa14e5b0 100644
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp
@@ -328,6 +328,11 @@ inline void Assembler::stcsr( int crd, Register s1, int simm13a) { v8_only();
inline void Assembler::stdcq( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); }
inline void Assembler::stdcq( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
+inline void Assembler::sub(Register s1, RegisterOrConstant s2, Register d, int offset) {
+ if (s2.is_register()) sub(s1, s2.as_register(), d);
+ else { sub(s1, s2.as_constant() + offset, d); offset = 0; }
+ if (offset != 0) sub(d, offset, d);
+}
// pp 231
diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp
index f3149d7426e..ee5f6afb5de 100644
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp
@@ -434,7 +434,7 @@ void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
Register pre_val_reg = pre_val()->as_register();
- ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false);
+ ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
if (__ is_in_wdisp16_range(_continuation)) {
__ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt,
pre_val_reg, _continuation);
diff --git a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp
index 05e034096b4..2304c2d0103 100644
--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp
@@ -155,4 +155,7 @@
static bool is_caller_save_register (LIR_Opr reg);
static bool is_caller_save_register (Register r);
+ static int nof_caller_save_cpu_regs() { return pd_nof_caller_save_cpu_regs_frame_map; }
+ static int last_cpu_reg() { return pd_last_cpu_reg; }
+
#endif // CPU_SPARC_VM_C1_FRAMEMAP_SPARC_HPP
diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
index b1e2a2b464f..1e02e0a68fd 100644
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
@@ -100,6 +100,11 @@ bool LIR_Assembler::is_single_instruction(LIR_Op* op) {
return false;
}
+ if (UseCompressedOops) {
+ if (dst->is_address() && !dst->is_stack() && (dst->type() == T_OBJECT || dst->type() == T_ARRAY)) return false;
+ if (src->is_address() && !src->is_stack() && (src->type() == T_OBJECT || src->type() == T_ARRAY)) return false;
+ }
+
if (dst->is_register()) {
if (src->is_address() && Assembler::is_simm13(src->as_address_ptr()->disp())) {
return !PatchALot;
@@ -253,7 +258,7 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
int count_offset = java_lang_String:: count_offset_in_bytes();
- __ ld_ptr(str0, value_offset, tmp0);
+ __ load_heap_oop(str0, value_offset, tmp0);
__ ld(str0, offset_offset, tmp2);
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
__ ld(str0, count_offset, str0);
@@ -262,7 +267,7 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
// str1 may be null
add_debug_info_for_null_check_here(info);
- __ ld_ptr(str1, value_offset, tmp1);
+ __ load_heap_oop(str1, value_offset, tmp1);
__ add(tmp0, tmp2, tmp0);
__ ld(str1, offset_offset, tmp2);
@@ -766,7 +771,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
add_debug_info_for_null_check_here(op->info());
- __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch);
+ __ load_klass(O0, G3_scratch);
if (__ is_simm13(op->vtable_offset())) {
__ ld_ptr(G3_scratch, op->vtable_offset(), G5_method);
} else {
@@ -780,138 +785,17 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
// the peephole pass fills the delay slot
}
-
-// load with 32-bit displacement
-int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) {
- int load_offset = code_offset();
- if (Assembler::is_simm13(disp)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- switch(ld_type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ ldsb(s, disp, d); break;
- case T_CHAR : __ lduh(s, disp, d); break;
- case T_SHORT : __ ldsh(s, disp, d); break;
- case T_INT : __ ld(s, disp, d); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(s, disp, d); break;
- default : ShouldNotReachHere();
- }
- } else {
- __ set(disp, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- load_offset = code_offset();
- switch(ld_type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ ldsb(s, O7, d); break;
- case T_CHAR : __ lduh(s, O7, d); break;
- case T_SHORT : __ ldsh(s, O7, d); break;
- case T_INT : __ ld(s, O7, d); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(s, O7, d); break;
- default : ShouldNotReachHere();
- }
- }
- if (ld_type == T_ARRAY || ld_type == T_OBJECT) __ verify_oop(d);
- return load_offset;
-}
-
-
-// store with 32-bit displacement
-void LIR_Assembler::store(Register value, Register base, int offset, BasicType type, CodeEmitInfo *info) {
- if (Assembler::is_simm13(offset)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- switch (type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ stb(value, base, offset); break;
- case T_CHAR : __ sth(value, base, offset); break;
- case T_SHORT : __ sth(value, base, offset); break;
- case T_INT : __ stw(value, base, offset); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : // fall through
- case T_OBJECT: __ st_ptr(value, base, offset); break;
- default : ShouldNotReachHere();
- }
- } else {
- __ set(offset, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- switch (type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ stb(value, base, O7); break;
- case T_CHAR : __ sth(value, base, O7); break;
- case T_SHORT : __ sth(value, base, O7); break;
- case T_INT : __ stw(value, base, O7); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : //fall through
- case T_OBJECT: __ st_ptr(value, base, O7); break;
- default : ShouldNotReachHere();
- }
- }
- // Note: Do the store before verification as the code might be patched!
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(value);
-}
-
-
-// load float with 32-bit displacement
-void LIR_Assembler::load(Register s, int disp, FloatRegister d, BasicType ld_type, CodeEmitInfo *info) {
- FloatRegisterImpl::Width w;
- switch(ld_type) {
- case T_FLOAT : w = FloatRegisterImpl::S; break;
- case T_DOUBLE: w = FloatRegisterImpl::D; break;
- default : ShouldNotReachHere();
- }
-
- if (Assembler::is_simm13(disp)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- if (disp % BytesPerLong != 0 && w == FloatRegisterImpl::D) {
- __ ldf(FloatRegisterImpl::S, s, disp + BytesPerWord, d->successor());
- __ ldf(FloatRegisterImpl::S, s, disp , d);
- } else {
- __ ldf(w, s, disp, d);
- }
- } else {
- __ set(disp, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- __ ldf(w, s, O7, d);
- }
-}
-
-
-// store float with 32-bit displacement
-void LIR_Assembler::store(FloatRegister value, Register base, int offset, BasicType type, CodeEmitInfo *info) {
- FloatRegisterImpl::Width w;
- switch(type) {
- case T_FLOAT : w = FloatRegisterImpl::S; break;
- case T_DOUBLE: w = FloatRegisterImpl::D; break;
- default : ShouldNotReachHere();
- }
-
- if (Assembler::is_simm13(offset)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- if (w == FloatRegisterImpl::D && offset % BytesPerLong != 0) {
- __ stf(FloatRegisterImpl::S, value->successor(), base, offset + BytesPerWord);
- __ stf(FloatRegisterImpl::S, value , base, offset);
- } else {
- __ stf(w, value, base, offset);
- }
- } else {
- __ set(offset, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- __ stf(w, value, O7, base);
- }
-}
-
-
-int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool unaligned) {
+int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned) {
int store_offset;
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
assert(!unaligned, "can't handle this");
// for offsets larger than a simm13 we setup the offset in O7
__ set(offset, O7);
- store_offset = store(from_reg, base, O7, type);
+ store_offset = store(from_reg, base, O7, type, wide);
} else {
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(from_reg->as_register());
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(from_reg->as_register());
+ }
store_offset = code_offset();
switch (type) {
case T_BOOLEAN: // fall through
@@ -934,9 +818,22 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType
__ stw(from_reg->as_register_hi(), base, offset + hi_word_offset_in_bytes);
#endif
break;
- case T_ADDRESS:// fall through
+ case T_ADDRESS:
+ __ st_ptr(from_reg->as_register(), base, offset);
+ break;
case T_ARRAY : // fall through
- case T_OBJECT: __ st_ptr(from_reg->as_register(), base, offset); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ encode_heap_oop(from_reg->as_register(), G3_scratch);
+ store_offset = code_offset();
+ __ stw(G3_scratch, base, offset);
+ } else {
+ __ st_ptr(from_reg->as_register(), base, offset);
+ }
+ break;
+ }
+
case T_FLOAT : __ stf(FloatRegisterImpl::S, from_reg->as_float_reg(), base, offset); break;
case T_DOUBLE:
{
@@ -958,8 +855,10 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType
}
-int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicType type) {
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(from_reg->as_register());
+int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicType type, bool wide) {
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(from_reg->as_register());
+ }
int store_offset = code_offset();
switch (type) {
case T_BOOLEAN: // fall through
@@ -975,9 +874,21 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicTy
__ std(from_reg->as_register_hi(), base, disp);
#endif
break;
- case T_ADDRESS:// fall through
+ case T_ADDRESS:
+ __ st_ptr(from_reg->as_register(), base, disp);
+ break;
case T_ARRAY : // fall through
- case T_OBJECT: __ st_ptr(from_reg->as_register(), base, disp); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ encode_heap_oop(from_reg->as_register(), G3_scratch);
+ store_offset = code_offset();
+ __ stw(G3_scratch, base, disp);
+ } else {
+ __ st_ptr(from_reg->as_register(), base, disp);
+ }
+ break;
+ }
case T_FLOAT : __ stf(FloatRegisterImpl::S, from_reg->as_float_reg(), base, disp); break;
case T_DOUBLE: __ stf(FloatRegisterImpl::D, from_reg->as_double_reg(), base, disp); break;
default : ShouldNotReachHere();
@@ -986,14 +897,14 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicTy
}
-int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool unaligned) {
+int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool wide, bool unaligned) {
int load_offset;
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
assert(base != O7, "destroying register");
assert(!unaligned, "can't handle this");
// for offsets larger than a simm13 we setup the offset in O7
__ set(offset, O7);
- load_offset = load(base, O7, to_reg, type);
+ load_offset = load(base, O7, to_reg, type, wide);
} else {
load_offset = code_offset();
switch(type) {
@@ -1030,9 +941,18 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
#endif
}
break;
- case T_ADDRESS:// fall through
+ case T_ADDRESS: __ ld_ptr(base, offset, to_reg->as_register()); break;
case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(base, offset, to_reg->as_register()); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ lduw(base, offset, to_reg->as_register());
+ __ decode_heap_oop(to_reg->as_register());
+ } else {
+ __ ld_ptr(base, offset, to_reg->as_register());
+ }
+ break;
+ }
case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, offset, to_reg->as_float_reg()); break;
case T_DOUBLE:
{
@@ -1048,23 +968,34 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
}
default : ShouldNotReachHere();
}
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(to_reg->as_register());
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(to_reg->as_register());
+ }
}
return load_offset;
}
-int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType type) {
+int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType type, bool wide) {
int load_offset = code_offset();
switch(type) {
case T_BOOLEAN: // fall through
- case T_BYTE : __ ldsb(base, disp, to_reg->as_register()); break;
- case T_CHAR : __ lduh(base, disp, to_reg->as_register()); break;
- case T_SHORT : __ ldsh(base, disp, to_reg->as_register()); break;
- case T_INT : __ ld(base, disp, to_reg->as_register()); break;
- case T_ADDRESS:// fall through
+ case T_BYTE : __ ldsb(base, disp, to_reg->as_register()); break;
+ case T_CHAR : __ lduh(base, disp, to_reg->as_register()); break;
+ case T_SHORT : __ ldsh(base, disp, to_reg->as_register()); break;
+ case T_INT : __ ld(base, disp, to_reg->as_register()); break;
+ case T_ADDRESS: __ ld_ptr(base, disp, to_reg->as_register()); break;
case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(base, disp, to_reg->as_register()); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ lduw(base, disp, to_reg->as_register());
+ __ decode_heap_oop(to_reg->as_register());
+ } else {
+ __ ld_ptr(base, disp, to_reg->as_register());
+ }
+ break;
+ }
case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, disp, to_reg->as_float_reg()); break;
case T_DOUBLE: __ ldf(FloatRegisterImpl::D, base, disp, to_reg->as_double_reg()); break;
case T_LONG :
@@ -1078,61 +1009,17 @@ int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType
break;
default : ShouldNotReachHere();
}
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(to_reg->as_register());
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(to_reg->as_register());
+ }
return load_offset;
}
-
-// load/store with an Address
-void LIR_Assembler::load(const Address& a, Register d, BasicType ld_type, CodeEmitInfo *info, int offset) {
- load(a.base(), a.disp() + offset, d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(Register value, const Address& dest, BasicType type, CodeEmitInfo *info, int offset) {
- store(value, dest.base(), dest.disp() + offset, type, info);
-}
-
-
-// loadf/storef with an Address
-void LIR_Assembler::load(const Address& a, FloatRegister d, BasicType ld_type, CodeEmitInfo *info, int offset) {
- load(a.base(), a.disp() + offset, d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(FloatRegister value, const Address& dest, BasicType type, CodeEmitInfo *info, int offset) {
- store(value, dest.base(), dest.disp() + offset, type, info);
-}
-
-
-// load/store with an Address
-void LIR_Assembler::load(LIR_Address* a, Register d, BasicType ld_type, CodeEmitInfo *info) {
- load(as_Address(a), d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(Register value, LIR_Address* dest, BasicType type, CodeEmitInfo *info) {
- store(value, as_Address(dest), type, info);
-}
-
-
-// loadf/storef with an Address
-void LIR_Assembler::load(LIR_Address* a, FloatRegister d, BasicType ld_type, CodeEmitInfo *info) {
- load(as_Address(a), d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(FloatRegister value, LIR_Address* dest, BasicType type, CodeEmitInfo *info) {
- store(value, as_Address(dest), type, info);
-}
-
-
void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) {
LIR_Const* c = src->as_constant_ptr();
switch (c->type()) {
case T_INT:
- case T_FLOAT:
- case T_ADDRESS: {
+ case T_FLOAT: {
Register src_reg = O7;
int value = c->as_jint_bits();
if (value == 0) {
@@ -1144,6 +1031,18 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) {
__ stw(src_reg, addr.base(), addr.disp());
break;
}
+ case T_ADDRESS: {
+ Register src_reg = O7;
+ int value = c->as_jint_bits();
+ if (value == 0) {
+ src_reg = G0;
+ } else {
+ __ set(value, O7);
+ }
+ Address addr = frame_map()->address_for_slot(dest->single_stack_ix());
+ __ st_ptr(src_reg, addr.base(), addr.disp());
+ break;
+ }
case T_OBJECT: {
Register src_reg = O7;
jobject2reg(c->as_jobject(), src_reg);
@@ -1178,14 +1077,12 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) {
}
-void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info ) {
+void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) {
LIR_Const* c = src->as_constant_ptr();
LIR_Address* addr = dest->as_address_ptr();
Register base = addr->base()->as_pointer_register();
+ int offset = -1;
- if (info != NULL) {
- add_debug_info_for_null_check_here(info);
- }
switch (c->type()) {
case T_INT:
case T_FLOAT:
@@ -1199,10 +1096,10 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi
}
if (addr->index()->is_valid()) {
assert(addr->disp() == 0, "must be zero");
- store(tmp, base, addr->index()->as_pointer_register(), type);
+ offset = store(tmp, base, addr->index()->as_pointer_register(), type, wide);
} else {
assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses");
- store(tmp, base, addr->disp(), type);
+ offset = store(tmp, base, addr->disp(), type, wide, false);
}
break;
}
@@ -1212,21 +1109,21 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi
assert(Assembler::is_simm13(addr->disp()) &&
Assembler::is_simm13(addr->disp() + 4), "can't handle larger addresses");
- Register tmp = O7;
+ LIR_Opr tmp = FrameMap::O7_opr;
int value_lo = c->as_jint_lo_bits();
if (value_lo == 0) {
- tmp = G0;
+ tmp = FrameMap::G0_opr;
} else {
__ set(value_lo, O7);
}
- store(tmp, base, addr->disp() + lo_word_offset_in_bytes, T_INT);
+ offset = store(tmp, base, addr->disp() + lo_word_offset_in_bytes, T_INT, wide, false);
int value_hi = c->as_jint_hi_bits();
if (value_hi == 0) {
- tmp = G0;
+ tmp = FrameMap::G0_opr;
} else {
__ set(value_hi, O7);
}
- store(tmp, base, addr->disp() + hi_word_offset_in_bytes, T_INT);
+ offset = store(tmp, base, addr->disp() + hi_word_offset_in_bytes, T_INT, wide, false);
break;
}
case T_OBJECT: {
@@ -1241,10 +1138,10 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi
// handle either reg+reg or reg+disp address
if (addr->index()->is_valid()) {
assert(addr->disp() == 0, "must be zero");
- store(tmp, base, addr->index()->as_pointer_register(), type);
+ offset = store(tmp, base, addr->index()->as_pointer_register(), type, wide);
} else {
assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses");
- store(tmp, base, addr->disp(), type);
+ offset = store(tmp, base, addr->disp(), type, wide, false);
}
break;
@@ -1252,6 +1149,10 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi
default:
Unimplemented();
}
+ if (info != NULL) {
+ assert(offset != -1, "offset should've been set");
+ add_debug_info_for_null_check(offset, info);
+ }
}
@@ -1336,7 +1237,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
assert(to_reg->is_single_cpu(), "Must be a cpu register.");
__ set(const_addrlit, O7);
- load(O7, 0, to_reg->as_register(), T_INT);
+ __ ld(O7, 0, to_reg->as_register());
}
}
break;
@@ -1429,7 +1330,7 @@ Address LIR_Assembler::as_Address_lo(LIR_Address* addr) {
void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type,
- LIR_PatchCode patch_code, CodeEmitInfo* info, bool unaligned) {
+ LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool unaligned) {
LIR_Address* addr = src_opr->as_address_ptr();
LIR_Opr to_reg = dest;
@@ -1475,16 +1376,15 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type,
assert(disp_reg != noreg || Assembler::is_simm13(disp_value), "should have set this up");
if (disp_reg == noreg) {
- offset = load(src, disp_value, to_reg, type, unaligned);
+ offset = load(src, disp_value, to_reg, type, wide, unaligned);
} else {
assert(!unaligned, "can't handle this");
- offset = load(src, disp_reg, to_reg, type);
+ offset = load(src, disp_reg, to_reg, type, wide);
}
if (patch != NULL) {
patching_epilog(patch, patch_code, src, info);
}
-
if (info != NULL) add_debug_info_for_null_check(offset, info);
}
@@ -1518,7 +1418,7 @@ void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) {
}
bool unaligned = (addr.disp() - STACK_BIAS) % 8 != 0;
- load(addr.base(), addr.disp(), dest, dest->type(), unaligned);
+ load(addr.base(), addr.disp(), dest, dest->type(), true /*wide*/, unaligned);
}
@@ -1530,7 +1430,7 @@ void LIR_Assembler::reg2stack(LIR_Opr from_reg, LIR_Opr dest, BasicType type, bo
addr = frame_map()->address_for_slot(dest->double_stack_ix());
}
bool unaligned = (addr.disp() - STACK_BIAS) % 8 != 0;
- store(from_reg, addr.base(), addr.disp(), from_reg->type(), unaligned);
+ store(from_reg, addr.base(), addr.disp(), from_reg->type(), true /*wide*/, unaligned);
}
@@ -1578,7 +1478,7 @@ void LIR_Assembler::reg2reg(LIR_Opr from_reg, LIR_Opr to_reg) {
void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack,
- bool unaligned) {
+ bool wide, bool unaligned) {
LIR_Address* addr = dest->as_address_ptr();
Register src = addr->base()->as_pointer_register();
@@ -1622,10 +1522,10 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
assert(disp_reg != noreg || Assembler::is_simm13(disp_value), "should have set this up");
if (disp_reg == noreg) {
- offset = store(from_reg, src, disp_value, type, unaligned);
+ offset = store(from_reg, src, disp_value, type, wide, unaligned);
} else {
assert(!unaligned, "can't handle this");
- offset = store(from_reg, src, disp_reg, type);
+ offset = store(from_reg, src, disp_reg, type, wide);
}
if (patch != NULL) {
@@ -2184,13 +2084,13 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
// make sure src and dst are non-null and load array length
if (flags & LIR_OpArrayCopy::src_null_check) {
__ tst(src);
- __ br(Assembler::equal, false, Assembler::pn, *stub->entry());
+ __ brx(Assembler::equal, false, Assembler::pn, *stub->entry());
__ delayed()->nop();
}
if (flags & LIR_OpArrayCopy::dst_null_check) {
__ tst(dst);
- __ br(Assembler::equal, false, Assembler::pn, *stub->entry());
+ __ brx(Assembler::equal, false, Assembler::pn, *stub->entry());
__ delayed()->nop();
}
@@ -2232,10 +2132,18 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
}
if (flags & LIR_OpArrayCopy::type_check) {
- __ ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp);
- __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
- __ cmp(tmp, tmp2);
- __ br(Assembler::notEqual, false, Assembler::pt, *stub->entry());
+ if (UseCompressedOops) {
+ // We don't need decode because we just need to compare
+ __ lduw(src, oopDesc::klass_offset_in_bytes(), tmp);
+ __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::notEqual, false, Assembler::pt, *stub->entry());
+ } else {
+ __ ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp);
+ __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::notEqual, false, Assembler::pt, *stub->entry());
+ }
__ delayed()->nop();
}
@@ -2250,20 +2158,44 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
// but not necessarily exactly of type default_type.
Label known_ok, halt;
jobject2reg(op->expected_type()->constant_encoding(), tmp);
- __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
- if (basic_type != T_OBJECT) {
- __ cmp(tmp, tmp2);
- __ br(Assembler::notEqual, false, Assembler::pn, halt);
- __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp2);
- __ cmp(tmp, tmp2);
- __ br(Assembler::equal, false, Assembler::pn, known_ok);
- __ delayed()->nop();
+ if (UseCompressedOops) {
+ // tmp holds the default type. It currently comes uncompressed after the
+ // load of a constant, so encode it.
+ __ encode_heap_oop(tmp);
+ // load the raw value of the dst klass, since we will be comparing
+ // uncompressed values directly.
+ __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ if (basic_type != T_OBJECT) {
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::notEqual, false, Assembler::pn, halt);
+ // load the raw value of the src klass.
+ __ delayed()->lduw(src, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ } else {
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->cmp(src, dst);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ }
} else {
- __ cmp(tmp, tmp2);
- __ br(Assembler::equal, false, Assembler::pn, known_ok);
- __ delayed()->cmp(src, dst);
- __ br(Assembler::equal, false, Assembler::pn, known_ok);
- __ delayed()->nop();
+ __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ if (basic_type != T_OBJECT) {
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::notEqual, false, Assembler::pn, halt);
+ __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ } else {
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->cmp(src, dst);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ }
}
__ bind(halt);
__ stop("incorrect type information in arraycopy");
@@ -2471,7 +2403,7 @@ void LIR_Assembler::type_profile_helper(Register mdo, int mdo_offset_bias,
Label next_test;
Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)) -
mdo_offset_bias);
- load(recv_addr, tmp1, T_OBJECT);
+ __ ld_ptr(recv_addr, tmp1);
__ br_notnull(tmp1, false, Assembler::pt, next_test);
__ delayed()->nop();
__ st_ptr(recv, recv_addr);
@@ -2487,11 +2419,8 @@ void LIR_Assembler::type_profile_helper(Register mdo, int mdo_offset_bias,
void LIR_Assembler::setup_md_access(ciMethod* method, int bci,
ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) {
- md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
data = md->bci_to_data(bci);
assert(data != NULL, "need data for checkcast");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -2563,7 +2492,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
// get object class
// not a safepoint as obj null check happens earlier
- load(obj, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL);
+ __ load_klass(obj, klass_RInfo);
if (op->fast_check()) {
assert_different_registers(klass_RInfo, k_RInfo);
__ cmp(k_RInfo, klass_RInfo);
@@ -2605,7 +2534,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
__ set(mdo_offset_bias, tmp1);
__ add(mdo, tmp1, mdo);
}
- load(Address(obj, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
+ __ load_klass(obj, recv);
type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, success);
// Jump over the failure case
__ ba(false, *success);
@@ -2674,11 +2603,12 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
__ br_null(value, false, Assembler::pn, done);
__ delayed()->nop();
}
- load(array, oopDesc::klass_offset_in_bytes(), k_RInfo, T_OBJECT, op->info_for_exception());
- load(value, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL);
+ add_debug_info_for_null_check_here(op->info_for_exception());
+ __ load_klass(array, k_RInfo);
+ __ load_klass(value, klass_RInfo);
// get instance klass
- load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL);
+ __ ld_ptr(Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)), k_RInfo);
// perform the fast part of the checking logic
__ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, success_target, failure_target, NULL);
@@ -2700,7 +2630,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
__ set(mdo_offset_bias, tmp1);
__ add(mdo, tmp1, mdo);
}
- load(Address(value, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
+ __ load_klass(value, recv);
type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &done);
__ ba(false, done);
__ delayed()->nop();
@@ -2781,14 +2711,17 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
Register t2 = op->tmp2()->as_register();
__ mov(cmp_value, t1);
__ mov(new_value, t2);
-#ifdef _LP64
if (op->code() == lir_cas_obj) {
- __ casx(addr, t1, t2);
- } else
-#endif
- {
+ if (UseCompressedOops) {
+ __ encode_heap_oop(t1);
+ __ encode_heap_oop(t2);
__ cas(addr, t1, t2);
+ } else {
+ __ cas_ptr(addr, t1, t2);
}
+ } else {
+ __ cas(addr, t1, t2);
+ }
__ cmp(t1, t2);
} else {
Unimplemented();
@@ -2885,11 +2818,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
int bci = op->profiled_bci();
// Update counter for all call types
- ciMethodData* md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
assert(data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
@@ -2966,7 +2896,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
}
}
} else {
- load(Address(recv, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
+ __ load_klass(recv, recv);
Label update_done;
type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &update_done);
// Receiver did not match any saved receiver and there is no empty row for it.
@@ -3160,7 +3090,7 @@ void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type,
} else {
// use normal move for all other volatiles since they don't need
// special handling to remain atomic.
- move_op(src, dest, type, lir_patch_none, info, false, false);
+ move_op(src, dest, type, lir_patch_none, info, false, false, false);
}
}
diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp
index ffcd5b494e9..386159c89b8 100644
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp
@@ -40,33 +40,11 @@
// and then a load or store is emitted with ([O7] + [d]).
//
- // some load/store variants return the code_offset for proper positioning of debug info for null checks
+ int store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned);
+ int store(LIR_Opr from_reg, Register base, Register disp, BasicType type, bool wide);
- // load/store with 32 bit displacement
- int load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(Register value, Register base, int offset, BasicType type, CodeEmitInfo *info = NULL);
-
- // loadf/storef with 32 bit displacement
- void load(Register s, int disp, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(FloatRegister d, Register s1, int disp, BasicType st_type, CodeEmitInfo* info = NULL);
-
- // convienence methods for calling load/store with an Address
- void load(const Address& a, Register d, BasicType ld_type, CodeEmitInfo* info = NULL, int offset = 0);
- void store(Register d, const Address& a, BasicType st_type, CodeEmitInfo* info = NULL, int offset = 0);
- void load(const Address& a, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL, int offset = 0);
- void store(FloatRegister d, const Address& a, BasicType st_type, CodeEmitInfo* info = NULL, int offset = 0);
-
- // convienence methods for calling load/store with an LIR_Address
- void load(LIR_Address* a, Register d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(Register d, LIR_Address* a, BasicType st_type, CodeEmitInfo* info = NULL);
- void load(LIR_Address* a, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(FloatRegister d, LIR_Address* a, BasicType st_type, CodeEmitInfo* info = NULL);
-
- int store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool unaligned = false);
- int store(LIR_Opr from_reg, Register base, Register disp, BasicType type);
-
- int load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool unaligned = false);
- int load(Register base, Register disp, LIR_Opr to_reg, BasicType type);
+ int load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool wide, bool unaligned);
+ int load(Register base, Register disp, LIR_Opr to_reg, BasicType type, bool wide);
void monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no);
diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp
index 6d9f9de5286..6340156f779 100644
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp
@@ -40,7 +40,7 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
const Register temp_reg = G3_scratch;
// Note: needs more testing of out-of-line vs. inline slow case
verify_oop(receiver);
- ld_ptr(receiver, oopDesc::klass_offset_in_bytes(), temp_reg);
+ load_klass(receiver, temp_reg);
cmp(temp_reg, iCache);
brx(Assembler::equal, true, Assembler::pt, L);
delayed()->nop();
@@ -185,9 +185,19 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
} else {
set((intx)markOopDesc::prototype(), t1);
}
- st_ptr(t1 , obj, oopDesc::mark_offset_in_bytes ());
- st_ptr(klass, obj, oopDesc::klass_offset_in_bytes ());
- if (len->is_valid()) st(len , obj, arrayOopDesc::length_offset_in_bytes());
+ st_ptr(t1, obj, oopDesc::mark_offset_in_bytes());
+ if (UseCompressedOops) {
+ // Save klass
+ mov(klass, t1);
+ encode_heap_oop_not_null(t1);
+ stw(t1, obj, oopDesc::klass_offset_in_bytes());
+ } else {
+ st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());
+ }
+ if (len->is_valid()) st(len, obj, arrayOopDesc::length_offset_in_bytes());
+ else if (UseCompressedOops) {
+ store_klass_gap(G0, obj);
+ }
}
@@ -235,7 +245,7 @@ void C1_MacroAssembler::initialize_object(
Register t1, // temp register
Register t2 // temp register
) {
- const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes();
+ const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
initialize_header(obj, klass, noreg, t1, t2);
diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
index 127cc9ab316..7dabe35c23e 100644
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
@@ -612,7 +612,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// load the klass and check the has finalizer flag
Label register_finalizer;
Register t = O1;
- __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), t);
+ __ load_klass(O0, t);
__ ld(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), t);
__ set(JVM_ACC_HAS_FINALIZER, G3);
__ andcc(G3, t, G0);
diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
index 50bbbafa405..699f9151b8c 100644
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
@@ -689,8 +689,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
{
// Perform an in-place conversion to int or an int subword.
__ ldsw(G3_amh_vmargslot, O0_argslot);
- Address vmarg = __ argument_address(O0_argslot);
Address value;
+ Address vmarg = __ argument_address(O0_argslot);
bool value_left_justified = false;
switch (ek) {
@@ -700,9 +700,21 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
case _adapter_opt_l2i:
{
// just delete the extra slot
+#ifdef _LP64
+ // In V9, longs are given 2 64-bit slots in the interpreter, but the
+ // data is passed in only 1 slot.
+ // Keep the second slot.
+ __ add(Gargs, __ argument_offset(O0_argslot, -1), O0_argslot);
+ remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch);
+ value = Address(O0_argslot, 4); // Get least-significant 32-bit of 64-bit value.
+ vmarg = Address(O0_argslot, Interpreter::stackElementSize);
+#else
+ // Keep the first slot.
__ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch);
- value = vmarg = Address(O0_argslot, 0);
+ value = Address(O0_argslot, 0);
+ vmarg = value;
+#endif
}
break;
case _adapter_opt_unboxi:
diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad
index 386b38f634b..018fe70b9ec 100644
--- a/hotspot/src/cpu/sparc/vm/sparc.ad
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad
@@ -667,6 +667,20 @@ intptr_t get_offset_from_base_2(const MachNode* n, const TypePtr* atype, int dis
return offset;
}
+static inline jdouble replicate_immI(int con, int count, int width) {
+ // Load a constant replicated "count" times with width "width"
+ int bit_width = width * 8;
+ jlong elt_val = con;
+ elt_val &= (((jlong) 1) << bit_width) - 1; // mask off sign bits
+ jlong val = elt_val;
+ for (int i = 0; i < count - 1; i++) {
+ val <<= bit_width;
+ val |= elt_val;
+ }
+ jdouble dval = *((jdouble*) &val); // coerce to double type
+ return dval;
+}
+
// Standard Sparc opcode form2 field breakdown
static inline void emit2_19(CodeBuffer &cbuf, int f30, int f29, int f25, int f22, int f20, int f19, int f0 ) {
f0 &= (1<<19)-1; // Mask displacement to 19 bits
@@ -1007,6 +1021,90 @@ void emit_lo(CodeBuffer &cbuf, int val) { }
void emit_hi(CodeBuffer &cbuf, int val) { }
+//=============================================================================
+const bool Matcher::constant_table_absolute_addressing = false;
+const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+ Compile* C = ra_->C;
+ Compile::ConstantTable& constant_table = C->constant_table();
+ MacroAssembler _masm(&cbuf);
+
+ Register r = as_Register(ra_->get_encode(this));
+ CodeSection* cs = __ code()->consts();
+ int consts_size = cs->align_at_start(cs->size());
+
+ if (UseRDPCForConstantTableBase) {
+ // For the following RDPC logic to work correctly the consts
+ // section must be allocated right before the insts section. This
+ // assert checks for that. The layout and the SECT_* constants
+ // are defined in src/share/vm/asm/codeBuffer.hpp.
+ assert(CodeBuffer::SECT_CONSTS + 1 == CodeBuffer::SECT_INSTS, "must be");
+ int offset = __ offset();
+ int disp;
+
+ // If the displacement from the current PC to the constant table
+ // base fits into simm13 we set the constant table base to the
+ // current PC.
+ if (__ is_simm13(-(consts_size + offset))) {
+ constant_table.set_table_base_offset(-(consts_size + offset));
+ disp = 0;
+ } else {
+ // If the offset of the top constant (last entry in the table)
+ // fits into simm13 we set the constant table base to the actual
+ // table base.
+ if (__ is_simm13(constant_table.top_offset())) {
+ constant_table.set_table_base_offset(0);
+ disp = consts_size + offset;
+ } else {
+ // Otherwise we set the constant table base in the middle of the
+ // constant table.
+ int half_consts_size = consts_size / 2;
+ assert(half_consts_size * 2 == consts_size, "sanity");
+ constant_table.set_table_base_offset(-half_consts_size); // table base offset gets added to the load displacement.
+ disp = half_consts_size + offset;
+ }
+ }
+
+ __ rdpc(r);
+
+ if (disp != 0) {
+ assert(r != O7, "need temporary");
+ __ sub(r, __ ensure_simm13_or_reg(disp, O7), r);
+ }
+ }
+ else {
+ // Materialize the constant table base.
+ assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size));
+ address baseaddr = cs->start() + -(constant_table.table_base_offset());
+ RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
+ AddressLiteral base(baseaddr, rspec);
+ __ set(base, r);
+ }
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
+ if (UseRDPCForConstantTableBase) {
+ // This is really the worst case but generally it's only 1 instruction.
+ return 4 /*rdpc*/ + 4 /*sub*/ + MacroAssembler::worst_case_size_of_set();
+ } else {
+ return MacroAssembler::worst_case_size_of_set();
+ }
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+ char reg[128];
+ ra_->dump_register(this, reg);
+ if (UseRDPCForConstantTableBase) {
+ st->print("RDPC %s\t! constant table base", reg);
+ } else {
+ st->print("SET &constanttable,%s\t! constant table base", reg);
+ }
+}
+#endif
+
+
//=============================================================================
#ifndef PRODUCT
@@ -2247,25 +2345,6 @@ encode %{
__ delayed()->nop();
%}
- enc_class jump_enc( iRegX switch_val, o7RegI table) %{
- MacroAssembler _masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register table_reg = O7;
-
- address table_base = __ address_table_constant(_index2label);
- RelocationHolder rspec = internal_word_Relocation::spec(table_base);
-
- // Move table address into a register.
- __ set(table_base, table_reg, rspec);
-
- // Jump to base address + switch value
- __ ld_ptr(table_reg, switch_reg, table_reg);
- __ jmp(table_reg, G0);
- __ delayed()->nop();
-
- %}
-
enc_class enc_ba( Label labl ) %{
MacroAssembler _masm(&cbuf);
Label &L = *($labl$$label);
@@ -2384,20 +2463,6 @@ encode %{
cbuf.insts()->emit_int32(op);
%}
- // Utility encoding for loading a 64 bit Pointer into a register
- // The 64 bit pointer is stored in the generated code stream
- enc_class SetPtr( immP src, iRegP rd ) %{
- Register dest = reg_to_register_object($rd$$reg);
- MacroAssembler _masm(&cbuf);
- // [RGV] This next line should be generated from ADLC
- if ( _opnds[1]->constant_is_oop() ) {
- intptr_t val = $src$$constant;
- __ set_oop_constant((jobject)val, dest);
- } else { // non-oop pointers, e.g. card mark base, heap top
- __ set($src$$constant, dest);
- }
- %}
-
enc_class Set13( immI13 src, iRegI rd ) %{
emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, $src$$constant );
%}
@@ -2411,10 +2476,6 @@ encode %{
__ set($src$$constant, reg_to_register_object($rd$$reg));
%}
- enc_class SetNull( iRegI rd ) %{
- emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, 0 );
- %}
-
enc_class call_epilog %{
if( VerifyStackAtCalls ) {
MacroAssembler _masm(&cbuf);
@@ -2778,35 +2839,6 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
__ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst);
%}
- enc_class LdImmL (immL src, iRegL dst, o7RegL tmp) %{ // Load Immediate
- MacroAssembler _masm(&cbuf);
- Register dest = reg_to_register_object($dst$$reg);
- Register temp = reg_to_register_object($tmp$$reg);
- __ set64( $src$$constant, dest, temp );
- %}
-
- enc_class LdReplImmI(immI src, regD dst, o7RegP tmp, int count, int width) %{
- // Load a constant replicated "count" times with width "width"
- int bit_width = $width$$constant * 8;
- jlong elt_val = $src$$constant;
- elt_val &= (((jlong)1) << bit_width) - 1; // mask off sign bits
- jlong val = elt_val;
- for (int i = 0; i < $count$$constant - 1; i++) {
- val <<= bit_width;
- val |= elt_val;
- }
- jdouble dval = *(jdouble*)&val; // coerce to double type
- MacroAssembler _masm(&cbuf);
- address double_address = __ double_constant(dval);
- RelocationHolder rspec = internal_word_Relocation::spec(double_address);
- AddressLiteral addrlit(double_address, rspec);
-
- __ sethi(addrlit, $tmp$$Register);
- // XXX This is a quick fix for 6833573.
- //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
- __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
- %}
-
// Compiler ensures base is doubleword aligned and cnt is count of doublewords
enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{
MacroAssembler _masm(&cbuf);
@@ -3521,6 +3553,29 @@ operand immP() %{
interface(CONST_INTER);
%}
+// Pointer Immediate: 32 or 64-bit
+operand immP_set() %{
+ predicate(!VM_Version::is_niagara1_plus());
+ match(ConP);
+
+ op_cost(5);
+ // formats are generated automatically for constants and base registers
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Pointer Immediate: 32 or 64-bit
+// From Niagara2 processors on a load should be better than materializing.
+operand immP_load() %{
+ predicate(VM_Version::is_niagara1_plus());
+ match(ConP);
+
+ op_cost(5);
+ // formats are generated automatically for constants and base registers
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
operand immP13() %{
predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095));
match(ConP);
@@ -3616,6 +3671,26 @@ operand immL_32bits() %{
interface(CONST_INTER);
%}
+// Long Immediate: cheap (materialize in <= 3 instructions)
+operand immL_cheap() %{
+ predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::size_of_set64(n->get_long()) <= 3);
+ match(ConL);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Long Immediate: expensive (materialize in > 3 instructions)
+operand immL_expensive() %{
+ predicate(VM_Version::is_niagara1_plus() && MacroAssembler::size_of_set64(n->get_long()) > 3);
+ match(ConL);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Double Immediate
operand immD() %{
match(ConD);
@@ -5981,25 +6056,59 @@ instruct loadConI13( iRegI dst, immI13 src ) %{
ins_pipe(ialu_imm);
%}
-instruct loadConP(iRegP dst, immP src) %{
- match(Set dst src);
+#ifndef _LP64
+instruct loadConP(iRegP dst, immP con) %{
+ match(Set dst con);
ins_cost(DEFAULT_COST * 3/2);
- format %{ "SET $src,$dst\t!ptr" %}
- // This rule does not use "expand" unlike loadConI because then
- // the result type is not known to be an Oop. An ADLC
- // enhancement will be needed to make that work - not worth it!
-
- ins_encode( SetPtr( src, dst ) );
+ format %{ "SET $con,$dst\t!ptr" %}
+ ins_encode %{
+ // [RGV] This next line should be generated from ADLC
+ if (_opnds[1]->constant_is_oop()) {
+ intptr_t val = $con$$constant;
+ __ set_oop_constant((jobject) val, $dst$$Register);
+ } else { // non-oop pointers, e.g. card mark base, heap top
+ __ set($con$$constant, $dst$$Register);
+ }
+ %}
ins_pipe(loadConP);
-
%}
+#else
+instruct loadConP_set(iRegP dst, immP_set con) %{
+ match(Set dst con);
+ ins_cost(DEFAULT_COST * 3/2);
+ format %{ "SET $con,$dst\t! ptr" %}
+ ins_encode %{
+ // [RGV] This next line should be generated from ADLC
+ if (_opnds[1]->constant_is_oop()) {
+ intptr_t val = $con$$constant;
+ __ set_oop_constant((jobject) val, $dst$$Register);
+ } else { // non-oop pointers, e.g. card mark base, heap top
+ __ set($con$$constant, $dst$$Register);
+ }
+ %}
+ ins_pipe(loadConP);
+%}
+
+instruct loadConP_load(iRegP dst, immP_load con) %{
+ match(Set dst con);
+ ins_cost(MEMORY_REF_COST);
+ format %{ "LD [$constanttablebase + $constantoffset],$dst\t! load from constant table: ptr=$con" %}
+ ins_encode %{
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register);
+ __ ld_ptr($constanttablebase, con_offset, $dst$$Register);
+ %}
+ ins_pipe(loadConP);
+%}
+#endif // _LP64
instruct loadConP0(iRegP dst, immP0 src) %{
match(Set dst src);
size(4);
format %{ "CLR $dst\t!ptr" %}
- ins_encode( SetNull( dst ) );
+ ins_encode %{
+ __ clr($dst$$Register);
+ %}
ins_pipe(ialu_imm);
%}
@@ -6019,7 +6128,9 @@ instruct loadConN0(iRegN dst, immN0 src) %{
size(4);
format %{ "CLR $dst\t! compressed NULL ptr" %}
- ins_encode( SetNull( dst ) );
+ ins_encode %{
+ __ clr($dst$$Register);
+ %}
ins_pipe(ialu_imm);
%}
@@ -6034,13 +6145,27 @@ instruct loadConN(iRegN dst, immN src) %{
ins_pipe(ialu_hi_lo_reg);
%}
-instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{
- // %%% maybe this should work like loadConD
- match(Set dst src);
+// Materialize long value (predicated by immL_cheap).
+instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{
+ match(Set dst con);
effect(KILL tmp);
- ins_cost(DEFAULT_COST * 4);
- format %{ "SET64 $src,$dst KILL $tmp\t! long" %}
- ins_encode( LdImmL(src, dst, tmp) );
+ ins_cost(DEFAULT_COST * 3);
+ format %{ "SET64 $con,$dst KILL $tmp\t! cheap long" %}
+ ins_encode %{
+ __ set64($con$$constant, $dst$$Register, $tmp$$Register);
+ %}
+ ins_pipe(loadConL);
+%}
+
+// Load long value from constant table (predicated by immL_expensive).
+instruct loadConL_ldx(iRegL dst, immL_expensive con) %{
+ match(Set dst con);
+ ins_cost(MEMORY_REF_COST);
+ format %{ "LDX [$constanttablebase + $constantoffset],$dst\t! load from constant table: long=$con" %}
+ ins_encode %{
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register);
+ __ ldx($constanttablebase, con_offset, $dst$$Register);
+ %}
ins_pipe(loadConL);
%}
@@ -6063,50 +6188,26 @@ instruct loadConL13( iRegL dst, immL13 src ) %{
ins_pipe(ialu_imm);
%}
-instruct loadConF(regF dst, immF src, o7RegP tmp) %{
- match(Set dst src);
+instruct loadConF(regF dst, immF con, o7RegI tmp) %{
+ match(Set dst con);
effect(KILL tmp);
-
-#ifdef _LP64
- size(8*4);
-#else
- size(2*4);
-#endif
-
- format %{ "SETHI hi(&$src),$tmp\t!get float $src from table\n\t"
- "LDF [$tmp+lo(&$src)],$dst" %}
+ format %{ "LDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: float=$con" %}
ins_encode %{
- address float_address = __ float_constant($src$$constant);
- RelocationHolder rspec = internal_word_Relocation::spec(float_address);
- AddressLiteral addrlit(float_address, rspec);
-
- __ sethi(addrlit, $tmp$$Register);
- __ ldf(FloatRegisterImpl::S, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::S, $constanttablebase, con_offset, $dst$$FloatRegister);
%}
ins_pipe(loadConFD);
%}
-instruct loadConD(regD dst, immD src, o7RegP tmp) %{
- match(Set dst src);
+instruct loadConD(regD dst, immD con, o7RegI tmp) %{
+ match(Set dst con);
effect(KILL tmp);
-
-#ifdef _LP64
- size(8*4);
-#else
- size(2*4);
-#endif
-
- format %{ "SETHI hi(&$src),$tmp\t!get double $src from table\n\t"
- "LDDF [$tmp+lo(&$src)],$dst" %}
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: double=$con" %}
ins_encode %{
- address double_address = __ double_constant($src$$constant);
- RelocationHolder rspec = internal_word_Relocation::spec(double_address);
- AddressLiteral addrlit(double_address, rspec);
-
- __ sethi(addrlit, $tmp$$Register);
// XXX This is a quick fix for 6833573.
- //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
- __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
%}
ins_pipe(loadConFD);
%}
@@ -8558,16 +8659,16 @@ instruct Repl8B_reg(stackSlotD dst, iRegI src) %{
%}
// Replicate scalar constant to packed byte values in Double register
-instruct Repl8B_immI(regD dst, immI13 src, o7RegP tmp) %{
- match(Set dst (Replicate8B src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl8($src)),$tmp\t!get Repl8B($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl8($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (8), (1)) );
+instruct Repl8B_immI(regD dst, immI13 con, o7RegI tmp) %{
+ match(Set dst (Replicate8B con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl8B($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 8, 1)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8594,16 +8695,16 @@ instruct Repl4C_reg(stackSlotD dst, iRegI src) %{
%}
// Replicate scalar constant to packed char values in Double register
-instruct Repl4C_immI(regD dst, immI src, o7RegP tmp) %{
- match(Set dst (Replicate4C src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4C($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl4($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) );
+instruct Repl4C_immI(regD dst, immI con, o7RegI tmp) %{
+ match(Set dst (Replicate4C con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4C($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 4, 2)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8630,16 +8731,16 @@ instruct Repl4S_reg(stackSlotD dst, iRegI src) %{
%}
// Replicate scalar constant to packed short values in Double register
-instruct Repl4S_immI(regD dst, immI src, o7RegP tmp) %{
- match(Set dst (Replicate4S src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4S($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl4($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) );
+instruct Repl4S_immI(regD dst, immI con, o7RegI tmp) %{
+ match(Set dst (Replicate4S con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4S($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 4, 2)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8664,16 +8765,16 @@ instruct Repl2I_reg(stackSlotD dst, iRegI src) %{
%}
// Replicate scalar zero constant to packed int values in Double register
-instruct Repl2I_immI(regD dst, immI src, o7RegP tmp) %{
- match(Set dst (Replicate2I src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl2($src)),$tmp\t!get Repl2I($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl2($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (2), (4)) );
+instruct Repl2I_immI(regD dst, immI con, o7RegI tmp) %{
+ match(Set dst (Replicate2I con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl2I($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 2, 4)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8929,12 +9030,27 @@ instruct jumpXtnd(iRegX switch_val, o7RegI table) %{
ins_cost(350);
- format %{ "SETHI [hi(table_base)],O7\n\t"
- "ADD O7, lo(table_base), O7\n\t"
- "LD [O7+$switch_val], O7\n\t"
+ format %{ "ADD $constanttablebase, $constantoffset, O7\n\t"
+ "LD [O7 + $switch_val], O7\n\t"
"JUMP O7"
%}
- ins_encode( jump_enc( switch_val, table) );
+ ins_encode %{
+ // Calculate table address into a register.
+ Register table_reg;
+ Register label_reg = O7;
+ if (constant_offset() == 0) {
+ table_reg = $constanttablebase;
+ } else {
+ table_reg = O7;
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset, O7);
+ __ add($constanttablebase, con_offset, table_reg);
+ }
+
+ // Jump to base address + switch value
+ __ ld_ptr(table_reg, $switch_val$$Register, label_reg);
+ __ jmp(label_reg, G0);
+ __ delayed()->nop();
+ %}
ins_pc_relative(1);
ins_pipe(ialu_reg_reg);
%}
diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
index 93487bd30d4..5ae1fcbc30c 100644
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
@@ -80,9 +80,6 @@ protected:
static bool is_sparc64(int features) { return (features & fmaf_instructions_m) != 0; }
static int maximum_niagara1_processor_count() { return 32; }
- // Returns true if the platform is in the niagara line and
- // newer than the niagara1.
- static bool is_niagara1_plus();
public:
// Initialization
@@ -105,6 +102,9 @@ public:
static bool is_ultra3() { return (_features & ultra3_m) == ultra3_m; }
static bool is_sun4v() { return (_features & sun4v_m) != 0; }
static bool is_niagara1() { return is_niagara1(_features); }
+ // Returns true if the platform is in the niagara line and
+ // newer than the niagara1.
+ static bool is_niagara1_plus();
static bool is_sparc64() { return is_sparc64(_features); }
static bool has_fast_fxtof() { return has_v9() && !is_ultra3(); }
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
index 8a2b2f9d421..85dc5411f02 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
@@ -2649,6 +2649,37 @@ void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
emit_byte(0xC0 | encode);
}
+void Assembler::sqrtsd(XMMRegister dst, Address src) {
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ InstructionMark im(this);
+ emit_byte(0xF2);
+ prefix(src, dst);
+ emit_byte(0x0F);
+ emit_byte(0x51);
+ emit_operand(dst, src);
+}
+
+void Assembler::sqrtss(XMMRegister dst, XMMRegister src) {
+ // HMM Table D-1 says sse2
+ // NOT_LP64(assert(VM_Version::supports_sse(), ""));
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ emit_byte(0xF3);
+ int encode = prefix_and_encode(dst->encoding(), src->encoding());
+ emit_byte(0x0F);
+ emit_byte(0x51);
+ emit_byte(0xC0 | encode);
+}
+
+void Assembler::sqrtss(XMMRegister dst, Address src) {
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ InstructionMark im(this);
+ emit_byte(0xF3);
+ prefix(src, dst);
+ emit_byte(0x0F);
+ emit_byte(0x51);
+ emit_operand(dst, src);
+}
+
void Assembler::stmxcsr( Address dst) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
InstructionMark im(this);
@@ -4358,16 +4389,6 @@ void Assembler::shrq(Register dst) {
emit_byte(0xE8 | encode);
}
-void Assembler::sqrtsd(XMMRegister dst, Address src) {
- NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- InstructionMark im(this);
- emit_byte(0xF2);
- prefix(src, dst);
- emit_byte(0x0F);
- emit_byte(0x51);
- emit_operand(dst, src);
-}
-
void Assembler::subq(Address dst, int32_t imm32) {
InstructionMark im(this);
prefixq(dst);
@@ -4929,10 +4950,6 @@ void MacroAssembler::movptr(Address dst, intptr_t src) {
}
-void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) {
- movsd(dst, as_Address(src));
-}
-
void MacroAssembler::pop_callee_saved_registers() {
pop(rcx);
pop(rdx);
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
index d4bf4b422ec..b9fcc2eff00 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
@@ -135,6 +135,7 @@ REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved
// Using noreg ensures if the dead code is incorrectly live and executed it
// will cause an assertion failure
#define rscratch1 noreg
+#define rscratch2 noreg
#endif // _LP64
@@ -1352,6 +1353,10 @@ private:
void sqrtsd(XMMRegister dst, Address src);
void sqrtsd(XMMRegister dst, XMMRegister src);
+ // Compute Square Root of Scalar Single-Precision Floating-Point Value
+ void sqrtss(XMMRegister dst, Address src);
+ void sqrtss(XMMRegister dst, XMMRegister src);
+
void std() { emit_byte(0xfd); }
void stmxcsr( Address dst );
@@ -2124,6 +2129,9 @@ class MacroAssembler: public Assembler {
void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); }
void comisd(XMMRegister dst, AddressLiteral src);
+ void fadd_s(Address src) { Assembler::fadd_s(src); }
+ void fadd_s(AddressLiteral src) { Assembler::fadd_s(as_Address(src)); }
+
void fldcw(Address src) { Assembler::fldcw(src); }
void fldcw(AddressLiteral src);
@@ -2137,6 +2145,9 @@ class MacroAssembler: public Assembler {
void fld_x(Address src) { Assembler::fld_x(src); }
void fld_x(AddressLiteral src);
+ void fmul_s(Address src) { Assembler::fmul_s(src); }
+ void fmul_s(AddressLiteral src) { Assembler::fmul_s(as_Address(src)); }
+
void ldmxcsr(Address src) { Assembler::ldmxcsr(src); }
void ldmxcsr(AddressLiteral src);
@@ -2153,10 +2164,50 @@ private:
public:
- void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); }
- void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); }
- void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); }
- void movsd(XMMRegister dst, AddressLiteral src);
+ void addsd(XMMRegister dst, XMMRegister src) { Assembler::addsd(dst, src); }
+ void addsd(XMMRegister dst, Address src) { Assembler::addsd(dst, src); }
+ void addsd(XMMRegister dst, AddressLiteral src) { Assembler::addsd(dst, as_Address(src)); }
+
+ void addss(XMMRegister dst, XMMRegister src) { Assembler::addss(dst, src); }
+ void addss(XMMRegister dst, Address src) { Assembler::addss(dst, src); }
+ void addss(XMMRegister dst, AddressLiteral src) { Assembler::addss(dst, as_Address(src)); }
+
+ void divsd(XMMRegister dst, XMMRegister src) { Assembler::divsd(dst, src); }
+ void divsd(XMMRegister dst, Address src) { Assembler::divsd(dst, src); }
+ void divsd(XMMRegister dst, AddressLiteral src) { Assembler::divsd(dst, as_Address(src)); }
+
+ void divss(XMMRegister dst, XMMRegister src) { Assembler::divss(dst, src); }
+ void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); }
+ void divss(XMMRegister dst, AddressLiteral src) { Assembler::divss(dst, as_Address(src)); }
+
+ void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); }
+ void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); }
+ void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); }
+ void movsd(XMMRegister dst, AddressLiteral src) { Assembler::movsd(dst, as_Address(src)); }
+
+ void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); }
+ void mulsd(XMMRegister dst, Address src) { Assembler::mulsd(dst, src); }
+ void mulsd(XMMRegister dst, AddressLiteral src) { Assembler::mulsd(dst, as_Address(src)); }
+
+ void mulss(XMMRegister dst, XMMRegister src) { Assembler::mulss(dst, src); }
+ void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); }
+ void mulss(XMMRegister dst, AddressLiteral src) { Assembler::mulss(dst, as_Address(src)); }
+
+ void sqrtsd(XMMRegister dst, XMMRegister src) { Assembler::sqrtsd(dst, src); }
+ void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); }
+ void sqrtsd(XMMRegister dst, AddressLiteral src) { Assembler::sqrtsd(dst, as_Address(src)); }
+
+ void sqrtss(XMMRegister dst, XMMRegister src) { Assembler::sqrtss(dst, src); }
+ void sqrtss(XMMRegister dst, Address src) { Assembler::sqrtss(dst, src); }
+ void sqrtss(XMMRegister dst, AddressLiteral src) { Assembler::sqrtss(dst, as_Address(src)); }
+
+ void subsd(XMMRegister dst, XMMRegister src) { Assembler::subsd(dst, src); }
+ void subsd(XMMRegister dst, Address src) { Assembler::subsd(dst, src); }
+ void subsd(XMMRegister dst, AddressLiteral src) { Assembler::subsd(dst, as_Address(src)); }
+
+ void subss(XMMRegister dst, XMMRegister src) { Assembler::subss(dst, src); }
+ void subss(XMMRegister dst, Address src) { Assembler::subss(dst, src); }
+ void subss(XMMRegister dst, AddressLiteral src) { Assembler::subss(dst, as_Address(src)); }
void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); }
void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); }
diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp
index e8de24a5552..62088bd100e 100644
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp
@@ -483,7 +483,7 @@ void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
Register pre_val_reg = pre_val()->as_register();
- ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false);
+ ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
__ cmpptr(pre_val_reg, (int32_t) NULL_WORD);
__ jcc(Assembler::equal, _continuation);
diff --git a/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp b/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp
index 883fa166336..dab876adc8a 100644
--- a/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp
@@ -61,8 +61,8 @@ enum {
pd_nof_xmm_regs_linearscan = pd_nof_xmm_regs_frame_map, // number of registers visible to linear scan
pd_first_cpu_reg = 0,
pd_last_cpu_reg = NOT_LP64(5) LP64_ONLY(11),
- pd_first_byte_reg = 2,
- pd_last_byte_reg = 5,
+ pd_first_byte_reg = NOT_LP64(2) LP64_ONLY(0),
+ pd_last_byte_reg = NOT_LP64(5) LP64_ONLY(11),
pd_first_fpu_reg = pd_nof_cpu_regs_frame_map,
pd_last_fpu_reg = pd_first_fpu_reg + 7,
pd_first_xmm_reg = pd_nof_cpu_regs_frame_map + pd_nof_fpu_regs_frame_map,
diff --git a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp
index bc5037404a3..52f42977f71 100644
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp
@@ -158,9 +158,11 @@ void FrameMap::initialize() {
map_register( 6, r8); r8_opr = LIR_OprFact::single_cpu(6);
map_register( 7, r9); r9_opr = LIR_OprFact::single_cpu(7);
map_register( 8, r11); r11_opr = LIR_OprFact::single_cpu(8);
- map_register( 9, r12); r12_opr = LIR_OprFact::single_cpu(9);
- map_register(10, r13); r13_opr = LIR_OprFact::single_cpu(10);
- map_register(11, r14); r14_opr = LIR_OprFact::single_cpu(11);
+ map_register( 9, r13); r13_opr = LIR_OprFact::single_cpu(9);
+ map_register(10, r14); r14_opr = LIR_OprFact::single_cpu(10);
+ // r12 is allocated conditionally. With compressed oops it holds
+ // the heapbase value and is not visible to the allocator.
+ map_register(11, r12); r12_opr = LIR_OprFact::single_cpu(11);
// The unallocatable registers are at the end
map_register(12, r10); r10_opr = LIR_OprFact::single_cpu(12);
map_register(13, r15); r15_opr = LIR_OprFact::single_cpu(13);
@@ -191,9 +193,9 @@ void FrameMap::initialize() {
_caller_save_cpu_regs[6] = r8_opr;
_caller_save_cpu_regs[7] = r9_opr;
_caller_save_cpu_regs[8] = r11_opr;
- _caller_save_cpu_regs[9] = r12_opr;
- _caller_save_cpu_regs[10] = r13_opr;
- _caller_save_cpu_regs[11] = r14_opr;
+ _caller_save_cpu_regs[9] = r13_opr;
+ _caller_save_cpu_regs[10] = r14_opr;
+ _caller_save_cpu_regs[11] = r12_opr;
#endif // _LP64
diff --git a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp
index 17f2386c0ba..642701c2831 100644
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp
@@ -130,4 +130,15 @@
return _caller_save_xmm_regs[i];
}
+ static int adjust_reg_range(int range) {
+ // Reduce the number of available regs (to free r12) in case of compressed oops
+ if (UseCompressedOops) return range - 1;
+ return range;
+ }
+
+ static int nof_caller_save_cpu_regs() { return adjust_reg_range(pd_nof_caller_save_cpu_regs_frame_map); }
+ static int last_cpu_reg() { return adjust_reg_range(pd_last_cpu_reg); }
+ static int last_byte_reg() { return adjust_reg_range(pd_last_byte_reg); }
+
#endif // CPU_X86_VM_C1_FRAMEMAP_X86_HPP
+
diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
index 8c15f1926e5..724d8411bb5 100644
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
@@ -343,8 +343,8 @@ int LIR_Assembler::check_icache() {
Register receiver = FrameMap::receiver_opr->as_register();
Register ic_klass = IC_Klass;
const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
-
- if (!VerifyOops) {
+ const bool do_post_padding = VerifyOops || UseCompressedOops;
+ if (!do_post_padding) {
// insert some nops so that the verified entry point is aligned on CodeEntryAlignment
while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) {
__ nop();
@@ -352,8 +352,8 @@ int LIR_Assembler::check_icache() {
}
int offset = __ offset();
__ inline_cache_check(receiver, IC_Klass);
- assert(__ offset() % CodeEntryAlignment == 0 || VerifyOops, "alignment must be correct");
- if (VerifyOops) {
+ assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct");
+ if (do_post_padding) {
// force alignment after the cache check.
// It's been verified to be aligned if !VerifyOops
__ align(CodeEntryAlignment);
@@ -559,16 +559,16 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst,
__ movptr (rax, arg1->as_register());
// Get addresses of first characters from both Strings
- __ movptr (rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
- __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
- __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+ __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
+ __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
+ __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
// rbx, may be NULL
add_debug_info_for_null_check_here(info);
- __ movptr (rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
- __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
- __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+ __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
+ __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
+ __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
// compute minimum length (in rax) and difference of lengths (on top of stack)
if (VM_Version::supports_cmov()) {
@@ -696,13 +696,18 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
LIR_Const* c = src->as_constant_ptr();
switch (c->type()) {
- case T_INT:
- case T_ADDRESS: {
+ case T_INT: {
assert(patch_code == lir_patch_none, "no patching handled here");
__ movl(dest->as_register(), c->as_jint());
break;
}
+ case T_ADDRESS: {
+ assert(patch_code == lir_patch_none, "no patching handled here");
+ __ movptr(dest->as_register(), c->as_jint());
+ break;
+ }
+
case T_LONG: {
assert(patch_code == lir_patch_none, "no patching handled here");
#ifdef _LP64
@@ -780,10 +785,13 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) {
switch (c->type()) {
case T_INT: // fall through
case T_FLOAT:
- case T_ADDRESS:
__ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits());
break;
+ case T_ADDRESS:
+ __ movptr(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits());
+ break;
+
case T_OBJECT:
__ movoop(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jobject());
break;
@@ -806,7 +814,7 @@ void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) {
}
}
-void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info ) {
+void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) {
assert(src->is_constant(), "should not call otherwise");
assert(dest->is_address(), "should not call otherwise");
LIR_Const* c = src->as_constant_ptr();
@@ -816,14 +824,21 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi
switch (type) {
case T_INT: // fall through
case T_FLOAT:
- case T_ADDRESS:
__ movl(as_Address(addr), c->as_jint_bits());
break;
+ case T_ADDRESS:
+ __ movptr(as_Address(addr), c->as_jint_bits());
+ break;
+
case T_OBJECT: // fall through
case T_ARRAY:
if (c->as_jobject() == NULL) {
- __ movptr(as_Address(addr), NULL_WORD);
+ if (UseCompressedOops && !wide) {
+ __ movl(as_Address(addr), (int32_t)NULL_WORD);
+ } else {
+ __ movptr(as_Address(addr), NULL_WORD);
+ }
} else {
if (is_literal_address(addr)) {
ShouldNotReachHere();
@@ -831,8 +846,14 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi
} else {
#ifdef _LP64
__ movoop(rscratch1, c->as_jobject());
- null_check_here = code_offset();
- __ movptr(as_Address_lo(addr), rscratch1);
+ if (UseCompressedOops && !wide) {
+ __ encode_heap_oop(rscratch1);
+ null_check_here = code_offset();
+ __ movl(as_Address_lo(addr), rscratch1);
+ } else {
+ null_check_here = code_offset();
+ __ movptr(as_Address_lo(addr), rscratch1);
+ }
#else
__ movoop(as_Address(addr), c->as_jobject());
#endif
@@ -1009,22 +1030,28 @@ void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool po
}
-void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool /* unaligned */) {
+void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide, bool /* unaligned */) {
LIR_Address* to_addr = dest->as_address_ptr();
PatchingStub* patch = NULL;
+ Register compressed_src = rscratch1;
if (type == T_ARRAY || type == T_OBJECT) {
__ verify_oop(src->as_register());
+#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ movptr(compressed_src, src->as_register());
+ __ encode_heap_oop(compressed_src);
+ }
+#endif
}
+
if (patch_code != lir_patch_none) {
patch = new PatchingStub(_masm, PatchingStub::access_field_id);
Address toa = as_Address(to_addr);
assert(toa.disp() != 0, "must have");
}
- if (info != NULL) {
- add_debug_info_for_null_check_here(info);
- }
+ int null_check_here = code_offset();
switch (type) {
case T_FLOAT: {
if (src->is_single_xmm()) {
@@ -1050,13 +1077,17 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
break;
}
- case T_ADDRESS: // fall through
case T_ARRAY: // fall through
case T_OBJECT: // fall through
-#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ movl(as_Address(to_addr), compressed_src);
+ } else {
+ __ movptr(as_Address(to_addr), src->as_register());
+ }
+ break;
+ case T_ADDRESS:
__ movptr(as_Address(to_addr), src->as_register());
break;
-#endif // _LP64
case T_INT:
__ movl(as_Address(to_addr), src->as_register());
break;
@@ -1113,6 +1144,9 @@ void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
default:
ShouldNotReachHere();
}
+ if (info != NULL) {
+ add_debug_info_for_null_check(null_check_here, info);
+ }
if (patch_code != lir_patch_none) {
patching_epilog(patch, patch_code, to_addr->base()->as_register(), info);
@@ -1196,7 +1230,7 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) {
}
-void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool /* unaligned */) {
+void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool /* unaligned */) {
assert(src->is_address(), "should not call otherwise");
assert(dest->is_register(), "should not call otherwise");
@@ -1250,13 +1284,18 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
break;
}
- case T_ADDRESS: // fall through
case T_OBJECT: // fall through
case T_ARRAY: // fall through
-#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ movl(dest->as_register(), from_addr);
+ } else {
+ __ movptr(dest->as_register(), from_addr);
+ }
+ break;
+
+ case T_ADDRESS:
__ movptr(dest->as_register(), from_addr);
break;
-#endif // _L64
case T_INT:
__ movl(dest->as_register(), from_addr);
break;
@@ -1351,6 +1390,11 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
}
if (type == T_ARRAY || type == T_OBJECT) {
+#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ decode_heap_oop(dest->as_register());
+ }
+#endif
__ verify_oop(dest->as_register());
}
}
@@ -1672,11 +1716,8 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
ciMethod* method = op->profiled_method();
assert(method != NULL, "Should have method");
int bci = op->profiled_bci();
- md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
data = md->bci_to_data(bci);
assert(data != NULL, "need data for type check");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -1690,7 +1731,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
} else if (obj == klass_RInfo) {
klass_RInfo = dst;
}
- if (k->is_loaded()) {
+ if (k->is_loaded() && !UseCompressedOops) {
select_different_registers(obj, dst, k_RInfo, klass_RInfo);
} else {
Rtmp1 = op->tmp3()->as_register();
@@ -1727,21 +1768,26 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
if (op->fast_check()) {
// get object class
// not a safepoint as obj null check happens earlier
- if (k->is_loaded()) {
#ifdef _LP64
- __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
-#else
- __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
-#endif // _LP64
+ if (UseCompressedOops) {
+ __ load_klass(Rtmp1, obj);
+ __ cmpptr(k_RInfo, Rtmp1);
} else {
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
}
+#else
+ if (k->is_loaded()) {
+ __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
+ } else {
+ __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
+ }
+#endif
__ jcc(Assembler::notEqual, *failure_target);
// successful cast, fall through to profile or jump
} else {
// get object class
// not a safepoint as obj null check happens earlier
- __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(klass_RInfo, obj);
if (k->is_loaded()) {
// See if we get an immediate positive hit
#ifdef _LP64
@@ -1796,7 +1842,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
Register mdo = klass_RInfo, recv = k_RInfo;
__ bind(profile_cast_success);
__ movoop(mdo, md->constant_encoding());
- __ movptr(recv, Address(obj, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(recv, obj);
Label update_done;
type_profile_helper(mdo, md, data, recv, success);
__ jmp(*success);
@@ -1830,11 +1876,8 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
ciMethod* method = op->profiled_method();
assert(method != NULL, "Should have method");
int bci = op->profiled_bci();
- md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
data = md->bci_to_data(bci);
assert(data != NULL, "need data for type check");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -1860,10 +1903,10 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
}
add_debug_info_for_null_check_here(op->info_for_exception());
- __ movptr(k_RInfo, Address(array, oopDesc::klass_offset_in_bytes()));
- __ movptr(klass_RInfo, Address(value, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(k_RInfo, array);
+ __ load_klass(klass_RInfo, value);
- // get instance klass
+ // get instance klass (it's already uncompressed)
__ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)));
// perform the fast part of the checking logic
__ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL);
@@ -1882,7 +1925,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
Register mdo = klass_RInfo, recv = k_RInfo;
__ bind(profile_cast_success);
__ movoop(mdo, md->constant_encoding());
- __ movptr(recv, Address(value, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(recv, value);
Label update_done;
type_profile_helper(mdo, md, data, recv, &done);
__ jmpb(done);
@@ -1946,12 +1989,31 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
assert(cmpval != newval, "cmp and new values must be in different registers");
assert(cmpval != addr, "cmp and addr must be in different registers");
assert(newval != addr, "new value and addr must be in different registers");
- if (os::is_MP()) {
- __ lock();
- }
+
if ( op->code() == lir_cas_obj) {
- __ cmpxchgptr(newval, Address(addr, 0));
- } else if (op->code() == lir_cas_int) {
+#ifdef _LP64
+ if (UseCompressedOops) {
+ __ encode_heap_oop(cmpval);
+ __ mov(rscratch1, newval);
+ __ encode_heap_oop(rscratch1);
+ if (os::is_MP()) {
+ __ lock();
+ }
+ // cmpval (rax) is implicitly used by this instruction
+ __ cmpxchgl(rscratch1, Address(addr, 0));
+ } else
+#endif
+ {
+ if (os::is_MP()) {
+ __ lock();
+ }
+ __ cmpxchgptr(newval, Address(addr, 0));
+ }
+ } else {
+ assert(op->code() == lir_cas_int, "lir_cas_int expected");
+ if (os::is_MP()) {
+ __ lock();
+ }
__ cmpxchgl(newval, Address(addr, 0));
}
#ifdef _LP64
@@ -3193,8 +3255,13 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
}
if (flags & LIR_OpArrayCopy::type_check) {
- __ movptr(tmp, src_klass_addr);
- __ cmpptr(tmp, dst_klass_addr);
+ if (UseCompressedOops) {
+ __ movl(tmp, src_klass_addr);
+ __ cmpl(tmp, dst_klass_addr);
+ } else {
+ __ movptr(tmp, src_klass_addr);
+ __ cmpptr(tmp, dst_klass_addr);
+ }
__ jcc(Assembler::notEqual, *stub->entry());
}
@@ -3209,13 +3276,23 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
// but not necessarily exactly of type default_type.
Label known_ok, halt;
__ movoop(tmp, default_type->constant_encoding());
+#ifdef _LP64
+ if (UseCompressedOops) {
+ __ encode_heap_oop(tmp);
+ }
+#endif
+
if (basic_type != T_OBJECT) {
- __ cmpptr(tmp, dst_klass_addr);
+
+ if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr);
+ else __ cmpptr(tmp, dst_klass_addr);
__ jcc(Assembler::notEqual, halt);
- __ cmpptr(tmp, src_klass_addr);
+ if (UseCompressedOops) __ cmpl(tmp, src_klass_addr);
+ else __ cmpptr(tmp, src_klass_addr);
__ jcc(Assembler::equal, known_ok);
} else {
- __ cmpptr(tmp, dst_klass_addr);
+ if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr);
+ else __ cmpptr(tmp, dst_klass_addr);
__ jcc(Assembler::equal, known_ok);
__ cmpptr(src, dst);
__ jcc(Assembler::equal, known_ok);
@@ -3289,11 +3366,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
int bci = op->profiled_bci();
// Update counter for all call types
- ciMethodData* md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
assert(data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
@@ -3344,7 +3418,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
}
}
} else {
- __ movptr(recv, Address(recv, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(recv, recv);
Label update_done;
type_profile_helper(mdo, md, data, recv, &update_done);
// Receiver did not match any saved receiver and there is no empty row for it.
diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
index cf2cd56463b..d792a0f62a6 100644
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
@@ -874,6 +874,10 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
assert(x->number_of_arguments() == 5, "wrong type");
+
+ // Make all state_for calls early since they can emit code
+ CodeEmitInfo* info = state_for(x, x->state());
+
LIRItem src(x->argument_at(0), this);
LIRItem src_pos(x->argument_at(1), this);
LIRItem dst(x->argument_at(2), this);
@@ -916,7 +920,6 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
ciArrayKlass* expected_type;
arraycopy_helper(x, &flags, &expected_type);
- CodeEmitInfo* info = state_for(x, x->state()); // we may want to have stack (deoptimization?)
__ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(), length.result(), tmp, expected_type, flags, info); // does add_safepoint
}
@@ -1151,9 +1154,12 @@ void LIRGenerator::do_CheckCast(CheckCast* x) {
stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
}
LIR_Opr reg = rlock_result(x);
+ LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
+ if (!x->klass()->is_loaded() || UseCompressedOops) {
+ tmp3 = new_register(objectType);
+ }
__ checkcast(reg, obj.result(), x->klass(),
- new_register(objectType), new_register(objectType),
- !x->klass()->is_loaded() ? new_register(objectType) : LIR_OprFact::illegalOpr,
+ new_register(objectType), new_register(objectType), tmp3,
x->direct_compare(), info_for_exception, patching_info, stub,
x->profiled_method(), x->profiled_bci());
}
@@ -1170,9 +1176,12 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
patching_info = state_for(x, x->state_before());
}
obj.load_item();
+ LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
+ if (!x->klass()->is_loaded() || UseCompressedOops) {
+ tmp3 = new_register(objectType);
+ }
__ instanceof(reg, obj.result(), x->klass(),
- new_register(objectType), new_register(objectType),
- !x->klass()->is_loaded() ? new_register(objectType) : LIR_OprFact::illegalOpr,
+ new_register(objectType), new_register(objectType), tmp3,
x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci());
}
diff --git a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp
index 88d15e50d86..efb2002fd65 100644
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp
@@ -31,18 +31,17 @@ inline bool LinearScan::is_processed_reg_num(int reg_num) {
assert(FrameMap::rsp_opr->cpu_regnr() == 6, "wrong assumption below");
assert(FrameMap::rbp_opr->cpu_regnr() == 7, "wrong assumption below");
assert(reg_num >= 0, "invalid reg_num");
-
- return reg_num < 6 || reg_num > 7;
#else
- // rsp and rbp, r10, r15 (numbers 6 ancd 7) are ignored
+ // rsp and rbp, r10, r15 (numbers [12,15]) are ignored
+ // r12 (number 11) is conditional on compressed oops.
+ assert(FrameMap::r12_opr->cpu_regnr() == 11, "wrong assumption below");
assert(FrameMap::r10_opr->cpu_regnr() == 12, "wrong assumption below");
assert(FrameMap::r15_opr->cpu_regnr() == 13, "wrong assumption below");
assert(FrameMap::rsp_opr->cpu_regnrLo() == 14, "wrong assumption below");
assert(FrameMap::rbp_opr->cpu_regnrLo() == 15, "wrong assumption below");
assert(reg_num >= 0, "invalid reg_num");
-
- return reg_num < 12 || reg_num > 15;
#endif // _LP64
+ return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map;
}
inline int LinearScan::num_physical_regs(BasicType type) {
@@ -104,7 +103,7 @@ inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) {
if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) {
assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only");
_first_reg = pd_first_byte_reg;
- _last_reg = pd_last_byte_reg;
+ _last_reg = FrameMap::last_byte_reg();
return true;
} else if ((UseSSE >= 1 && cur->type() == T_FLOAT) || (UseSSE >= 2 && cur->type() == T_DOUBLE)) {
_first_reg = pd_first_xmm_reg;
diff --git a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp
index de6e2e58108..48d117b3fd5 100644
--- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp
@@ -155,11 +155,26 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
// This assumes that all prototype bits fit in an int32_t
movptr(Address(obj, oopDesc::mark_offset_in_bytes ()), (int32_t)(intptr_t)markOopDesc::prototype());
}
+#ifdef _LP64
+ if (UseCompressedOops) { // Take care not to kill klass
+ movptr(t1, klass);
+ encode_heap_oop_not_null(t1);
+ movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
+ } else
+#endif
+ {
+ movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
+ }
- movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
if (len->is_valid()) {
movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
}
+#ifdef _LP64
+ else if (UseCompressedOops) {
+ xorptr(t1, t1);
+ store_klass_gap(obj, t1);
+ }
+#endif
}
@@ -230,7 +245,7 @@ void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2,
void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) {
assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
"con_size_in_bytes is not multiple of alignment");
- const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes();
+ const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
initialize_header(obj, klass, noreg, t1, t2);
@@ -317,13 +332,19 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
// check against inline cache
assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
int start_offset = offset();
- cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes()));
+
+ if (UseCompressedOops) {
+ load_klass(rscratch1, receiver);
+ cmpptr(rscratch1, iCache);
+ } else {
+ cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ }
// if icache check fails, then jump to runtime routine
// Note: RECEIVER must still contain the receiver!
jump_cc(Assembler::notEqual,
RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
- assert(offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
+ assert(UseCompressedOops || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
}
diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
index 23afb8267d0..ce51fea3add 100644
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
@@ -1261,7 +1261,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// load the klass and check the has finalizer flag
Label register_finalizer;
Register t = rsi;
- __ movptr(t, Address(rax, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(t, rax);
__ movl(t, Address(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc)));
__ testl(t, JVM_ACC_HAS_FINALIZER);
__ jcc(Assembler::notZero, register_finalizer);
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index 1087bf9c54c..3d5bcc99bfb 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -2197,9 +2197,6 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
- checkcast_copy_entry = __ pc();
- BLOCK_COMMENT("Entry:");
-
#ifdef ASSERT
// caller guarantees that the arrays really are different
// otherwise, we would have to make conjoint checks
@@ -2210,26 +2207,28 @@ class StubGenerator: public StubCodeGenerator {
}
#endif //ASSERT
- // allocate spill slots for r13, r14
- enum {
- saved_r13_offset,
- saved_r14_offset,
- saved_rbp_offset,
- saved_rip_offset,
- saved_rarg0_offset
- };
- __ subptr(rsp, saved_rbp_offset * wordSize);
- __ movptr(Address(rsp, saved_r13_offset * wordSize), r13);
- __ movptr(Address(rsp, saved_r14_offset * wordSize), r14);
setup_arg_regs(4); // from => rdi, to => rsi, length => rdx
// ckoff => rcx, ckval => r8
// r9 and r10 may be used to save non-volatile registers
#ifdef _WIN64
// last argument (#4) is on stack on Win64
- const int ckval_offset = saved_rarg0_offset + 4;
- __ movptr(ckval, Address(rsp, ckval_offset * wordSize));
+ __ movptr(ckval, Address(rsp, 6 * wordSize));
#endif
+ // Caller of this entry point must set up the argument registers.
+ checkcast_copy_entry = __ pc();
+ BLOCK_COMMENT("Entry:");
+
+ // allocate spill slots for r13, r14
+ enum {
+ saved_r13_offset,
+ saved_r14_offset,
+ saved_rbp_offset
+ };
+ __ subptr(rsp, saved_rbp_offset * wordSize);
+ __ movptr(Address(rsp, saved_r13_offset * wordSize), r13);
+ __ movptr(Address(rsp, saved_r14_offset * wordSize), r14);
+
// check that int operands are properly extended to size_t
assert_clean_int(length, rax);
assert_clean_int(ckoff, rax);
@@ -2443,11 +2442,10 @@ class StubGenerator: public StubCodeGenerator {
const Register src_pos = c_rarg1; // source position
const Register dst = c_rarg2; // destination array oop
const Register dst_pos = c_rarg3; // destination position
- // elements count is on stack on Win64
-#ifdef _WIN64
-#define C_RARG4 Address(rsp, 6 * wordSize)
+#ifndef _WIN64
+ const Register length = c_rarg4;
#else
-#define C_RARG4 c_rarg4
+ const Address length(rsp, 6 * wordSize); // elements count is on stack on Win64
#endif
{ int modulus = CodeEntryAlignment;
@@ -2514,27 +2512,27 @@ class StubGenerator: public StubCodeGenerator {
// registers used as temp
const Register r11_length = r11; // elements count to copy
const Register r10_src_klass = r10; // array klass
- const Register r9_dst_klass = r9; // dest array klass
// if (length < 0) return -1;
- __ movl(r11_length, C_RARG4); // length (elements count, 32-bits value)
+ __ movl(r11_length, length); // length (elements count, 32-bits value)
__ testl(r11_length, r11_length);
__ jccb(Assembler::negative, L_failed_0);
__ load_klass(r10_src_klass, src);
#ifdef ASSERT
// assert(src->klass() != NULL);
- BLOCK_COMMENT("assert klasses not null");
- { Label L1, L2;
+ {
+ BLOCK_COMMENT("assert klasses not null {");
+ Label L1, L2;
__ testptr(r10_src_klass, r10_src_klass);
__ jcc(Assembler::notZero, L2); // it is broken if klass is NULL
__ bind(L1);
__ stop("broken null klass");
__ bind(L2);
- __ load_klass(r9_dst_klass, dst);
- __ cmpq(r9_dst_klass, 0);
+ __ load_klass(rax, dst);
+ __ cmpq(rax, 0);
__ jcc(Assembler::equal, L1); // this would be broken also
- BLOCK_COMMENT("assert done");
+ BLOCK_COMMENT("} assert klasses not null done");
}
#endif
@@ -2546,34 +2544,36 @@ class StubGenerator: public StubCodeGenerator {
// array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
//
- int lh_offset = klassOopDesc::header_size() * HeapWordSize +
- Klass::layout_helper_offset_in_bytes();
-
- const Register rax_lh = rax; // layout helper
-
- __ movl(rax_lh, Address(r10_src_klass, lh_offset));
+ const int lh_offset = klassOopDesc::header_size() * HeapWordSize +
+ Klass::layout_helper_offset_in_bytes();
// Handle objArrays completely differently...
- jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
- __ cmpl(rax_lh, objArray_lh);
+ const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
+ __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
__ jcc(Assembler::equal, L_objArray);
// if (src->klass() != dst->klass()) return -1;
- __ load_klass(r9_dst_klass, dst);
- __ cmpq(r10_src_klass, r9_dst_klass);
+ __ load_klass(rax, dst);
+ __ cmpq(r10_src_klass, rax);
__ jcc(Assembler::notEqual, L_failed);
+ const Register rax_lh = rax; // layout helper
+ __ movl(rax_lh, Address(r10_src_klass, lh_offset));
+
// if (!src->is_Array()) return -1;
__ cmpl(rax_lh, Klass::_lh_neutral_value);
__ jcc(Assembler::greaterEqual, L_failed);
// At this point, it is known to be a typeArray (array_tag 0x3).
#ifdef ASSERT
- { Label L;
+ {
+ BLOCK_COMMENT("assert primitive array {");
+ Label L;
__ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
__ jcc(Assembler::greaterEqual, L);
__ stop("must be a primitive array");
__ bind(L);
+ BLOCK_COMMENT("} assert primitive array done");
}
#endif
@@ -2631,11 +2631,14 @@ class StubGenerator: public StubCodeGenerator {
__ BIND(L_copy_longs);
#ifdef ASSERT
- { Label L;
+ {
+ BLOCK_COMMENT("assert long copy {");
+ Label L;
__ cmpl(rax_elsize, LogBytesPerLong);
__ jcc(Assembler::equal, L);
__ stop("must be long copy, but elsize is wrong");
__ bind(L);
+ BLOCK_COMMENT("} assert long copy done");
}
#endif
__ lea(from, Address(src, src_pos, Address::times_8, 0));// src_addr
@@ -2645,12 +2648,12 @@ class StubGenerator: public StubCodeGenerator {
// objArrayKlass
__ BIND(L_objArray);
- // live at this point: r10_src_klass, src[_pos], dst[_pos]
+ // live at this point: r10_src_klass, r11_length, src[_pos], dst[_pos]
Label L_plain_copy, L_checkcast_copy;
// test array classes for subtyping
- __ load_klass(r9_dst_klass, dst);
- __ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality
+ __ load_klass(rax, dst);
+ __ cmpq(r10_src_klass, rax); // usual case is exact equality
__ jcc(Assembler::notEqual, L_checkcast_copy);
// Identically typed arrays can be copied without element-wise checks.
@@ -2666,41 +2669,33 @@ class StubGenerator: public StubCodeGenerator {
__ jump(RuntimeAddress(oop_copy_entry));
__ BIND(L_checkcast_copy);
- // live at this point: r10_src_klass, !r11_length
+ // live at this point: r10_src_klass, r11_length, rax (dst_klass)
{
- // assert(r11_length == C_RARG4); // will reload from here
- Register r11_dst_klass = r11;
- __ load_klass(r11_dst_klass, dst);
-
// Before looking at dst.length, make sure dst is also an objArray.
- __ cmpl(Address(r11_dst_klass, lh_offset), objArray_lh);
+ __ cmpl(Address(rax, lh_offset), objArray_lh);
__ jcc(Assembler::notEqual, L_failed);
// It is safe to examine both src.length and dst.length.
-#ifndef _WIN64
- arraycopy_range_checks(src, src_pos, dst, dst_pos, C_RARG4,
- rax, L_failed);
-#else
- __ movl(r11_length, C_RARG4); // reload
arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
rax, L_failed);
+
+ const Register r11_dst_klass = r11;
__ load_klass(r11_dst_klass, dst); // reload
-#endif
// Marshal the base address arguments now, freeing registers.
__ lea(from, Address(src, src_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
__ lea(to, Address(dst, dst_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
- __ movl(count, C_RARG4); // length (reloaded)
+ __ movl(count, length); // length (reloaded)
Register sco_temp = c_rarg3; // this register is free now
assert_different_registers(from, to, count, sco_temp,
r11_dst_klass, r10_src_klass);
assert_clean_int(count, sco_temp);
// Generate the type check.
- int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
- Klass::super_check_offset_offset_in_bytes());
+ const int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
+ Klass::super_check_offset_offset_in_bytes());
__ movl(sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
generate_type_check(r10_src_klass, sco_temp, r11_dst_klass, L_plain_copy);
@@ -2709,12 +2704,14 @@ class StubGenerator: public StubCodeGenerator {
int ek_offset = (klassOopDesc::header_size() * HeapWordSize +
objArrayKlass::element_klass_offset_in_bytes());
__ movptr(r11_dst_klass, Address(r11_dst_klass, ek_offset));
- __ movl(sco_temp, Address(r11_dst_klass, sco_offset));
+ __ movl( sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
// the checkcast_copy loop needs two extra arguments:
assert(c_rarg3 == sco_temp, "#3 already in place");
- __ movptr(C_RARG4, r11_dst_klass); // dst.klass.element_klass
+ // Set up arguments for checkcast_copy_entry.
+ setup_arg_regs(4);
+ __ movptr(r8, r11_dst_klass); // dst.klass.element_klass, r8 is c_rarg4 on Linux/Solaris
__ jump(RuntimeAddress(checkcast_copy_entry));
}
@@ -2727,8 +2724,6 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
-#undef length_arg
-
void generate_arraycopy_stubs() {
// Call the conjoint generation methods immediately after
// the disjoint ones so that short branches from the former
diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad
index 21b6bf97bfe..b73bcda7fa9 100644
--- a/hotspot/src/cpu/x86/vm/x86_32.ad
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad
@@ -506,6 +506,25 @@ void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) {
}
+//=============================================================================
+const bool Matcher::constant_table_absolute_addressing = true;
+const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+ // Empty encoding
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
+ return 0;
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+ st->print("# MachConstantBaseNode (empty encoding)");
+}
+#endif
+
+
//=============================================================================
#ifndef PRODUCT
void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
@@ -1320,29 +1339,6 @@ int emit_deopt_handler(CodeBuffer& cbuf) {
}
-static void emit_double_constant(CodeBuffer& cbuf, double x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address double_address = __ double_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int)double_address,
- internal_word_Relocation::spec(double_address),
- RELOC_DISP32);
-}
-
-static void emit_float_constant(CodeBuffer& cbuf, float x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address float_address = __ float_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int)float_address,
- internal_word_Relocation::spec(float_address),
- RELOC_DISP32);
-}
-
-
const bool Matcher::match_rule_supported(int opcode) {
if (!has_match_rule(opcode))
return false;
@@ -1354,22 +1350,6 @@ int Matcher::regnum_to_fpu_offset(int regnum) {
return regnum - 32; // The FP registers are in the second chunk
}
-bool is_positive_zero_float(jfloat f) {
- return jint_cast(f) == jint_cast(0.0F);
-}
-
-bool is_positive_one_float(jfloat f) {
- return jint_cast(f) == jint_cast(1.0F);
-}
-
-bool is_positive_zero_double(jdouble d) {
- return jlong_cast(d) == jlong_cast(0.0);
-}
-
-bool is_positive_one_double(jdouble d) {
- return jlong_cast(d) == jlong_cast(1.0);
-}
-
// This is UltraSparc specific, true just means we have fast l2f conversion
const bool Matcher::convL2FSupported(void) {
return true;
@@ -2036,67 +2016,6 @@ encode %{
%}
- enc_class LdImmD (immD src) %{ // Load Immediate
- if( is_positive_zero_double($src$$constant)) {
- // FLDZ
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xEE);
- } else if( is_positive_one_double($src$$constant)) {
- // FLD1
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xE8);
- } else {
- emit_opcode(cbuf,0xDD);
- emit_rm(cbuf, 0x0, 0x0, 0x5);
- emit_double_constant(cbuf, $src$$constant);
- }
- %}
-
-
- enc_class LdImmF (immF src) %{ // Load Immediate
- if( is_positive_zero_float($src$$constant)) {
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xEE);
- } else if( is_positive_one_float($src$$constant)) {
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xE8);
- } else {
- $$$emit8$primary;
- // Load immediate does not have a zero or sign extended version
- // for 8-bit immediates
- // First load to TOS, then move to dst
- emit_rm(cbuf, 0x0, 0x0, 0x5);
- emit_float_constant(cbuf, $src$$constant);
- }
- %}
-
- enc_class LdImmX (regX dst, immXF con) %{ // Load Immediate
- emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
- emit_float_constant(cbuf, $con$$constant);
- %}
-
- enc_class LdImmXD (regXD dst, immXD con) %{ // Load Immediate
- emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
- emit_double_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_conXD (regXD dst, immXD con) %{ // Load double constant
- // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
- emit_opcode(cbuf, 0x0F);
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
- emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
- emit_double_constant(cbuf, $con$$constant);
- %}
-
- enc_class Opc_MemImm_F(immF src) %{
- cbuf.set_insts_mark();
- $$$emit8$primary;
- emit_rm(cbuf, 0x0, $secondary, 0x5);
- emit_float_constant(cbuf, $src$$constant);
- %}
-
-
enc_class MovI2X_reg(regX dst, eRegI src) %{
emit_opcode(cbuf, 0x66 ); // MOVD dst,src
emit_opcode(cbuf, 0x0F );
@@ -4801,7 +4720,7 @@ operand immD0() %{
interface(CONST_INTER);
%}
-// Double Immediate
+// Double Immediate one
operand immD1() %{
predicate( UseSSE<=1 && n->getd() == 1.0 );
match(ConD);
@@ -4844,7 +4763,17 @@ operand immXD0() %{
// Float Immediate zero
operand immF0() %{
- predicate( UseSSE == 0 && n->getf() == 0.0 );
+ predicate(UseSSE == 0 && n->getf() == 0.0F);
+ match(ConF);
+
+ op_cost(5);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Float Immediate one
+operand immF1() %{
+ predicate(UseSSE == 0 && n->getf() == 1.0F);
match(ConF);
op_cost(5);
@@ -7215,24 +7144,53 @@ instruct loadConL0(eRegL dst, immL0 src, eFlagsReg cr) %{
%}
// The instruction usage is guarded by predicate in operand immF().
-instruct loadConF(regF dst, immF src) %{
- match(Set dst src);
+instruct loadConF(regF dst, immF con) %{
+ match(Set dst con);
ins_cost(125);
-
- format %{ "FLD_S ST,$src\n\t"
+ format %{ "FLD_S ST,[$constantaddress]\t# load from constant table: float=$con\n\t"
"FSTP $dst" %}
- opcode(0xD9, 0x00); /* D9 /0 */
- ins_encode(LdImmF(src), Pop_Reg_F(dst) );
- ins_pipe( fpu_reg_con );
+ ins_encode %{
+ __ fld_s($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immF0().
+instruct loadConF0(regF dst, immF0 con) %{
+ match(Set dst con);
+ ins_cost(125);
+ format %{ "FLDZ ST\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fldz();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immF1().
+instruct loadConF1(regF dst, immF1 con) %{
+ match(Set dst con);
+ ins_cost(125);
+ format %{ "FLD1 ST\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld1();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
%}
// The instruction usage is guarded by predicate in operand immXF().
instruct loadConX(regX dst, immXF con) %{
match(Set dst con);
ins_cost(125);
- format %{ "MOVSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), LdImmX(dst, con));
- ins_pipe( pipe_slow );
+ format %{ "MOVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ movflt($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
// The instruction usage is guarded by predicate in operand immXF0().
@@ -7240,28 +7198,63 @@ instruct loadConX0(regX dst, immXF0 src) %{
match(Set dst src);
ins_cost(100);
format %{ "XORPS $dst,$dst\t# float 0.0" %}
- ins_encode( Opcode(0x0F), Opcode(0x57), RegReg(dst,dst));
- ins_pipe( pipe_slow );
+ ins_encode %{
+ __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe(pipe_slow);
%}
// The instruction usage is guarded by predicate in operand immD().
-instruct loadConD(regD dst, immD src) %{
- match(Set dst src);
+instruct loadConD(regD dst, immD con) %{
+ match(Set dst con);
ins_cost(125);
- format %{ "FLD_D ST,$src\n\t"
+ format %{ "FLD_D ST,[$constantaddress]\t# load from constant table: double=$con\n\t"
"FSTP $dst" %}
- ins_encode(LdImmD(src), Pop_Reg_D(dst) );
- ins_pipe( fpu_reg_con );
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immD0().
+instruct loadConD0(regD dst, immD0 con) %{
+ match(Set dst con);
+ ins_cost(125);
+
+ format %{ "FLDZ ST\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fldz();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immD1().
+instruct loadConD1(regD dst, immD1 con) %{
+ match(Set dst con);
+ ins_cost(125);
+
+ format %{ "FLD1 ST\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld1();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
%}
// The instruction usage is guarded by predicate in operand immXD().
instruct loadConXD(regXD dst, immXD con) %{
match(Set dst con);
ins_cost(125);
- format %{ "MOVSD $dst,[$con]" %}
- ins_encode(load_conXD(dst, con));
- ins_pipe( pipe_slow );
+ format %{ "MOVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ movdbl($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
// The instruction usage is guarded by predicate in operand immXD0().
@@ -10303,41 +10296,45 @@ instruct addD_mem_reg(memory dst, regD src) %{
ins_pipe( fpu_reg_mem );
%}
-instruct addD_reg_imm1(regD dst, immD1 src) %{
+instruct addD_reg_imm1(regD dst, immD1 con) %{
predicate(UseSSE<=1);
- match(Set dst (AddD dst src));
+ match(Set dst (AddD dst con));
ins_cost(125);
format %{ "FLD1\n\t"
"DADDp $dst,ST" %}
- opcode(0xDE, 0x00);
- ins_encode( LdImmD(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg );
+ ins_encode %{
+ __ fld1();
+ __ faddp($dst$$reg);
+ %}
+ ins_pipe(fpu_reg);
%}
-instruct addD_reg_imm(regD dst, immD src) %{
+instruct addD_reg_imm(regD dst, immD con) %{
predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
- match(Set dst (AddD dst src));
+ match(Set dst (AddD dst con));
ins_cost(200);
- format %{ "FLD_D [$src]\n\t"
+ format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
"DADDp $dst,ST" %}
- opcode(0xDE, 0x00); /* DE /0 */
- ins_encode( LdImmD(src),
- OpcP, RegOpc(dst));
- ins_pipe( fpu_reg_mem );
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ faddp($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_mem);
%}
instruct addD_reg_imm_round(stackSlotD dst, regD src, immD con) %{
predicate(UseSSE<=1 && _kids[0]->_kids[1]->_leaf->getd() != 0.0 && _kids[0]->_kids[1]->_leaf->getd() != 1.0 );
match(Set dst (RoundDouble (AddD src con)));
ins_cost(200);
- format %{ "FLD_D [$con]\n\t"
+ format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
"DADD ST,$src\n\t"
"FSTP_D $dst\t# D-round" %}
- opcode(0xD8, 0x00); /* D8 /0 */
- ins_encode( LdImmD(con),
- OpcP, RegOpc(src), Pop_Mem_D(dst));
- ins_pipe( fpu_mem_reg_con );
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ fadd($src$$reg);
+ __ fstp_d(Address(rsp, $dst$$disp));
+ %}
+ ins_pipe(fpu_mem_reg_con);
%}
// Add two double precision floating point values in xmm
@@ -10352,9 +10349,11 @@ instruct addXD_reg(regXD dst, regXD src) %{
instruct addXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (AddD dst con));
- format %{ "ADDSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), LdImmXD(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "ADDSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ addsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct addXD_mem(regXD dst, memory mem) %{
@@ -10377,9 +10376,11 @@ instruct subXD_reg(regXD dst, regXD src) %{
instruct subXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (SubD dst con));
- format %{ "SUBSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), LdImmXD(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "SUBSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ subsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct subXD_mem(regXD dst, memory mem) %{
@@ -10402,9 +10403,11 @@ instruct mulXD_reg(regXD dst, regXD src) %{
instruct mulXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (MulD dst con));
- format %{ "MULSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), LdImmXD(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "MULSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ mulsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct mulXD_mem(regXD dst, memory mem) %{
@@ -10428,9 +10431,11 @@ instruct divXD_reg(regXD dst, regXD src) %{
instruct divXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (DivD dst con));
- format %{ "DIVSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), LdImmXD(dst, con));
- ins_pipe( pipe_slow );
+ format %{ "DIVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ divsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct divXD_mem(regXD dst, memory mem) %{
@@ -10481,16 +10486,17 @@ instruct strictfp_mulD_reg(regDPR1 dst, regnotDPR1 src) %{
ins_pipe( fpu_reg_reg );
%}
-instruct mulD_reg_imm(regD dst, immD src) %{
+instruct mulD_reg_imm(regD dst, immD con) %{
predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
- match(Set dst (MulD dst src));
+ match(Set dst (MulD dst con));
ins_cost(200);
- format %{ "FLD_D [$src]\n\t"
+ format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
"DMULp $dst,ST" %}
- opcode(0xDE, 0x1); /* DE /1 */
- ins_encode( LdImmD(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_mem );
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ fmulp($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_mem);
%}
@@ -11224,9 +11230,11 @@ instruct addX_reg(regX dst, regX src) %{
instruct addX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (AddF dst con));
- format %{ "ADDSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "ADDSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ addss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct addX_mem(regX dst, memory mem) %{
@@ -11249,9 +11257,11 @@ instruct subX_reg(regX dst, regX src) %{
instruct subX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (SubF dst con));
- format %{ "SUBSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "SUBSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ subss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct subX_mem(regX dst, memory mem) %{
@@ -11274,9 +11284,11 @@ instruct mulX_reg(regX dst, regX src) %{
instruct mulX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (MulF dst con));
- format %{ "MULSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "MULSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ mulss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct mulX_mem(regX dst, memory mem) %{
@@ -11299,9 +11311,11 @@ instruct divX_reg(regX dst, regX src) %{
instruct divX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (DivF dst con));
- format %{ "DIVSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "DIVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ divss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct divX_mem(regX dst, memory mem) %{
@@ -11456,31 +11470,33 @@ instruct addF24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
// Spill to obtain 24-bit precision
-instruct addF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
+instruct addF24_reg_imm(stackSlotF dst, regF src, immF con) %{
predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 src2));
- format %{ "FLD $src1\n\t"
- "FADD $src2\n\t"
+ match(Set dst (AddF src con));
+ format %{ "FLD $src\n\t"
+ "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
"FSTP_S $dst" %}
- opcode(0xD8, 0x00); /* D8 /0 */
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Mem_F(dst));
- ins_pipe( fpu_mem_reg_con );
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fadd_s($constantaddress($con));
+ __ fstp_s(Address(rsp, $dst$$disp));
+ %}
+ ins_pipe(fpu_mem_reg_con);
%}
//
// This instruction does not round to 24-bits
-instruct addF_reg_imm(regF dst, regF src1, immF src2) %{
+instruct addF_reg_imm(regF dst, regF src, immF con) %{
predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 src2));
- format %{ "FLD $src1\n\t"
- "FADD $src2\n\t"
- "FSTP_S $dst" %}
- opcode(0xD8, 0x00); /* D8 /0 */
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Reg_F(dst));
- ins_pipe( fpu_reg_reg_con );
+ match(Set dst (AddF src con));
+ format %{ "FLD $src\n\t"
+ "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fadd_s($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_reg_con);
%}
// Spill to obtain 24-bit precision
@@ -11559,29 +11575,35 @@ instruct mulF24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
%}
// Spill to obtain 24-bit precision
-instruct mulF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
+instruct mulF24_reg_imm(stackSlotF dst, regF src, immF con) %{
predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 src2));
+ match(Set dst (MulF src con));
- format %{ "FMULc $dst,$src1,$src2" %}
- opcode(0xD8, 0x1); /* D8 /1*/
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Mem_F(dst));
- ins_pipe( fpu_mem_reg_con );
+ format %{ "FLD $src\n\t"
+ "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+ "FSTP_S $dst" %}
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fmul_s($constantaddress($con));
+ __ fstp_s(Address(rsp, $dst$$disp));
+ %}
+ ins_pipe(fpu_mem_reg_con);
%}
//
// This instruction does not round to 24-bits
-instruct mulF_reg_imm(regF dst, regF src1, immF src2) %{
+instruct mulF_reg_imm(regF dst, regF src, immF con) %{
predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 src2));
+ match(Set dst (MulF src con));
- format %{ "FMULc $dst. $src1, $src2" %}
- opcode(0xD8, 0x1); /* D8 /1*/
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Reg_F(dst));
- ins_pipe( fpu_reg_reg_con );
+ format %{ "FLD $src\n\t"
+ "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fmul_s($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_reg_con);
%}
@@ -12939,16 +12961,11 @@ instruct maxI_eReg(eRegI dst, eRegI src, eFlagsReg flags) %{
instruct jumpXtnd(eRegI switch_val) %{
match(Jump switch_val);
ins_cost(350);
-
- format %{ "JMP [table_base](,$switch_val,1)\n\t" %}
-
+ format %{ "JMP [$constantaddress](,$switch_val,1)\n\t" %}
ins_encode %{
- address table_base = __ address_table_constant(_index2label);
-
// Jump to Address(table_base + switch_reg)
- InternalAddress table(table_base);
Address index(noreg, $switch_val$$Register, Address::times_1);
- __ jump(ArrayAddress(table, index));
+ __ jump(ArrayAddress($constantaddress, index));
%}
ins_pc_relative(1);
ins_pipe(pipe_jmp);
diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad
index 8f6912307bf..e007ce96cc8 100644
--- a/hotspot/src/cpu/x86/vm/x86_64.ad
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad
@@ -832,6 +832,25 @@ void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) {
}
+//=============================================================================
+const bool Matcher::constant_table_absolute_addressing = true;
+const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+ // Empty encoding
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
+ return 0;
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+ st->print("# MachConstantBaseNode (empty encoding)");
+}
+#endif
+
+
//=============================================================================
#ifndef PRODUCT
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const
@@ -1922,28 +1941,6 @@ int emit_deopt_handler(CodeBuffer& cbuf)
return offset;
}
-static void emit_double_constant(CodeBuffer& cbuf, double x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address double_address = __ double_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int) (double_address - cbuf.insts_end() - 4),
- internal_word_Relocation::spec(double_address),
- RELOC_DISP32);
-}
-
-static void emit_float_constant(CodeBuffer& cbuf, float x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address float_address = __ float_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int) (float_address - cbuf.insts_end() - 4),
- internal_word_Relocation::spec(float_address),
- RELOC_DISP32);
-}
-
const bool Matcher::match_rule_supported(int opcode) {
if (!has_match_rule(opcode))
@@ -2789,43 +2786,6 @@ encode %{
}
%}
- enc_class load_immF(regF dst, immF con)
- %{
- // XXX reg_mem doesn't support RIP-relative addressing yet
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_float_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_immD(regD dst, immD con)
- %{
- // XXX reg_mem doesn't support RIP-relative addressing yet
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_double_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_conF (regF dst, immF con) %{ // Load float constant
- emit_opcode(cbuf, 0xF3);
- if ($dst$$reg >= 8) {
- emit_opcode(cbuf, Assembler::REX_R);
- }
- emit_opcode(cbuf, 0x0F);
- emit_opcode(cbuf, 0x10);
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_float_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_conD (regD dst, immD con) %{ // Load double constant
- // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
- if ($dst$$reg >= 8) {
- emit_opcode(cbuf, Assembler::REX_R);
- }
- emit_opcode(cbuf, 0x0F);
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_double_constant(cbuf, $con$$constant);
- %}
-
// Encode a reg-reg copy. If it is useless, then empty encoding.
enc_class enc_copy(rRegI dst, rRegI src)
%{
@@ -2926,63 +2886,6 @@ encode %{
emit_d32(cbuf, 0x00);
%}
- enc_class jump_enc(rRegL switch_val, rRegI dest) %{
- MacroAssembler masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register dest_reg = as_Register($dest$$reg);
- address table_base = masm.address_table_constant(_index2label);
-
- // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
- // to do that and the compiler is using that register as one it can allocate.
- // So we build it all by hand.
- // Address index(noreg, switch_reg, Address::times_1);
- // ArrayAddress dispatch(table, index);
-
- Address dispatch(dest_reg, switch_reg, Address::times_1);
-
- masm.lea(dest_reg, InternalAddress(table_base));
- masm.jmp(dispatch);
- %}
-
- enc_class jump_enc_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{
- MacroAssembler masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register dest_reg = as_Register($dest$$reg);
- address table_base = masm.address_table_constant(_index2label);
-
- // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
- // to do that and the compiler is using that register as one it can allocate.
- // So we build it all by hand.
- // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
- // ArrayAddress dispatch(table, index);
-
- Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
-
- masm.lea(dest_reg, InternalAddress(table_base));
- masm.jmp(dispatch);
- %}
-
- enc_class jump_enc_offset(rRegL switch_val, immI2 shift, rRegI dest) %{
- MacroAssembler masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register dest_reg = as_Register($dest$$reg);
- address table_base = masm.address_table_constant(_index2label);
-
- // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
- // to do that and the compiler is using that register as one it can allocate.
- // So we build it all by hand.
- // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
- // ArrayAddress dispatch(table, index);
-
- Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant);
- masm.lea(dest_reg, InternalAddress(table_base));
- masm.jmp(dispatch);
-
- %}
-
enc_class lock_prefix()
%{
if (os::is_MP()) {
@@ -6641,12 +6544,11 @@ instruct loadConL32(rRegL dst, immL32 src)
ins_pipe(ialu_reg);
%}
-instruct loadConP(rRegP dst, immP src)
-%{
- match(Set dst src);
+instruct loadConP(rRegP dst, immP con) %{
+ match(Set dst con);
- format %{ "movq $dst, $src\t# ptr" %}
- ins_encode(load_immP(dst, src));
+ format %{ "movq $dst, $con\t# ptr" %}
+ ins_encode(load_immP(dst, con));
ins_pipe(ialu_reg_fat); // XXX
%}
@@ -6673,13 +6575,13 @@ instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
ins_pipe(ialu_reg);
%}
-instruct loadConF(regF dst, immF src)
-%{
- match(Set dst src);
+instruct loadConF(regF dst, immF con) %{
+ match(Set dst con);
ins_cost(125);
-
- format %{ "movss $dst, [$src]" %}
- ins_encode(load_conF(dst, src));
+ format %{ "movss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ movflt($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -6721,13 +6623,13 @@ instruct loadConF0(regF dst, immF0 src)
%}
// Use the same format since predicate() can not be used here.
-instruct loadConD(regD dst, immD src)
-%{
- match(Set dst src);
+instruct loadConD(regD dst, immD con) %{
+ match(Set dst con);
ins_cost(125);
-
- format %{ "movsd $dst, [$src]" %}
- ins_encode(load_conD(dst, src));
+ format %{ "movsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ movdbl($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -7694,9 +7596,18 @@ instruct jumpXtnd_offset(rRegL switch_val, immI2 shift, rRegI dest) %{
predicate(false);
effect(TEMP dest);
- format %{ "leaq $dest, table_base\n\t"
+ format %{ "leaq $dest, [$constantaddress]\n\t"
"jmp [$dest + $switch_val << $shift]\n\t" %}
- ins_encode(jump_enc_offset(switch_val, shift, dest));
+ ins_encode %{
+ // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+ // to do that and the compiler is using that register as one it can allocate.
+ // So we build it all by hand.
+ // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
+ // ArrayAddress dispatch(table, index);
+ Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant);
+ __ lea($dest$$Register, $constantaddress);
+ __ jmp(dispatch);
+ %}
ins_pipe(pipe_jmp);
ins_pc_relative(1);
%}
@@ -7706,9 +7617,18 @@ instruct jumpXtnd_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest)
ins_cost(350);
effect(TEMP dest);
- format %{ "leaq $dest, table_base\n\t"
+ format %{ "leaq $dest, [$constantaddress]\n\t"
"jmp [$dest + $switch_val << $shift + $offset]\n\t" %}
- ins_encode(jump_enc_addr(switch_val, shift, offset, dest));
+ ins_encode %{
+ // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+ // to do that and the compiler is using that register as one it can allocate.
+ // So we build it all by hand.
+ // Address index(noreg, switch_reg, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
+ // ArrayAddress dispatch(table, index);
+ Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
+ __ lea($dest$$Register, $constantaddress);
+ __ jmp(dispatch);
+ %}
ins_pipe(pipe_jmp);
ins_pc_relative(1);
%}
@@ -7718,9 +7638,18 @@ instruct jumpXtnd(rRegL switch_val, rRegI dest) %{
ins_cost(350);
effect(TEMP dest);
- format %{ "leaq $dest, table_base\n\t"
+ format %{ "leaq $dest, [$constantaddress]\n\t"
"jmp [$dest + $switch_val]\n\t" %}
- ins_encode(jump_enc(switch_val, dest));
+ ins_encode %{
+ // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+ // to do that and the compiler is using that register as one it can allocate.
+ // So we build it all by hand.
+ // Address index(noreg, switch_reg, Address::times_1);
+ // ArrayAddress dispatch(table, index);
+ Address dispatch($dest$$Register, $switch_val$$Register, Address::times_1);
+ __ lea($dest$$Register, $constantaddress);
+ __ jmp(dispatch);
+ %}
ins_pipe(pipe_jmp);
ins_pc_relative(1);
%}
@@ -10376,30 +10305,36 @@ instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{
ins_pipe(pipe_slow);
%}
-instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2)
-%{
- match(Set cr (CmpF src1 src2));
+instruct cmpF_cc_imm(rFlagsRegU cr, regF src, immF con) %{
+ match(Set cr (CmpF src con));
ins_cost(145);
- format %{ "ucomiss $src1, $src2\n\t"
+ format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
"jnp,s exit\n\t"
"pushfq\t# saw NaN, set CF\n\t"
"andq [rsp], #0xffffff2b\n\t"
"popfq\n"
"exit: nop\t# avoid branch to branch" %}
- opcode(0x0F, 0x2E);
- ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2),
- cmpfp_fixup);
+ ins_encode %{
+ Label L_exit;
+ __ ucomiss($src$$XMMRegister, $constantaddress($con));
+ __ jcc(Assembler::noParity, L_exit);
+ __ pushf();
+ __ andq(rsp, 0xffffff2b);
+ __ popf();
+ __ bind(L_exit);
+ __ nop();
+ %}
ins_pipe(pipe_slow);
%}
-instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{
- match(Set cr (CmpF src1 src2));
-
+instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{
+ match(Set cr (CmpF src con));
ins_cost(100);
- format %{ "ucomiss $src1, $src2" %}
- opcode(0x0F, 0x2E);
- ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2));
+ format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ ucomiss($src$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10458,30 +10393,36 @@ instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{
ins_pipe(pipe_slow);
%}
-instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2)
-%{
- match(Set cr (CmpD src1 src2));
+instruct cmpD_cc_imm(rFlagsRegU cr, regD src, immD con) %{
+ match(Set cr (CmpD src con));
ins_cost(145);
- format %{ "ucomisd $src1, [$src2]\n\t"
+ format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
"jnp,s exit\n\t"
"pushfq\t# saw NaN, set CF\n\t"
"andq [rsp], #0xffffff2b\n\t"
"popfq\n"
"exit: nop\t# avoid branch to branch" %}
- opcode(0x66, 0x0F, 0x2E);
- ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2),
- cmpfp_fixup);
+ ins_encode %{
+ Label L_exit;
+ __ ucomisd($src$$XMMRegister, $constantaddress($con));
+ __ jcc(Assembler::noParity, L_exit);
+ __ pushf();
+ __ andq(rsp, 0xffffff2b);
+ __ popf();
+ __ bind(L_exit);
+ __ nop();
+ %}
ins_pipe(pipe_slow);
%}
-instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{
- match(Set cr (CmpD src1 src2));
-
+instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{
+ match(Set cr (CmpD src con));
ins_cost(100);
- format %{ "ucomisd $src1, [$src2]" %}
- opcode(0x66, 0x0F, 0x2E);
- ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2));
+ format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ ucomisd($src$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10528,23 +10469,29 @@ instruct cmpF_mem(rRegI dst, regF src1, memory src2, rFlagsReg cr)
%}
// Compare into -1,0,1
-instruct cmpF_imm(rRegI dst, regF src1, immF src2, rFlagsReg cr)
-%{
- match(Set dst (CmpF3 src1 src2));
+instruct cmpF_imm(rRegI dst, regF src, immF con, rFlagsReg cr) %{
+ match(Set dst (CmpF3 src con));
effect(KILL cr);
ins_cost(275);
- format %{ "ucomiss $src1, [$src2]\n\t"
+ format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
"movl $dst, #-1\n\t"
"jp,s done\n\t"
"jb,s done\n\t"
"setne $dst\n\t"
"movzbl $dst, $dst\n"
"done:" %}
-
- opcode(0x0F, 0x2E);
- ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2),
- cmpfp3(dst));
+ ins_encode %{
+ Label L_done;
+ Register Rdst = $dst$$Register;
+ __ ucomiss($src$$XMMRegister, $constantaddress($con));
+ __ movl(Rdst, -1);
+ __ jcc(Assembler::parity, L_done);
+ __ jcc(Assembler::below, L_done);
+ __ setb(Assembler::notEqual, Rdst);
+ __ movzbl(Rdst, Rdst);
+ __ bind(L_done);
+ %}
ins_pipe(pipe_slow);
%}
@@ -10591,23 +10538,29 @@ instruct cmpD_mem(rRegI dst, regD src1, memory src2, rFlagsReg cr)
%}
// Compare into -1,0,1
-instruct cmpD_imm(rRegI dst, regD src1, immD src2, rFlagsReg cr)
-%{
- match(Set dst (CmpD3 src1 src2));
+instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{
+ match(Set dst (CmpD3 src con));
effect(KILL cr);
ins_cost(275);
- format %{ "ucomisd $src1, [$src2]\n\t"
+ format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
"movl $dst, #-1\n\t"
"jp,s done\n\t"
"jb,s done\n\t"
"setne $dst\n\t"
"movzbl $dst, $dst\n"
"done:" %}
-
- opcode(0x66, 0x0F, 0x2E);
- ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2),
- cmpfp3(dst));
+ ins_encode %{
+ Register Rdst = $dst$$Register;
+ Label L_done;
+ __ ucomisd($src$$XMMRegister, $constantaddress($con));
+ __ movl(Rdst, -1);
+ __ jcc(Assembler::parity, L_done);
+ __ jcc(Assembler::below, L_done);
+ __ setb(Assembler::notEqual, Rdst);
+ __ movzbl(Rdst, Rdst);
+ __ bind(L_done);
+ %}
ins_pipe(pipe_slow);
%}
@@ -10633,14 +10586,13 @@ instruct addF_mem(regF dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct addF_imm(regF dst, immF src)
-%{
- match(Set dst (AddF dst src));
-
- format %{ "addss $dst, [$src]" %}
+instruct addF_imm(regF dst, immF con) %{
+ match(Set dst (AddF dst con));
+ format %{ "addss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x58);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ addss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10666,14 +10618,13 @@ instruct addD_mem(regD dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct addD_imm(regD dst, immD src)
-%{
- match(Set dst (AddD dst src));
-
- format %{ "addsd $dst, [$src]" %}
+instruct addD_imm(regD dst, immD con) %{
+ match(Set dst (AddD dst con));
+ format %{ "addsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x58);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ addsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10699,14 +10650,13 @@ instruct subF_mem(regF dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct subF_imm(regF dst, immF src)
-%{
- match(Set dst (SubF dst src));
-
- format %{ "subss $dst, [$src]" %}
+instruct subF_imm(regF dst, immF con) %{
+ match(Set dst (SubF dst con));
+ format %{ "subss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x5C);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ subss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10732,14 +10682,13 @@ instruct subD_mem(regD dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct subD_imm(regD dst, immD src)
-%{
- match(Set dst (SubD dst src));
-
- format %{ "subsd $dst, [$src]" %}
+instruct subD_imm(regD dst, immD con) %{
+ match(Set dst (SubD dst con));
+ format %{ "subsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x5C);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ subsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10765,14 +10714,13 @@ instruct mulF_mem(regF dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct mulF_imm(regF dst, immF src)
-%{
- match(Set dst (MulF dst src));
-
- format %{ "mulss $dst, [$src]" %}
+instruct mulF_imm(regF dst, immF con) %{
+ match(Set dst (MulF dst con));
+ format %{ "mulss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x59);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ mulss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10798,14 +10746,13 @@ instruct mulD_mem(regD dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct mulD_imm(regD dst, immD src)
-%{
- match(Set dst (MulD dst src));
-
- format %{ "mulsd $dst, [$src]" %}
+instruct mulD_imm(regD dst, immD con) %{
+ match(Set dst (MulD dst con));
+ format %{ "mulsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x59);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ mulsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10831,14 +10778,13 @@ instruct divF_mem(regF dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct divF_imm(regF dst, immF src)
-%{
- match(Set dst (DivF dst src));
-
- format %{ "divss $dst, [$src]" %}
+instruct divF_imm(regF dst, immF con) %{
+ match(Set dst (DivF dst con));
+ format %{ "divss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x5E);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ divss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10864,14 +10810,13 @@ instruct divD_mem(regD dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct divD_imm(regD dst, immD src)
-%{
- match(Set dst (DivD dst src));
-
- format %{ "divsd $dst, [$src]" %}
+instruct divD_imm(regD dst, immD con) %{
+ match(Set dst (DivD dst con));
+ format %{ "divsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x5E);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ divsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10897,14 +10842,13 @@ instruct sqrtF_mem(regF dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct sqrtF_imm(regF dst, immF src)
-%{
- match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
-
- format %{ "sqrtss $dst, [$src]" %}
+instruct sqrtF_imm(regF dst, immF con) %{
+ match(Set dst (ConvD2F (SqrtD (ConvF2D con))));
+ format %{ "sqrtss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x51);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ sqrtss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10930,14 +10874,13 @@ instruct sqrtD_mem(regD dst, memory src)
ins_pipe(pipe_slow);
%}
-instruct sqrtD_imm(regD dst, immD src)
-%{
- match(Set dst (SqrtD src));
-
- format %{ "sqrtsd $dst, [$src]" %}
+instruct sqrtD_imm(regD dst, immD con) %{
+ match(Set dst (SqrtD con));
+ format %{ "sqrtsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x51);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ sqrtsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index 8700d10bee0..330e347a7e5 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -115,6 +115,7 @@
# include
# include
# include
+# include
#define MAX_PATH (2 * K)
@@ -4433,6 +4434,15 @@ int os::available(int fd, jlong *bytes) {
return 1;
}
+int os::socket_available(int fd, jint *pbytes) {
+ // Linux doc says EINTR not returned, unlike Solaris
+ int ret = ::ioctl(fd, FIONREAD, pbytes);
+
+ //%% note ioctl can return 0 when successful, JVM_SocketAvailable
+ // is expected to return 0 on failure and 1 on success to the jdk.
+ return (ret < 0) ? 0 : 1;
+}
+
// Map a block of memory.
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp
index 6e52d108fb8..9af7e789764 100644
--- a/hotspot/src/os/linux/vm/os_linux.inline.hpp
+++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp
@@ -45,7 +45,6 @@
#include
#include
#include
-#include
#include
inline void* os::thread_local_storage_at(int index) {
@@ -268,16 +267,6 @@ inline int os::sendto(int fd, char *buf, int len, int flags,
RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen));
}
-inline int os::socket_available(int fd, jint *pbytes) {
- // Linux doc says EINTR not returned, unlike Solaris
- int ret = ::ioctl(fd, FIONREAD, pbytes);
-
- //%% note ioctl can return 0 when successful, JVM_SocketAvailable
- // is expected to return 0 on failure and 1 on success to the jdk.
- return (ret < 0) ? 0 : 1;
-}
-
-
inline int os::socket_shutdown(int fd, int howto){
return ::shutdown(fd, howto);
}
diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
index db5340f9d7c..1cd430cfbc7 100644
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
@@ -635,7 +635,29 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1;
}
- return fd;
+ // Verify that we have enough disk space for this file.
+ // We'll get random SIGBUS crashes on memory accesses if
+ // we don't.
+
+ for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) {
+ int zero_int = 0;
+ result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
+ if (result == -1 ) break;
+ RESTARTABLE(::write(fd, &zero_int, 1), result);
+ if (result != 1) {
+ if (errno == ENOSPC) {
+ warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
+ }
+ break;
+ }
+ }
+
+ if (result != -1) {
+ return fd;
+ } else {
+ RESTARTABLE(::close(fd), result);
+ return -1;
+ }
}
// open the shared memory file for the given user and vmid. returns
diff --git a/hotspot/src/os/linux/vm/vmError_linux.cpp b/hotspot/src/os/linux/vm/vmError_linux.cpp
index 578ef7c8692..8ec6ca04c25 100644
--- a/hotspot/src/os/linux/vm/vmError_linux.cpp
+++ b/hotspot/src/os/linux/vm/vmError_linux.cpp
@@ -44,11 +44,11 @@ void VMError::show_message_box(char *buf, int buflen) {
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
- "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT "\n"
+ "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n"
"Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_process_id(),
- os::current_thread_id());
+ os::current_thread_id(), os::current_thread_id());
yes = os::message_box("Unexpected Error", buf);
diff --git a/hotspot/src/os/posix/launcher/java_md.c b/hotspot/src/os/posix/launcher/java_md.c
index dd45278f2b5..3ee0f20a77d 100644
--- a/hotspot/src/os/posix/launcher/java_md.c
+++ b/hotspot/src/os/posix/launcher/java_md.c
@@ -812,13 +812,10 @@ GetApplicationHome(char *buf, jint bufsize)
#ifdef GAMMA
{
- /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */
- char* java_home_var = getenv("ALT_JAVA_HOME");
+ /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */
+ char* java_home_var = getenv("JAVA_HOME");
if (java_home_var == NULL) {
- java_home_var = getenv("JAVA_HOME");
- }
- if (java_home_var == NULL) {
- printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
+ printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
return JNI_FALSE;
}
snprintf(buf, bufsize, "%s", java_home_var);
@@ -1837,7 +1834,7 @@ ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void
if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
void * tmp;
pthread_join(tid, &tmp);
- rslt = (int)tmp;
+ rslt = (int)(intptr_t)tmp;
} else {
/*
* Continue execution in current thread if for some reason (e.g. out of
@@ -1855,7 +1852,7 @@ ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void
if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) {
void * tmp;
thr_join(tid, NULL, &tmp);
- rslt = (int)tmp;
+ rslt = (int)(intptr_t)tmp;
} else {
/* See above. Continue in current thread if thr_create() failed */
rslt = continuation(args);
diff --git a/hotspot/src/os/posix/launcher/launcher.script b/hotspot/src/os/posix/launcher/launcher.script
index 6eae75a3de2..22ed66b9c2f 100644
--- a/hotspot/src/os/posix/launcher/launcher.script
+++ b/hotspot/src/os/posix/launcher/launcher.script
@@ -95,17 +95,21 @@ case "$1" in
;;
esac
+# Find out the absolute path to this script
+MYDIR=$(cd $(dirname $SCRIPT) && pwd)
+
+JDK=
if [ "${ALT_JAVA_HOME}" = "" ]; then
- if [ "${JAVA_HOME}" = "" ]; then
- echo "Neither ALT_JAVA_HOME nor JAVA_HOME is set. Aborting.";
- exit 1;
- else
- JDK=${JAVA_HOME%%/jre};
- fi
+ source ${MYDIR}/jdkpath.sh
else
JDK=${ALT_JAVA_HOME%%/jre};
fi
+if [ "${JDK}" = "" ]; then
+ echo Failed to find JDK. ALT_JAVA_HOME is not set or ./jdkpath.sh is empty or not found.
+ exit 1
+fi
+
# We will set the LD_LIBRARY_PATH as follows:
# o $JVMPATH (directory portion only)
# o $JRE/lib/$ARCH
diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp
index 0141763216a..7b08e979d2f 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp
@@ -80,6 +80,7 @@
// put OS-includes here
# include
# include
+# include
# include
# include
# include
@@ -1475,6 +1476,13 @@ sigset_t* os::Solaris::allowdebug_blocked_signals() {
return &allowdebug_blocked_sigs;
}
+
+void _handle_uncaught_cxx_exception() {
+ VMError err("An uncaught C++ exception");
+ err.report_and_die();
+}
+
+
// First crack at OS-specific initialization, from inside the new thread.
void os::initialize_thread() {
int r = thr_main() ;
@@ -1564,6 +1572,7 @@ void os::initialize_thread() {
// use the dynamic check for T2 libthread.
os::Solaris::init_thread_fpu_state();
+ std::set_terminate(_handle_uncaught_cxx_exception);
}
diff --git a/hotspot/src/os/windows/launcher/java_md.c b/hotspot/src/os/windows/launcher/java_md.c
index 715be6cd0f5..2fde40ad205 100644
--- a/hotspot/src/os/windows/launcher/java_md.c
+++ b/hotspot/src/os/windows/launcher/java_md.c
@@ -22,6 +22,7 @@
*
*/
+#include
#include
#include
#include
@@ -486,16 +487,62 @@ GetApplicationHome(char *buf, jint bufsize)
#else /* ifndef GAMMA */
- /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */
- char* java_home_var = getenv("ALT_JAVA_HOME");
- if (java_home_var == NULL) {
- java_home_var = getenv("JAVA_HOME");
+ char env[MAXPATHLEN + 1];
+
+ /* gamma launcher uses ALT_JAVA_HOME environment variable or jdkpath.txt file to find JDK/JRE */
+
+ if (getenv("ALT_JAVA_HOME") != NULL) {
+ snprintf(buf, bufsize, "%s", getenv("ALT_JAVA_HOME"));
}
- if (java_home_var == NULL) {
- printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
- return JNI_FALSE;
+ else {
+ char path[MAXPATHLEN + 1];
+ char* p;
+ int len;
+ FILE* fp;
+
+ // find the path to the currect executable
+ len = GetModuleFileName(NULL, path, MAXPATHLEN + 1);
+ if (len == 0 || len > MAXPATHLEN) {
+ printf("Could not get directory of current executable.");
+ return JNI_FALSE;
+ }
+ // remove last path component ("hotspot.exe")
+ p = strrchr(path, '\\');
+ if (p == NULL) {
+ printf("Could not parse directory of current executable.\n");
+ return JNI_FALSE;
+ }
+ *p = '\0';
+
+ // open jdkpath.txt and read JAVA_HOME from it
+ if (strlen(path) + strlen("\\jdkpath.txt") + 1 >= MAXPATHLEN) {
+ printf("Path too long: %s\n", path);
+ return JNI_FALSE;
+ }
+ strcat(path, "\\jdkpath.txt");
+ fp = fopen(path, "r");
+ if (fp == NULL) {
+ printf("Could not open file %s to get path to JDK.\n", path);
+ return JNI_FALSE;
+ }
+
+ if (fgets(buf, bufsize, fp) == NULL) {
+ printf("Could not read from file %s to get path to JDK.\n", path);
+ fclose(fp);
+ return JNI_FALSE;
+ }
+ // trim the buffer
+ p = buf + strlen(buf) - 1;
+ while(isspace(*p)) {
+ *p = '\0';
+ p--;
+ }
+ fclose(fp);
}
- snprintf(buf, bufsize, "%s", java_home_var);
+
+ _snprintf(env, MAXPATHLEN, "JAVA_HOME=%s", buf);
+ _putenv(env);
+
return JNI_TRUE;
#endif /* ifndef GAMMA */
}
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 1cc90f7b642..0422063c50e 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * CopyrighT (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1711,14 +1711,11 @@ void os::jvm_path(char *buf, jint buflen) {
buf[0] = '\0';
if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) {
// Support for the gamma launcher. Check for an
- // ALT_JAVA_HOME or JAVA_HOME environment variable
+ // JAVA_HOME environment variable
// and fix up the path so it looks like
// libjvm.so is installed there (append a fake suffix
// hotspot/libjvm.so).
- char* java_home_var = ::getenv("ALT_JAVA_HOME");
- if (java_home_var == NULL) {
- java_home_var = ::getenv("JAVA_HOME");
- }
+ char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != NULL && java_home_var[0] != 0) {
strncpy(buf, java_home_var, buflen);
@@ -2007,6 +2004,16 @@ struct siglabel {
int number;
};
+// All Visual C++ exceptions thrown from code generated by the Microsoft Visual
+// C++ compiler contain this error code. Because this is a compiler-generated
+// error, the code is not listed in the Win32 API header files.
+// The code is actually a cryptic mnemonic device, with the initial "E"
+// standing for "exception" and the final 3 bytes (0x6D7363) representing the
+// ASCII values of "msc".
+
+#define EXCEPTION_UNCAUGHT_CXX_EXCEPTION 0xE06D7363
+
+
struct siglabel exceptlabels[] = {
def_excpt(EXCEPTION_ACCESS_VIOLATION),
def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT),
@@ -2031,6 +2038,7 @@ struct siglabel exceptlabels[] = {
def_excpt(EXCEPTION_INVALID_DISPOSITION),
def_excpt(EXCEPTION_GUARD_PAGE),
def_excpt(EXCEPTION_INVALID_HANDLE),
+ def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION),
NULL, 0
};
@@ -2264,7 +2272,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
}
-
if (t != NULL && t->is_Java_thread()) {
JavaThread* thread = (JavaThread*) t;
bool in_java = thread->thread_state() == _thread_in_Java;
@@ -2468,8 +2475,9 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
} // switch
}
#ifndef _WIN64
- if ((thread->thread_state() == _thread_in_Java) ||
- (thread->thread_state() == _thread_in_native) )
+ if (((thread->thread_state() == _thread_in_Java) ||
+ (thread->thread_state() == _thread_in_native)) &&
+ exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION)
{
LONG result=Handle_FLT_Exception(exceptionInfo);
if (result==EXCEPTION_CONTINUE_EXECUTION) return result;
@@ -2493,6 +2501,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
case EXCEPTION_ILLEGAL_INSTRUCTION_2:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ case EXCEPTION_UNCAUGHT_CXX_EXCEPTION:
{ report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
exceptionInfo->ContextRecord);
}
diff --git a/hotspot/src/share/tools/ProjectCreator/BuildConfig.java b/hotspot/src/share/tools/ProjectCreator/BuildConfig.java
index 7a2a03c7842..6e97b28f1e6 100644
--- a/hotspot/src/share/tools/ProjectCreator/BuildConfig.java
+++ b/hotspot/src/share/tools/ProjectCreator/BuildConfig.java
@@ -22,8 +22,11 @@
*
*/
-import java.util.*;
import java.io.File;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
class BuildConfig {
Hashtable vars;
@@ -57,7 +60,6 @@ class BuildConfig {
// ones mentioned above were needed to expand format
String buildBase = expandFormat(getFieldString(null, "BuildBase"));
- String jdkDir = getFieldString(null, "JdkTargetRoot");
String sourceBase = getFieldString(null, "SourceBase");
String outDir = buildBase;
@@ -65,7 +67,7 @@ class BuildConfig {
put("OutputDir", outDir);
put("SourceBase", sourceBase);
put("BuildBase", buildBase);
- put("OutputDll", jdkDir + Util.sep + outDll);
+ put("OutputDll", outDir + Util.sep + outDll);
context = new String [] {flavourBuild, flavour, build, null};
}
@@ -537,68 +539,75 @@ abstract class GenericDebugConfig extends BuildConfig {
}
}
-class C1DebugConfig extends GenericDebugConfig {
+abstract class GenericDebugNonKernelConfig extends GenericDebugConfig {
+ protected void init(Vector includes, Vector defines) {
+ super.init(includes, defines);
+ getCI().getAdditionalNonKernelLinkerFlags(getV("LinkerFlags"));
+ }
+}
+
+class C1DebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getNoOptFlag();
}
C1DebugConfig() {
- initNames("compiler1", "debug", "fastdebug\\jre\\bin\\client\\jvm.dll");
+ initNames("compiler1", "debug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
-class C1FastDebugConfig extends GenericDebugConfig {
+class C1FastDebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getOptFlag();
}
C1FastDebugConfig() {
- initNames("compiler1", "fastdebug", "fastdebug\\jre\\bin\\client\\jvm.dll");
+ initNames("compiler1", "fastdebug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
-class C2DebugConfig extends GenericDebugConfig {
+class C2DebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getNoOptFlag();
}
C2DebugConfig() {
- initNames("compiler2", "debug", "fastdebug\\jre\\bin\\server\\jvm.dll");
+ initNames("compiler2", "debug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
-class C2FastDebugConfig extends GenericDebugConfig {
+class C2FastDebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getOptFlag();
}
C2FastDebugConfig() {
- initNames("compiler2", "fastdebug", "fastdebug\\jre\\bin\\server\\jvm.dll");
+ initNames("compiler2", "fastdebug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
-class TieredDebugConfig extends GenericDebugConfig {
+class TieredDebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getNoOptFlag();
}
TieredDebugConfig() {
- initNames("tiered", "debug", "fastdebug\\jre\\bin\\server\\jvm.dll");
+ initNames("tiered", "debug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
-class TieredFastDebugConfig extends GenericDebugConfig {
+class TieredFastDebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getOptFlag();
}
TieredFastDebugConfig() {
- initNames("tiered", "fastdebug", "fastdebug\\jre\\bin\\server\\jvm.dll");
+ initNames("tiered", "fastdebug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
@@ -618,45 +627,45 @@ abstract class ProductConfig extends BuildConfig {
class C1ProductConfig extends ProductConfig {
C1ProductConfig() {
- initNames("compiler1", "product", "jre\\bin\\client\\jvm.dll");
+ initNames("compiler1", "product", "jvm.dll");
init(getIncludes(), getDefines());
}
}
class C2ProductConfig extends ProductConfig {
C2ProductConfig() {
- initNames("compiler2", "product", "jre\\bin\\server\\jvm.dll");
+ initNames("compiler2", "product", "jvm.dll");
init(getIncludes(), getDefines());
}
}
class TieredProductConfig extends ProductConfig {
TieredProductConfig() {
- initNames("tiered", "product", "jre\\bin\\server\\jvm.dll");
+ initNames("tiered", "product", "jvm.dll");
init(getIncludes(), getDefines());
}
}
-class CoreDebugConfig extends GenericDebugConfig {
+class CoreDebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getNoOptFlag();
}
CoreDebugConfig() {
- initNames("core", "debug", "fastdebug\\jre\\bin\\core\\jvm.dll");
+ initNames("core", "debug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
-class CoreFastDebugConfig extends GenericDebugConfig {
+class CoreFastDebugConfig extends GenericDebugNonKernelConfig {
String getOptFlag() {
return getCI().getOptFlag();
}
CoreFastDebugConfig() {
- initNames("core", "fastdebug", "fastdebug\\jre\\bin\\core\\jvm.dll");
+ initNames("core", "fastdebug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
@@ -664,7 +673,7 @@ class CoreFastDebugConfig extends GenericDebugConfig {
class CoreProductConfig extends ProductConfig {
CoreProductConfig() {
- initNames("core", "product", "jre\\bin\\core\\jvm.dll");
+ initNames("core", "product", "jvm.dll");
init(getIncludes(), getDefines());
}
}
@@ -675,7 +684,7 @@ class KernelDebugConfig extends GenericDebugConfig {
}
KernelDebugConfig() {
- initNames("kernel", "debug", "fastdebug\\jre\\bin\\kernel\\jvm.dll");
+ initNames("kernel", "debug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
@@ -687,7 +696,7 @@ class KernelFastDebugConfig extends GenericDebugConfig {
}
KernelFastDebugConfig() {
- initNames("kernel", "fastdebug", "fastdebug\\jre\\bin\\kernel\\jvm.dll");
+ initNames("kernel", "fastdebug", "jvm.dll");
init(getIncludes(), getDefines());
}
}
@@ -695,7 +704,7 @@ class KernelFastDebugConfig extends GenericDebugConfig {
class KernelProductConfig extends ProductConfig {
KernelProductConfig() {
- initNames("kernel", "product", "jre\\bin\\kernel\\jvm.dll");
+ initNames("kernel", "product", "jvm.dll");
init(getIncludes(), getDefines());
}
}
@@ -704,6 +713,7 @@ abstract class CompilerInterface {
abstract Vector getBaseLinkerFlags(String outDir, String outDll);
abstract Vector getDebugCompilerFlags(String opt);
abstract Vector getDebugLinkerFlags();
+ abstract void getAdditionalNonKernelLinkerFlags(Vector rv);
abstract Vector getProductCompilerFlags();
abstract Vector getProductLinkerFlags();
abstract String getOptFlag();
@@ -713,4 +723,14 @@ abstract class CompilerInterface {
void addAttr(Vector receiver, String attr, String value) {
receiver.add(attr); receiver.add(value);
}
+ void extAttr(Vector receiver, String attr, String value) {
+ int attr_pos=receiver.indexOf(attr) ;
+ if ( attr_pos == -1) {
+ // If attr IS NOT present in the Vector - add it
+ receiver.add(attr); receiver.add(value);
+ } else {
+ // If attr IS present in the Vector - append value to it
+ receiver.set(attr_pos+1,receiver.get(attr_pos+1)+value);
+ }
+ }
}
diff --git a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatform.java b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatform.java
index ece6b1252c1..a2416f50be7 100644
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatform.java
+++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatform.java
@@ -22,8 +22,15 @@
*
*/
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+import java.util.Vector;
abstract class HsArgHandler extends ArgHandler {
static final int STRING = 1;
@@ -345,11 +352,23 @@ public abstract class WinGammaPlatform {
new ArgsParser(args,
new ArgRule[]
{
- new HsArgRule("-sourceBase",
- "SourceBase",
- " (Did you set the HotSpotWorkSpace environment variable?)",
- HsArgHandler.STRING
- ),
+ new ArgRule("-sourceBase",
+ new HsArgHandler() {
+ public void handle(ArgIterator it) {
+ String cfg = getCfg(it.get());
+ if (nextNotKey(it)) {
+ String sb = (String) it.get();
+ if (sb.endsWith(Util.sep)) {
+ sb = sb.substring(0, sb.length() - 1);
+ }
+ BuildConfig.putField(cfg, "SourceBase", sb);
+ it.next();
+ } else {
+ empty("-sourceBase", null);
+ }
+ }
+ }
+ ),
new HsArgRule("-buildBase",
"BuildBase",
@@ -512,7 +531,6 @@ public abstract class WinGammaPlatform {
new HsArgHandler() {
public void handle(ArgIterator it) {
if (nextNotKey(it)) {
- String build = it.get();
if (nextNotKey(it)) {
String description = it.get();
if (nextNotKey(it)) {
@@ -528,7 +546,28 @@ public abstract class WinGammaPlatform {
empty(null, "** Error: wrong number of args to -prelink");
}
}
- )
+ ),
+
+ new ArgRule("-postbuild",
+ new HsArgHandler() {
+ public void handle(ArgIterator it) {
+ if (nextNotKey(it)) {
+ if (nextNotKey(it)) {
+ String description = it.get();
+ if (nextNotKey(it)) {
+ String command = it.get();
+ BuildConfig.putField(null, "PostbuildDescription", description);
+ BuildConfig.putField(null, "PostbuildCommand", command);
+ it.next();
+ return;
+ }
+ }
+ }
+
+ empty(null, "** Error: wrong number of args to -postbuild");
+ }
+ }
+ ),
},
new ArgHandler() {
public void handle(ArgIterator it) {
@@ -618,10 +657,6 @@ public abstract class WinGammaPlatform {
public int compareTo(Object o) {
FileInfo oo = (FileInfo)o;
- // Don't squelch identical short file names where the full
- // paths are different
- if (!attr.shortName.equals(oo.attr.shortName))
- return attr.shortName.compareTo(oo.attr.shortName);
return full.compareTo(oo.full);
}
diff --git a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java
index fb64f7b9275..6e59d78673b 100644
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java
+++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java
@@ -260,6 +260,8 @@ class CompilerInterfaceVC6 extends CompilerInterface {
return rv;
}
+ void getAdditionalNonKernelLinkerFlags(Vector rv) {}
+
Vector getProductCompilerFlags() {
Vector rv = new Vector();
diff --git a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java
index e0545228f6c..dad8ed6d108 100644
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java
+++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java
@@ -22,8 +22,13 @@
*
*/
-import java.io.*;
-import java.util.*;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.Vector;
public class WinGammaPlatformVC7 extends WinGammaPlatform {
@@ -104,7 +109,9 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
boolean match(FileInfo fi) {
- return fi.full.regionMatches(true, baseLen, dir, 0, dirLen);
+ int lastSlashIndex = fi.full.lastIndexOf('/');
+ String fullDir = fi.full.substring(0, lastSlashIndex);
+ return fullDir.endsWith(dir);
}
}
@@ -217,65 +224,41 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
// - container filter just provides a container to group together real filters
// - real filter can select elements from the set according to some rule, put it into XML
// and remove from the list
- Vector makeFilters(TreeSet files) {
+ Vector makeFilters(TreeSet files) {
Vector rv = new Vector();
String sbase = Util.normalize(BuildConfig.getFieldString(null, "SourceBase")+"/src/");
- ContainerFilter rt = new ContainerFilter("Runtime");
- rt.add(new DirectoryFilter("share/vm/prims", sbase));
- rt.add(new DirectoryFilter("share/vm/runtime", sbase));
- rt.add(new DirectoryFilter("share/vm/oops", sbase));
- rv.add(rt);
+ String currentDir = "";
+ DirectoryFilter container = null;
+ for(FileInfo fileInfo : files) {
- ContainerFilter gc = new ContainerFilter("GC");
- gc.add(new DirectoryFilter("share/vm/memory", sbase));
- gc.add(new DirectoryFilter("share/vm/gc_interface", sbase));
+ if (!fileInfo.full.startsWith(sbase)) {
+ continue;
+ }
- ContainerFilter gc_impl = new ContainerFilter("Implementations");
- gc_impl.add(new DirectoryFilter("CMS",
- "share/vm/gc_implementation/concurrentMarkSweep",
- sbase));
- gc_impl.add(new DirectoryFilter("Parallel Scavenge",
- "share/vm/gc_implementation/parallelScavenge",
- sbase));
- gc_impl.add(new DirectoryFilter("Shared",
- "share/vm/gc_implementation/shared",
- sbase));
- // for all leftovers
- gc_impl.add(new DirectoryFilter("Misc",
- "share/vm/gc_implementation",
- sbase));
+ int lastSlash = fileInfo.full.lastIndexOf('/');
+ String dir = fileInfo.full.substring(sbase.length(), lastSlash);
+ if(dir.equals("share/vm")) {
+ // skip files directly in share/vm - should only be precompiled.hpp which is handled below
+ continue;
+ }
+ if (!dir.equals(currentDir)) {
+ currentDir = dir;
+ if (container != null) {
+ rv.add(container);
+ }
- gc.add(gc_impl);
- rv.add(gc);
-
- rv.add(new DirectoryFilter("C1", "share/vm/c1", sbase));
-
- rv.add(new DirectoryFilter("C2", "share/vm/opto", sbase));
-
- ContainerFilter comp = new ContainerFilter("Compiler Common");
- comp.add(new DirectoryFilter("share/vm/asm", sbase));
- comp.add(new DirectoryFilter("share/vm/ci", sbase));
- comp.add(new DirectoryFilter("share/vm/code", sbase));
- comp.add(new DirectoryFilter("share/vm/compiler", sbase));
- rv.add(comp);
-
- rv.add(new DirectoryFilter("Interpreter",
- "share/vm/interpreter",
- sbase));
-
- ContainerFilter misc = new ContainerFilter("Misc");
- misc.add(new DirectoryFilter("share/vm/libadt", sbase));
- misc.add(new DirectoryFilter("share/vm/services", sbase));
- misc.add(new DirectoryFilter("share/vm/utilities", sbase));
- misc.add(new DirectoryFilter("share/vm/classfile", sbase));
- rv.add(misc);
-
- rv.add(new DirectoryFilter("os_cpu", sbase));
-
- rv.add(new DirectoryFilter("cpu", sbase));
-
- rv.add(new DirectoryFilter("os", sbase));
+ // remove "share/vm/" from names
+ String name = dir;
+ if (dir.startsWith("share/vm/")) {
+ name = dir.substring("share/vm/".length(), dir.length());
+ }
+ container = new DirectoryFilter(name, dir, sbase);
+ }
+ }
+ if (container != null) {
+ rv.add(container);
+ }
ContainerFilter generated = new ContainerFilter("Generated");
ContainerFilter c1Generated = new ContainerFilter("C1");
@@ -397,7 +380,6 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
"Name", cfg,
"ExcludedFromBuild", "TRUE"
});
- tag("Tool", new String[] {"Name", "VCCLCompilerTool"});
endTag("FileConfiguration");
}
@@ -441,7 +423,11 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
tag("Tool",
new String[] {
- "Name", "VCPostBuildEventTool"
+ "Name", "VCPostBuildEventTool",
+ "Description", BuildConfig.getFieldString(null, "PostbuildDescription"),
+ //Caution: String.replace(String,String) is available from JDK5 onwards only
+ "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PostbuildCommand").replace
+ ("\t", "
"))
}
);
@@ -469,33 +455,6 @@ public class WinGammaPlatformVC7 extends WinGammaPlatform {
"Culture", "1033"
}
);
- tag("Tool",
- new String[] {
- "Name", "VCWebServiceProxyGeneratorTool"
- }
- );
-
- tag ("Tool",
- new String[] {
- "Name", "VCXMLDataGeneratorTool"
- }
- );
-
- tag("Tool",
- new String[] {
- "Name", "VCWebDeploymentTool"
- }
- );
- tag("Tool",
- new String[] {
- "Name", "VCManagedWrapperGeneratorTool"
- }
- );
- tag("Tool",
- new String[] {
- "Name", "VCAuxiliaryManagedWrapperGeneratorTool"
- }
- );
tag("Tool",
new String[] {
@@ -597,7 +556,7 @@ class CompilerInterfaceVC7 extends CompilerInterface {
addAttr(rv, "PrecompiledHeaderFile", outDir+Util.sep+"vm.pch");
addAttr(rv, "AssemblerListingLocation", outDir);
addAttr(rv, "ObjectFile", outDir+Util.sep);
- addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"vm.pdb");
+ addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"jvm.pdb");
// Set /nologo optin
addAttr(rv, "SuppressStartupBanner", "TRUE");
// Surpass the default /Tc or /Tp. 0 is compileAsDefault
@@ -631,17 +590,22 @@ class CompilerInterfaceVC7 extends CompilerInterface {
addAttr(rv, "AdditionalOptions",
"/export:JNI_GetDefaultJavaVMInitArgs " +
"/export:JNI_CreateJavaVM " +
+ "/export:JVM_FindClassFromBootLoader "+
"/export:JNI_GetCreatedJavaVMs "+
"/export:jio_snprintf /export:jio_printf "+
"/export:jio_fprintf /export:jio_vfprintf "+
- "/export:jio_vsnprintf ");
+ "/export:jio_vsnprintf "+
+ "/export:JVM_GetVersionInfo "+
+ "/export:JVM_GetThreadStateNames "+
+ "/export:JVM_GetThreadStateValues "+
+ "/export:JVM_InitAgentProperties ");
addAttr(rv, "AdditionalDependencies", "Wsock32.lib winmm.lib");
addAttr(rv, "OutputFile", outDll);
// Set /INCREMENTAL option. 1 is linkIncrementalNo
addAttr(rv, "LinkIncremental", "1");
addAttr(rv, "SuppressStartupBanner", "TRUE");
addAttr(rv, "ModuleDefinitionFile", outDir+Util.sep+"vm.def");
- addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"vm.pdb");
+ addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"jvm.pdb");
// Set /SUBSYSTEM option. 2 is subSystemWindows
addAttr(rv, "SubSystem", "2");
addAttr(rv, "BaseAddress", "0x8000000");
@@ -682,6 +646,11 @@ class CompilerInterfaceVC7 extends CompilerInterface {
return rv;
}
+ void getAdditionalNonKernelLinkerFlags(Vector rv) {
+ extAttr(rv, "AdditionalOptions",
+ "/export:AsyncGetCallTrace ");
+ }
+
void getProductCompilerFlags_common(Vector rv) {
// Set /O2 option. 2 is optimizeMaxSpeed
addAttr(rv, "Optimization", "2");
diff --git a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC8.java b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC8.java
index 21926357a3d..3980a141d3e 100644
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC8.java
+++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC8.java
@@ -22,7 +22,7 @@
*
*/
-import java.util.*;
+import java.util.Vector;
public class WinGammaPlatformVC8 extends WinGammaPlatformVC7 {
@@ -41,6 +41,9 @@ class CompilerInterfaceVC8 extends CompilerInterfaceVC7 {
// Set /EHsc- option. 0 is cppExceptionHandlingNo
addAttr(rv, "ExceptionHandling", "0");
+ // enable multi process builds
+ extAttr(rv, "AdditionalOptions", "/MP");
+
return rv;
}
diff --git a/hotspot/src/share/tools/launcher/java.c b/hotspot/src/share/tools/launcher/java.c
index f054be1702b..5ebfb9a8dc3 100644
--- a/hotspot/src/share/tools/launcher/java.c
+++ b/hotspot/src/share/tools/launcher/java.c
@@ -275,6 +275,8 @@ main(int argc, char ** argv)
jvmpath, sizeof(jvmpath),
original_argv);
+ printf("Using java runtime at: %s\n", jrepath);
+
ifn.CreateJavaVM = 0;
ifn.GetDefaultJavaVMInitArgs = 0;
diff --git a/hotspot/src/share/tools/launcher/jli_util.c b/hotspot/src/share/tools/launcher/jli_util.c
index 86987be5503..36b164e3d37 100644
--- a/hotspot/src/share/tools/launcher/jli_util.c
+++ b/hotspot/src/share/tools/launcher/jli_util.c
@@ -1,3 +1,4 @@
+
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -27,7 +28,7 @@
#include "jli_util.h"
#ifdef GAMMA
-#ifdef _WINDOWS
+#ifdef TARGET_OS_FAMILY_windows
#define strdup _strdup
#endif
#endif
diff --git a/hotspot/src/share/vm/adlc/adlparse.cpp b/hotspot/src/share/vm/adlc/adlparse.cpp
index bd37af19afe..c2d9ee0ab48 100644
--- a/hotspot/src/share/vm/adlc/adlparse.cpp
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp
@@ -95,7 +95,7 @@ void ADLParser::parse() {
if (ident == NULL) { // Empty line
continue; // Get the next line
}
- if (!strcmp(ident, "instruct")) instr_parse();
+ if (!strcmp(ident, "instruct")) instr_parse();
else if (!strcmp(ident, "operand")) oper_parse();
else if (!strcmp(ident, "opclass")) opclass_parse();
else if (!strcmp(ident, "ins_attrib")) ins_attr_parse();
@@ -216,24 +216,23 @@ void ADLParser::instr_parse(void) {
else if (!strcmp(ident, "encode")) {
parse_err(SYNERR, "Instructions specify ins_encode, not encode\n");
}
- else if (!strcmp(ident, "ins_encode"))
- instr->_insencode = ins_encode_parse(*instr);
- else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr);
- else if (!strcmp(ident, "size")) instr->_size = size_parse(instr);
- else if (!strcmp(ident, "effect")) effect_parse(instr);
- else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr);
- else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
+ else if (!strcmp(ident, "ins_encode")) ins_encode_parse(*instr);
+ else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr);
+ else if (!strcmp(ident, "size")) instr->_size = size_parse(instr);
+ else if (!strcmp(ident, "effect")) effect_parse(instr);
+ else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr);
+ else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
else if (!strcmp(ident, "constraint")) {
parse_err(SYNERR, "Instructions do not specify a constraint\n");
}
else if (!strcmp(ident, "construct")) {
parse_err(SYNERR, "Instructions do not specify a construct\n");
}
- else if (!strcmp(ident, "format")) instr->_format = format_parse();
+ else if (!strcmp(ident, "format")) instr->_format = format_parse();
else if (!strcmp(ident, "interface")) {
parse_err(SYNERR, "Instructions do not specify an interface\n");
}
- else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
+ else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
else { // Done with staticly defined parts of instruction definition
// Check identifier to see if it is the name of an attribute
const Form *form = _globalNames[ident];
@@ -323,7 +322,8 @@ void ADLParser::adjust_set_rule(InstructForm *instr) {
const char *optype2 = NULL;
// Can not have additional base operands in right side of match!
if ( ! right->base_operand( position, _globalNames, result2, name2, optype2) ) {
- assert( instr->_predicate == NULL, "ADLC does not support instruction chain rules with predicates");
+ if (instr->_predicate != NULL)
+ parse_err(SYNERR, "ADLC does not support instruction chain rules with predicates");
// Chain from input _ideal_operand_type_,
// Needed for shared roots of match-trees
ChainList *lst = (ChainList *)_AD._chainRules[optype];
@@ -935,9 +935,9 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
// (2)
// If we are at a replacement variable,
// copy it and record in EncClass
- if ( _curchar == '$' ) {
+ if (_curchar == '$') {
// Found replacement Variable
- char *rep_var = get_rep_var_ident_dup();
+ char* rep_var = get_rep_var_ident_dup();
// Add flag to _strings list indicating we should check _rep_vars
encoding->add_rep_var(rep_var);
}
@@ -2774,47 +2774,122 @@ Predicate *ADLParser::pred_parse(void) {
//------------------------------ins_encode_parse_block-------------------------
// Parse the block form of ins_encode. See ins_encode_parse for more details
-InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
+void ADLParser::ins_encode_parse_block(InstructForm& inst) {
// Create a new encoding name based on the name of the instruction
// definition, which should be unique.
- const char * prefix = "__enc_";
- char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1);
+ const char* prefix = "__ins_encode_";
+ char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
sprintf(ec_name, "%s%s", prefix, inst._ident);
assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
- EncClass *encoding = _AD._encode->add_EncClass(ec_name);
+ EncClass* encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = linenum();
// synthesize the arguments list for the enc_class from the
// arguments to the instruct definition.
- const char * param = NULL;
+ const char* param = NULL;
inst._parameters.reset();
while ((param = inst._parameters.iter()) != NULL) {
- OperandForm *opForm = (OperandForm*)inst._localNames[param];
+ OperandForm* opForm = (OperandForm*) inst._localNames[param];
encoding->add_parameter(opForm->_ident, param);
}
- // Add the prologue to create the MacroAssembler
- encoding->add_code("\n"
- " // Define a MacroAssembler instance for use by the encoding. The\n"
- " // name is chosen to match the __ idiom used for assembly in other\n"
- " // parts of hotspot and assumes the existence of the standard\n"
- " // #define __ _masm.\n"
- " MacroAssembler _masm(&cbuf);\n");
+ // Define a MacroAssembler instance for use by the encoding. The
+ // name is chosen to match the __ idiom used for assembly in other
+ // parts of hotspot and assumes the existence of the standard
+ // #define __ _masm.
+ encoding->add_code(" MacroAssembler _masm(&cbuf);\n");
// Parse the following %{ }% block
- enc_class_parse_block(encoding, ec_name);
+ ins_encode_parse_block_impl(inst, encoding, ec_name);
// Build an encoding rule which invokes the encoding rule we just
// created, passing all arguments that we received.
- InsEncode *encrule = new InsEncode(); // Encode class for instruction
- NameAndList *params = encrule->add_encode(ec_name);
+ InsEncode* encrule = new InsEncode(); // Encode class for instruction
+ NameAndList* params = encrule->add_encode(ec_name);
inst._parameters.reset();
while ((param = inst._parameters.iter()) != NULL) {
params->add_entry(param);
}
- return encrule;
+ // Set encode class of this instruction.
+ inst._insencode = encrule;
+}
+
+
+void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name) {
+ skipws_no_preproc(); // Skip leading whitespace
+ // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
+ if (_AD._adlocation_debug) {
+ encoding->add_code(get_line_string());
+ }
+
+ // Collect the parts of the encode description
+ // (1) strings that are passed through to output
+ // (2) replacement/substitution variable, preceeded by a '$'
+ while ((_curchar != '%') && (*(_ptr+1) != '}')) {
+
+ // (1)
+ // Check if there is a string to pass through to output
+ char *start = _ptr; // Record start of the next string
+ while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
+ // If at the start of a comment, skip past it
+ if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
+ skipws_no_preproc();
+ } else {
+ // ELSE advance to the next character, or start of the next line
+ next_char_or_line();
+ }
+ }
+ // If a string was found, terminate it and record in EncClass
+ if (start != _ptr) {
+ *_ptr = '\0'; // Terminate the string
+ encoding->add_code(start);
+ }
+
+ // (2)
+ // If we are at a replacement variable,
+ // copy it and record in EncClass
+ if (_curchar == '$') {
+ // Found replacement Variable
+ char* rep_var = get_rep_var_ident_dup();
+
+ // Add flag to _strings list indicating we should check _rep_vars
+ encoding->add_rep_var(rep_var);
+
+ skipws();
+
+ // Check if this instruct is a MachConstantNode.
+ if (strcmp(rep_var, "constanttablebase") == 0) {
+ // This instruct is a MachConstantNode.
+ inst.set_is_mach_constant(true);
+
+ if (_curchar == '(') {
+ parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument (only constantaddress and constantoffset)", ec_name);
+ return;
+ }
+ }
+ else if ((strcmp(rep_var, "constantaddress") == 0) ||
+ (strcmp(rep_var, "constantoffset") == 0)) {
+ // This instruct is a MachConstantNode.
+ inst.set_is_mach_constant(true);
+
+ // If the constant keyword has an argument, parse it.
+ if (_curchar == '(') constant_parse(inst);
+ }
+ }
+ } // end while part of format description
+ next_char(); // Skip '%'
+ next_char(); // Skip '}'
+
+ skipws();
+
+ if (_AD._adlocation_debug) {
+ encoding->add_code(end_line_marker());
+ }
+
+ // Debug Stuff
+ if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
}
@@ -2838,7 +2913,7 @@ InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
//
// making it more compact to take advantage of the MacroAssembler and
// placing the assembly closer to it's use by instructions.
-InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
+void ADLParser::ins_encode_parse(InstructForm& inst) {
// Parse encode class name
skipws(); // Skip whitespace
@@ -2849,11 +2924,12 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
next_char(); // Skip '{'
// Parse the block form of ins_encode
- return ins_encode_parse_block(inst);
+ ins_encode_parse_block(inst);
+ return;
}
parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n");
- return NULL;
+ return;
}
next_char(); // move past '('
skipws();
@@ -2866,7 +2942,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
ec_name = get_ident();
if (ec_name == NULL) {
parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n");
- return NULL;
+ return;
}
// Check that encoding is defined in the encode section
EncClass *encode_class = _AD._encode->encClass(ec_name);
@@ -2898,7 +2974,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
(Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
- return NULL;
+ return;
}
params->add_entry(param);
@@ -2915,7 +2991,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
// Only ',' or ')' are valid after a parameter name
parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n",
ec_name);
- return NULL;
+ return;
}
} else {
@@ -2923,11 +2999,11 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
// Did not find a parameter
if (_curchar == ',') {
parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name);
- return NULL;
+ return;
}
if (_curchar != ')') {
parse_err(SYNERR, "Expected ')' after encode parameters.\n");
- return NULL;
+ return;
}
}
} // WHILE loop collecting parameters
@@ -2944,7 +3020,7 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
else if ( _curchar != ')' ) {
// If not a ',' then only a ')' is allowed
parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name);
- return NULL;
+ return;
}
// Check for ',' separating parameters
@@ -2956,14 +3032,14 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
} // done parsing ins_encode methods and their parameters
if (_curchar != ')') {
parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n");
- return NULL;
+ return;
}
next_char(); // move past ')'
skipws(); // Skip leading whitespace
if ( _curchar != ';' ) {
parse_err(SYNERR, "Missing ';' at end of ins_encode.\n");
- return NULL;
+ return;
}
next_char(); // move past ';'
skipws(); // be friendly to oper_parse()
@@ -2971,7 +3047,113 @@ InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
// Debug Stuff
if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name);
- return encrule;
+ // Set encode class of this instruction.
+ inst._insencode = encrule;
+}
+
+
+//------------------------------constant_parse---------------------------------
+// Parse a constant expression.
+void ADLParser::constant_parse(InstructForm& inst) {
+ // Create a new encoding name based on the name of the instruction
+ // definition, which should be unique.
+ const char* prefix = "__constant_";
+ char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
+ sprintf(ec_name, "%s%s", prefix, inst._ident);
+
+ assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
+ EncClass* encoding = _AD._encode->add_EncClass(ec_name);
+ encoding->_linenum = linenum();
+
+ // synthesize the arguments list for the enc_class from the
+ // arguments to the instruct definition.
+ const char* param = NULL;
+ inst._parameters.reset();
+ while ((param = inst._parameters.iter()) != NULL) {
+ OperandForm* opForm = (OperandForm*) inst._localNames[param];
+ encoding->add_parameter(opForm->_ident, param);
+ }
+
+ // Parse the following ( ) expression.
+ constant_parse_expression(encoding, ec_name);
+
+ // Build an encoding rule which invokes the encoding rule we just
+ // created, passing all arguments that we received.
+ InsEncode* encrule = new InsEncode(); // Encode class for instruction
+ NameAndList* params = encrule->add_encode(ec_name);
+ inst._parameters.reset();
+ while ((param = inst._parameters.iter()) != NULL) {
+ params->add_entry(param);
+ }
+
+ // Set encode class of this instruction.
+ inst._constant = encrule;
+}
+
+
+//------------------------------constant_parse_expression----------------------
+void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
+ skipws();
+
+ // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
+ if (_AD._adlocation_debug) {
+ encoding->add_code(get_line_string());
+ }
+
+ // Start code line.
+ encoding->add_code(" _constant = C->constant_table().add");
+
+ // Parse everything in ( ) expression.
+ encoding->add_code("(");
+ next_char(); // Skip '('
+ int parens_depth = 1;
+
+ // Collect the parts of the constant expression.
+ // (1) strings that are passed through to output
+ // (2) replacement/substitution variable, preceeded by a '$'
+ while (parens_depth > 0) {
+ if (_curchar == '(') {
+ parens_depth++;
+ encoding->add_code("(");
+ next_char();
+ }
+ else if (_curchar == ')') {
+ parens_depth--;
+ encoding->add_code(")");
+ next_char();
+ }
+ else {
+ // (1)
+ // Check if there is a string to pass through to output
+ char *start = _ptr; // Record start of the next string
+ while ((_curchar != '$') && (_curchar != '(') && (_curchar != ')')) {
+ next_char();
+ }
+ // If a string was found, terminate it and record in EncClass
+ if (start != _ptr) {
+ *_ptr = '\0'; // Terminate the string
+ encoding->add_code(start);
+ }
+
+ // (2)
+ // If we are at a replacement variable, copy it and record in EncClass.
+ if (_curchar == '$') {
+ // Found replacement Variable
+ char* rep_var = get_rep_var_ident_dup();
+ encoding->add_rep_var(rep_var);
+ }
+ }
+ }
+
+ // Finish code line.
+ encoding->add_code(";");
+
+ if (_AD._adlocation_debug) {
+ encoding->add_code(end_line_marker());
+ }
+
+ // Debug Stuff
+ if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
}
diff --git a/hotspot/src/share/vm/adlc/adlparse.hpp b/hotspot/src/share/vm/adlc/adlparse.hpp
index 1ebb3e3250e..ee33b88ef8e 100644
--- a/hotspot/src/share/vm/adlc/adlparse.hpp
+++ b/hotspot/src/share/vm/adlc/adlparse.hpp
@@ -156,8 +156,13 @@ protected:
Attribute *attr_parse(char *ident);// Parse instr/operand attribute rule
// Parse instruction encode rule
- InsEncode *ins_encode_parse(InstructForm &inst);
- InsEncode *ins_encode_parse_block(InstructForm &inst);
+ void ins_encode_parse(InstructForm &inst);
+ void ins_encode_parse_block(InstructForm &inst);
+ void ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name);
+
+ void constant_parse(InstructForm& inst);
+ void constant_parse_expression(EncClass* encoding, char* ec_name);
+
Opcode *opcode_parse(InstructForm *insr); // Parse instruction opcode
char *size_parse(InstructForm *insr); // Parse instruction size
Interface *interface_parse(); // Parse operand interface rule
diff --git a/hotspot/src/share/vm/adlc/archDesc.hpp b/hotspot/src/share/vm/adlc/archDesc.hpp
index 7a2ff93afeb..ad8f454be5a 100644
--- a/hotspot/src/share/vm/adlc/archDesc.hpp
+++ b/hotspot/src/share/vm/adlc/archDesc.hpp
@@ -126,7 +126,6 @@ private:
void chain_rule(FILE *fp, const char *indent, const char *ideal,
const Expr *icost, const char *irule,
Dict &operands_chained_from, ProductionState &status);
- void chain_rule_c(FILE *fp, char *indent, char *ideal, char *irule); // %%%%% TODO: remove this
void expand_opclass(FILE *fp, const char *indent, const Expr *cost,
const char *result_type, ProductionState &status);
Expr *calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status);
@@ -301,13 +300,18 @@ public:
void buildMachNodeGenerator(FILE *fp_cpp);
// Generator for Expand methods for instructions with expand rules
- void defineExpand(FILE *fp, InstructForm *node);
+ void defineExpand (FILE *fp, InstructForm *node);
// Generator for Peephole methods for instructions with peephole rules
- void definePeephole(FILE *fp, InstructForm *node);
+ void definePeephole (FILE *fp, InstructForm *node);
// Generator for Size methods for instructions
- void defineSize(FILE *fp, InstructForm &node);
+ void defineSize (FILE *fp, InstructForm &node);
+
+public:
+ // Generator for EvalConstantValue methods for instructions
+ void defineEvalConstant(FILE *fp, InstructForm &node);
// Generator for Emit methods for instructions
- void defineEmit(FILE *fp, InstructForm &node);
+ void defineEmit (FILE *fp, InstructForm &node);
+
// Define a MachOper encode method
void define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals,
const char *name, const char *encoding);
diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp
index 5011b505c16..c659cdb881d 100644
--- a/hotspot/src/share/vm/adlc/formssel.cpp
+++ b/hotspot/src/share/vm/adlc/formssel.cpp
@@ -30,11 +30,14 @@
InstructForm::InstructForm(const char *id, bool ideal_only)
: _ident(id), _ideal_only(ideal_only),
_localNames(cmpstr, hashstr, Form::arena),
- _effects(cmpstr, hashstr, Form::arena) {
+ _effects(cmpstr, hashstr, Form::arena),
+ _is_mach_constant(false)
+{
_ftype = Form::INS;
_matrule = NULL;
_insencode = NULL;
+ _constant = NULL;
_opcode = NULL;
_size = NULL;
_attribs = NULL;
@@ -58,11 +61,14 @@ InstructForm::InstructForm(const char *id, bool ideal_only)
InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule)
: _ident(id), _ideal_only(false),
_localNames(instr->_localNames),
- _effects(instr->_effects) {
+ _effects(instr->_effects),
+ _is_mach_constant(false)
+{
_ftype = Form::INS;
_matrule = rule;
_insencode = instr->_insencode;
+ _constant = instr->_constant;
_opcode = instr->_opcode;
_size = instr->_size;
_attribs = instr->_attribs;
@@ -1094,6 +1100,9 @@ const char *InstructForm::mach_base_class(FormDict &globals) const {
else if (is_ideal_nop()) {
return "MachNopNode";
}
+ else if (is_mach_constant()) {
+ return "MachConstantNode";
+ }
else if (captures_bottom_type(globals)) {
return "MachTypeNode";
} else {
@@ -1190,6 +1199,21 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch
//
// Generate the format call for the replacement variable
void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {
+ // Handle special constant table variables.
+ if (strcmp(rep_var, "constanttablebase") == 0) {
+ fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg);\n");
+ fprintf(fp, "st->print(\"%%s\");\n");
+ return;
+ }
+ if (strcmp(rep_var, "constantoffset") == 0) {
+ fprintf(fp, "st->print(\"#%%d\", constant_offset());\n");
+ return;
+ }
+ if (strcmp(rep_var, "constantaddress") == 0) {
+ fprintf(fp, "st->print(\"constant table base + #%%d\", constant_offset());\n");
+ return;
+ }
+
// Find replacement variable's type
const Form *form = _localNames[rep_var];
if (form == NULL) {
@@ -1348,6 +1372,7 @@ void InstructForm::output(FILE *fp) {
fprintf(fp,"\nInstruction: %s\n", (_ident?_ident:""));
if (_matrule) _matrule->output(fp);
if (_insencode) _insencode->output(fp);
+ if (_constant) _constant->output(fp);
if (_opcode) _opcode->output(fp);
if (_attribs) _attribs->output(fp);
if (_predicate) _predicate->output(fp);
diff --git a/hotspot/src/share/vm/adlc/formssel.hpp b/hotspot/src/share/vm/adlc/formssel.hpp
index 285eacd0afa..88ba702672c 100644
--- a/hotspot/src/share/vm/adlc/formssel.hpp
+++ b/hotspot/src/share/vm/adlc/formssel.hpp
@@ -74,15 +74,16 @@ class ArchDesc;
//------------------------------InstructForm-----------------------------------
class InstructForm : public Form {
private:
- bool _ideal_only; // Not a user-defined instruction
+ bool _ideal_only; // Not a user-defined instruction
// Members used for tracking CISC-spilling
- uint _cisc_spill_operand;// Which operand may cisc-spill
+ uint _cisc_spill_operand;// Which operand may cisc-spill
void set_cisc_spill_operand(uint op_index) { _cisc_spill_operand = op_index; }
- bool _is_cisc_alternate;
+ bool _is_cisc_alternate;
InstructForm *_cisc_spill_alternate;// cisc possible replacement
const char *_cisc_reg_mask_name;
InstructForm *_short_branch_form;
bool _is_short_branch;
+ bool _is_mach_constant; // true if Node is a MachConstantNode
uint _alignment;
public:
@@ -94,6 +95,7 @@ public:
Opcode *_opcode; // Encoding of the opcode for instruction
char *_size; // Size of instruction
InsEncode *_insencode; // Encoding class instruction belongs to
+ InsEncode *_constant; // Encoding class constant value belongs to
Attribute *_attribs; // List of Attribute rules
Predicate *_predicate; // Predicate test for this instruction
FormDict _effects; // Dictionary of effect rules
@@ -251,6 +253,9 @@ public:
bool is_short_branch() { return _is_short_branch; }
void set_short_branch(bool val) { _is_short_branch = val; }
+ bool is_mach_constant() const { return _is_mach_constant; }
+ void set_is_mach_constant(bool x) { _is_mach_constant = x; }
+
InstructForm *short_branch_form() { return _short_branch_form; }
bool has_short_branch_form() { return _short_branch_form != NULL; }
// Output short branch prototypes and method bodies
diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp
index 75cdcacb997..776c486f179 100644
--- a/hotspot/src/share/vm/adlc/output_c.cpp
+++ b/hotspot/src/share/vm/adlc/output_c.cpp
@@ -1496,8 +1496,8 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
unsigned i;
// Generate Expand function header
- fprintf(fp,"MachNode *%sNode::Expand(State *state, Node_List &proj_list, Node* mem) {\n", node->_ident);
- fprintf(fp,"Compile* C = Compile::current();\n");
+ fprintf(fp, "MachNode* %sNode::Expand(State* state, Node_List& proj_list, Node* mem) {\n", node->_ident);
+ fprintf(fp, " Compile* C = Compile::current();\n");
// Generate expand code
if( node->expands() ) {
const char *opid;
@@ -1818,6 +1818,12 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
}
}
+ // If the node is a MachConstantNode, insert the MachConstantBaseNode edge.
+ // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input).
+ if (node->is_mach_constant()) {
+ fprintf(fp," add_req(C->mach_constant_base_node());\n");
+ }
+
fprintf(fp,"\n");
if( node->expands() ) {
fprintf(fp," return result;\n");
@@ -1924,7 +1930,17 @@ public:
// No state needed.
assert( _opclass == NULL,
"'primary', 'secondary' and 'tertiary' don't follow operand.");
- } else {
+ }
+ else if ((strcmp(rep_var, "constanttablebase") == 0) ||
+ (strcmp(rep_var, "constantoffset") == 0) ||
+ (strcmp(rep_var, "constantaddress") == 0)) {
+ if (!_inst.is_mach_constant()) {
+ _AD.syntax_err(_encoding._linenum,
+ "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n",
+ rep_var, _encoding._name);
+ }
+ }
+ else {
// Lookup its position in parameter list
int param_no = _encoding.rep_var_index(rep_var);
if ( param_no == -1 ) {
@@ -2380,6 +2396,15 @@ private:
rep_var, _inst._ident, _encoding._name);
}
}
+ else if (strcmp(rep_var, "constanttablebase") == 0) {
+ fprintf(_fp, "as_Register(ra_->get_encode(in(mach_constant_base_node_input())))");
+ }
+ else if (strcmp(rep_var, "constantoffset") == 0) {
+ fprintf(_fp, "constant_offset()");
+ }
+ else if (strcmp(rep_var, "constantaddress") == 0) {
+ fprintf(_fp, "InternalAddress(__ code()->consts()->start() + constant_offset())");
+ }
else {
// Lookup its position in parameter list
int param_no = _encoding.rep_var_index(rep_var);
@@ -2465,37 +2490,39 @@ void ArchDesc::defineSize(FILE *fp, InstructForm &inst) {
fprintf(fp,"}\n");
}
-void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) {
- InsEncode *ins_encode = inst._insencode;
+// defineEmit -----------------------------------------------------------------
+void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
+ InsEncode* encode = inst._insencode;
// (1)
// Output instruction's emit prototype
- fprintf(fp,"void %sNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {\n",
- inst._ident);
+ fprintf(fp, "void %sNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {\n", inst._ident);
// If user did not define an encode section,
// provide stub that does not generate any machine code.
- if( (_encode == NULL) || (ins_encode == NULL) ) {
+ if( (_encode == NULL) || (encode == NULL) ) {
fprintf(fp, " // User did not define an encode section.\n");
- fprintf(fp,"}\n");
+ fprintf(fp, "}\n");
return;
}
// Save current instruction's starting address (helps with relocation).
- fprintf(fp, " cbuf.set_insts_mark();\n");
+ fprintf(fp, " cbuf.set_insts_mark();\n");
- // // // idx0 is only needed for syntactic purposes and only by "storeSSI"
- // fprintf( fp, " unsigned idx0 = 0;\n");
+ // For MachConstantNodes which are ideal jump nodes, fill the jump table.
+ if (inst.is_mach_constant() && inst.is_ideal_jump()) {
+ fprintf(fp, " ra_->C->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n");
+ }
// Output each operand's offset into the array of registers.
- inst.index_temps( fp, _globalNames );
+ inst.index_temps(fp, _globalNames);
// Output this instruction's encodings
const char *ec_name;
bool user_defined = false;
- ins_encode->reset();
- while ( (ec_name = ins_encode->encode_class_iter()) != NULL ) {
- fprintf(fp, " {");
+ encode->reset();
+ while ((ec_name = encode->encode_class_iter()) != NULL) {
+ fprintf(fp, " {\n");
// Output user-defined encoding
user_defined = true;
@@ -2507,25 +2534,25 @@ void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) {
abort();
}
- if (ins_encode->current_encoding_num_args() != encoding->num_args()) {
- globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
- inst._ident, ins_encode->current_encoding_num_args(),
+ if (encode->current_encoding_num_args() != encoding->num_args()) {
+ globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+ inst._ident, encode->current_encoding_num_args(),
ec_name, encoding->num_args());
}
- DefineEmitState pending(fp, *this, *encoding, *ins_encode, inst );
+ DefineEmitState pending(fp, *this, *encoding, *encode, inst);
encoding->_code.reset();
encoding->_rep_vars.reset();
// Process list of user-defined strings,
// and occurrences of replacement variables.
// Replacement Vars are pushed into a list and then output
- while ( (ec_code = encoding->_code.iter()) != NULL ) {
- if ( ! encoding->_code.is_signal( ec_code ) ) {
+ while ((ec_code = encoding->_code.iter()) != NULL) {
+ if (!encoding->_code.is_signal(ec_code)) {
// Emit pending code
pending.emit();
pending.clear();
// Emit this code section
- fprintf(fp,"%s", ec_code);
+ fprintf(fp, "%s", ec_code);
} else {
// A replacement variable or one of its subfields
// Obtain replacement variable from list
@@ -2536,7 +2563,7 @@ void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) {
// Emit pending code
pending.emit();
pending.clear();
- fprintf(fp, "}\n");
+ fprintf(fp, " }\n");
} // end while instruction's encodings
// Check if user stated which encoding to user
@@ -2545,7 +2572,86 @@ void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) {
}
// (3) and (4)
- fprintf(fp,"}\n");
+ fprintf(fp, "}\n");
+}
+
+// defineEvalConstant ---------------------------------------------------------
+void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) {
+ InsEncode* encode = inst._constant;
+
+ // (1)
+ // Output instruction's emit prototype
+ fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident);
+
+ // For ideal jump nodes, allocate a jump table.
+ if (inst.is_ideal_jump()) {
+ fprintf(fp, " _constant = C->constant_table().allocate_jump_table(this);\n");
+ }
+
+ // If user did not define an encode section,
+ // provide stub that does not generate any machine code.
+ if ((_encode == NULL) || (encode == NULL)) {
+ fprintf(fp, " // User did not define an encode section.\n");
+ fprintf(fp, "}\n");
+ return;
+ }
+
+ // Output this instruction's encodings
+ const char *ec_name;
+ bool user_defined = false;
+ encode->reset();
+ while ((ec_name = encode->encode_class_iter()) != NULL) {
+ fprintf(fp, " {\n");
+ // Output user-defined encoding
+ user_defined = true;
+
+ const char *ec_code = NULL;
+ const char *ec_rep_var = NULL;
+ EncClass *encoding = _encode->encClass(ec_name);
+ if (encoding == NULL) {
+ fprintf(stderr, "User did not define contents of this encode_class: %s\n", ec_name);
+ abort();
+ }
+
+ if (encode->current_encoding_num_args() != encoding->num_args()) {
+ globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+ inst._ident, encode->current_encoding_num_args(),
+ ec_name, encoding->num_args());
+ }
+
+ DefineEmitState pending(fp, *this, *encoding, *encode, inst);
+ encoding->_code.reset();
+ encoding->_rep_vars.reset();
+ // Process list of user-defined strings,
+ // and occurrences of replacement variables.
+ // Replacement Vars are pushed into a list and then output
+ while ((ec_code = encoding->_code.iter()) != NULL) {
+ if (!encoding->_code.is_signal(ec_code)) {
+ // Emit pending code
+ pending.emit();
+ pending.clear();
+ // Emit this code section
+ fprintf(fp, "%s", ec_code);
+ } else {
+ // A replacement variable or one of its subfields
+ // Obtain replacement variable from list
+ ec_rep_var = encoding->_rep_vars.iter();
+ pending.add_rep_var(ec_rep_var);
+ }
+ }
+ // Emit pending code
+ pending.emit();
+ pending.clear();
+ fprintf(fp, " }\n");
+ } // end while instruction's encodings
+
+ // Check if user stated which encoding to user
+ if (user_defined == false) {
+ fprintf(fp, " // User did not define which encode class to use.\n");
+ }
+
+ // (3) and (4)
+ fprintf(fp, "}\n");
}
// ---------------------------------------------------------------------------
@@ -2952,6 +3058,7 @@ void ArchDesc::defineClasses(FILE *fp) {
// If there are multiple defs/kills, or an explicit expand rule, build rule
if( instr->expands() || instr->needs_projections() ||
instr->has_temps() ||
+ instr->is_mach_constant() ||
instr->_matrule != NULL &&
instr->num_opnds() != instr->num_unique_opnds() )
defineExpand(_CPP_EXPAND_file._fp, instr);
@@ -3032,8 +3139,9 @@ void ArchDesc::defineClasses(FILE *fp) {
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
- if (instr->_insencode) defineEmit(fp, *instr);
- if (instr->_size) defineSize(fp, *instr);
+ if (instr->_insencode) defineEmit (fp, *instr);
+ if (instr->is_mach_constant()) defineEvalConstant(fp, *instr);
+ if (instr->_size) defineSize (fp, *instr);
// side-call to generate output that used to be in the header file:
extern void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &oper, bool for_c_file);
diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp
index 1bae8b1fd33..08e8ca6bf69 100644
--- a/hotspot/src/share/vm/adlc/output_h.cpp
+++ b/hotspot/src/share/vm/adlc/output_h.cpp
@@ -1550,7 +1550,12 @@ void ArchDesc::declareClasses(FILE *fp) {
}
// virtual functions for encode and format
- //
+
+ // Virtual function for evaluating the constant.
+ if (instr->is_mach_constant()) {
+ fprintf(fp," virtual void eval_constant(Compile* C);\n");
+ }
+
// Output the opcode function and the encode function here using the
// encoding class information in the _insencode slot.
if ( instr->_insencode ) {
@@ -1559,7 +1564,7 @@ void ArchDesc::declareClasses(FILE *fp) {
// virtual function for getting the size of an instruction
if ( instr->_size ) {
- fprintf(fp," virtual uint size(PhaseRegAlloc *ra_) const;\n");
+ fprintf(fp," virtual uint size(PhaseRegAlloc *ra_) const;\n");
}
// Return the top-level ideal opcode.
@@ -1752,6 +1757,7 @@ void ArchDesc::declareClasses(FILE *fp) {
// Virtual methods which are only generated to override base class
if( instr->expands() || instr->needs_projections() ||
instr->has_temps() ||
+ instr->is_mach_constant() ||
instr->_matrule != NULL &&
instr->num_opnds() != instr->num_unique_opnds() ) {
fprintf(fp," virtual MachNode *Expand(State *state, Node_List &proj_list, Node* mem);\n");
@@ -1780,24 +1786,6 @@ void ArchDesc::declareClasses(FILE *fp) {
// Declare short branch methods, if applicable
instr->declare_short_branch_methods(fp);
- // Instructions containing a constant that will be entered into the
- // float/double table redefine the base virtual function
-#ifdef SPARC
- // Sparc doubles entries in the constant table require more space for
- // alignment. (expires 9/98)
- int table_entries = (3 * instr->num_consts( _globalNames, Form::idealD ))
- + instr->num_consts( _globalNames, Form::idealF );
-#else
- int table_entries = instr->num_consts( _globalNames, Form::idealD )
- + instr->num_consts( _globalNames, Form::idealF );
-#endif
- if( table_entries != 0 ) {
- fprintf(fp," virtual int const_size() const {");
- fprintf(fp, " return %d;", table_entries);
- fprintf(fp, " }\n");
- }
-
-
// See if there is an "ins_pipe" declaration for this instruction
if (instr->_ins_pipe) {
fprintf(fp," static const Pipeline *pipeline_class();\n");
diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp
index 04d84c43797..0b3544e695f 100644
--- a/hotspot/src/share/vm/asm/assembler.hpp
+++ b/hotspot/src/share/vm/asm/assembler.hpp
@@ -292,7 +292,16 @@ class AbstractAssembler : public ResourceObj {
address start_a_const(int required_space, int required_align = sizeof(double));
void end_a_const();
- // fp constants support
+ // constants support
+ address long_constant(jlong c) {
+ address ptr = start_a_const(sizeof(c), sizeof(c));
+ if (ptr != NULL) {
+ *(jlong*)ptr = c;
+ _code_pos = ptr + sizeof(c);
+ end_a_const();
+ }
+ return ptr;
+ }
address double_constant(jdouble c) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
@@ -311,6 +320,15 @@ class AbstractAssembler : public ResourceObj {
}
return ptr;
}
+ address address_constant(address c) {
+ address ptr = start_a_const(sizeof(c), sizeof(c));
+ if (ptr != NULL) {
+ *(address*)ptr = c;
+ _code_pos = ptr + sizeof(c);
+ end_a_const();
+ }
+ return ptr;
+ }
address address_constant(address c, RelocationHolder const& rspec) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
@@ -321,8 +339,6 @@ class AbstractAssembler : public ResourceObj {
}
return ptr;
}
- inline address address_constant(Label& L);
- inline address address_table_constant(GrowableArray
- * The invoker will spread the varargs array, apply
- * reference casts as necessary, and unbox primitive arguments.
+ *
+ * The invoker will behave like a call to {@link MethodHandle.invokeGeneric} with
+ * the indicated {@code type}.
+ * That is, if the target is exactly of the given {@code type}, it will behave
+ * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle.asType}
+ * is used to convert the target to the required {@code type}.
+ *
+ * The type of the returned invoker will not be the given {@code type}, but rather
+ * will have all parameter and return types replaced by {@code Object}, except for
+ * the last parameter type, which will be the array type {@code Object[]}.
+ *
+ * Before invoking its target, the invoker will spread the varargs array, apply
+ * reference casts as necessary, and unbox and widen primitive arguments.
* The return value of the invoker will be an {@code Object} reference,
* boxing a primitive value if the original type returns a primitive,
* and always null if the original type returns void.
*
* This method is equivalent to the following code (though it may be more efficient):
*
* @param type the desired target type
* @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
@@ -881,7 +928,6 @@ public class MethodHandles {
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
* Produce a method handle which will take a invoke any method handle of the
* given type. The resulting invoker will have a type which is
* exactly equal to the desired type, except that it will accept
@@ -889,7 +935,7 @@ public class MethodHandles {
*
* This method is equivalent to the following code (though it may be more efficient):
*
* @param type the desired target type
* @return a method handle suitable for invoking any method handle of the given type
@@ -899,39 +945,6 @@ public class MethodHandles {
return invokers(type).exactInvoker();
}
- /**
- * PROVISIONAL API, WORK IN PROGRESS:
- * Produce a method handle equivalent to an invokedynamic instruction
- * which has been linked to the given call site.
- * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic},
- * and {@link Lookup#findSpecial}, this completes the emulation
- * of the JVM's {@code invoke} instructions.
- *
This method is equivalent to the following code:
- *
- * @return a method handle which always invokes the call site's target
- */
- public static
- MethodHandle dynamicInvoker(CallSite site) throws NoAccessException {
- MethodHandle getCSTarget = GET_TARGET;
- if (getCSTarget == null) {
- try {
- GET_TARGET = getCSTarget = Lookup.IMPL_LOOKUP.
- findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
- } catch (NoAccessException ex) {
- throw new InternalError();
- }
- }
- MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, getCSTarget, site);
- MethodHandle invoker = exactInvoker(site.type());
- return foldArguments(invoker, getTarget);
- }
- private static MethodHandle GET_TARGET = null; // link this lazily, not eagerly
-
static Invokers invokers(MethodType type) {
return MethodTypeImpl.invokers(IMPL_TOKEN, type);
}
@@ -974,23 +987,23 @@ public class MethodHandles {
if (t0.isPrimitive())
return Wrapper.asPrimitiveType(t1).cast(value);
else
- return Wrapper.OBJECT.cast(value, t1);
+ return Wrapper.OBJECT.convert(value, t1);
}
boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
if (!prim0) {
// check contract with caller
- Wrapper.OBJECT.cast(value, t0);
+ Wrapper.OBJECT.convert(value, t0);
if (!prim1) {
- return Wrapper.OBJECT.cast(value, t1);
+ return Wrapper.OBJECT.convert(value, t1);
}
// convert reference to primitive by unboxing
Wrapper w1 = Wrapper.forPrimitiveType(t1);
- return w1.cast(value, t1);
+ return w1.convert(value, t1);
}
// check contract with caller:
Wrapper.asWrapperType(t0).cast(value);
Wrapper w1 = Wrapper.forPrimitiveType(t1);
- return w1.cast(value, t1);
+ return w1.convert(value, t1);
}
static
@@ -1011,7 +1024,7 @@ public class MethodHandles {
* Produce a method handle which adapts the type of the
* given method handle to a new type by pairwise argument conversion.
* The original type and new type must have the same number of arguments.
- * The resulting method handle is guaranteed to confess a type
+ * The resulting method handle is guaranteed to report a type
* which is equal to the desired new type.
*
* If the original type and new type are equal, returns target.
@@ -1023,34 +1036,21 @@ public class MethodHandles {
* Given those types T0, T1, one of the following conversions is applied
* if possible:
*
- *
If T0 and T1 are references, and T1 is not an interface type,
- * then a cast to T1 is applied.
+ *
If T0 and T1 are references, then a cast to T1 is applied.
* (The types do not need to be related in any particular way.)
- *
If T0 and T1 are references, and T1 is an interface type,
- * then the value of type T0 is passed as a T1 without a cast.
- * (This treatment of interfaces follows the usage of the bytecode verifier.)
- *
If T0 and T1 are primitives, then a Java casting
- * conversion (JLS 5.5) is applied, if one exists.
- *
If T0 and T1 are primitives and one is boolean,
- * the boolean is treated as a one-bit unsigned integer.
- * (This treatment follows the usage of the bytecode verifier.)
- * A conversion from another primitive type behaves as if
- * it first converts to byte, and then masks all but the low bit.
+ *
If T0 and T1 are primitives, then a Java method invocation
+ * conversion (JLS 5.3) is applied, if one exists.
*
If T0 is a primitive and T1 a reference, a boxing
* conversion is applied if one exists, possibly followed by
- * an reference conversion to a superclass.
+ * a reference conversion to a superclass.
* T1 must be a wrapper class or a supertype of one.
- * If T1 is a wrapper class, T0 is converted if necessary
- * to T1's primitive type by one of the preceding conversions.
- * Otherwise, T0 is boxed, and its wrapper converted to T1.
*
If T0 is a reference and T1 a primitive, an unboxing
- * conversion is applied if one exists, possibly preceded by
- * a reference conversion to a wrapper class.
+ * conversion will be applied at runtime, possibly followed
+ * by a Java method invocation conversion (JLS 5.3)
+ * on the primitive value. (These are the widening conversions.)
* T0 must be a wrapper class or a supertype of one.
- * If T0 is a wrapper class, its primitive value is converted
- * if necessary to T1 by one of the preceding conversions.
- * Otherwise, T0 is converted directly to the wrapper type for T1,
- * which is then unboxed.
+ * (In the case where T0 is Object, these are the conversions
+ * allowed by java.lang.reflect.Method.invoke.)
*
If the return type T1 is void, any returned value is discarded
*
If the return type T0 is void and T1 a reference, a null value is introduced.
*
If the return type T0 is void and T1 a primitive, a zero value is introduced.
@@ -1060,26 +1060,109 @@ public class MethodHandles {
* @return a method handle which delegates to {@code target} after performing
* any necessary argument conversions, and arranges for any
* necessary return value conversions
- * @throws IllegalArgumentException if the conversion cannot be made
+ * @throws WrongMethodTypeException if the conversion cannot be made
* @see MethodHandle#asType
+ * @see MethodHandles#explicitCastArguments
*/
public static
MethodHandle convertArguments(MethodHandle target, MethodType newType) {
MethodType oldType = target.type();
if (oldType.equals(newType))
return target;
- MethodHandle res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
- newType, oldType, null);
+ MethodHandle res = null;
+ try {
+ res = MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
+ newType, oldType, null);
+ } catch (IllegalArgumentException ex) {
+ }
if (res == null)
- throw newIllegalArgumentException("cannot convert to "+newType+": "+target);
+ throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
return res;
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
+ * Produce a method handle which adapts the type of the
+ * given method handle to a new type by pairwise argument conversion.
+ * The original type and new type must have the same number of arguments.
+ * The resulting method handle is guaranteed to report a type
+ * which is equal to the desired new type.
+ *
+ * If the original type and new type are equal, returns target.
+ *
+ * The same conversions are allowed as for {@link #convertArguments convertArguments},
+ * and some additional conversions are also applied if those conversions fail.
+ * Given types T0, T1, one of the following conversions is applied
+ * in addition, if the conversions specified for {@code convertArguments}
+ * would be insufficient:
+ *
+ *
If T0 and T1 are references, and T1 is an interface type,
+ * then the value of type T0 is passed as a T1 without a cast.
+ * (This treatment of interfaces follows the usage of the bytecode verifier.)
+ *
If T0 and T1 are primitives and one is boolean,
+ * the boolean is treated as a one-bit unsigned integer.
+ * (This treatment follows the usage of the bytecode verifier.)
+ * A conversion from another primitive type behaves as if
+ * it first converts to byte, and then masks all but the low bit.
+ *
If a primitive value would be converted by {@code convertArguments}
+ * using Java method invocation conversion (JLS 5.3),
+ * Java casting conversion (JLS 5.5) may be used also.
+ * This allows primitives to be narrowed as well as widened.
+ *
+ * @param target the method handle to invoke after arguments are retyped
+ * @param newType the expected type of the new method handle
+ * @return a method handle which delegates to {@code target} after performing
+ * any necessary argument conversions, and arranges for any
+ * necessary return value conversions
+ * @throws WrongMethodTypeException if the conversion cannot be made
+ * @see MethodHandle#asType
+ * @see MethodHandles#convertArguments
+ */
+ public static
+ MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
+ return convertArguments(target, newType); // FIXME!
+ }
+
+ /*
+ FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion:
+
+ Both converters arrange for their method handles to convert arguments
+ and return values. The conversion rules are the same for arguments
+ and return values, and depend only on source and target types, S and
+ T. The conversions allowed by castConvertArguments are a strict
+ superset of those performed by convertArguments.
+
+ In all cases, if S and T are references, a simple checkcast is done.
+ If neither S nor T is a primitive, no attempt is made to unbox and
+ box. A failed conversion throws ClassCastException.
+
+ If T is void, the value is dropped.
+
+ For compatibility with reflection, if S is void and T is a reference,
+ a null value is produced.
+
+ For compatibility with reflection, if S is a reference and T is a
+ primitive, S is first unboxed and then undergoes primitive conversion.
+ In the case of 'convertArguments', only assignment conversion is
+ performed (no narrowing primitive conversion).
+
+ If S is a primitive, S is boxed, and then the above rules are applied.
+ If S and T are both primitives, the boxing will be undetectable; only
+ the primitive conversions will be apparent to the user. The key point
+ is that if S is a primitive type, the implementation may box it and
+ treat is as Object, without loss of information, or it may use a "fast
+ path" which does not use boxing.
+
+ Notwithstanding the rules above, for compatibility with the verifier,
+ if T is an interface, it is treated as if it were Object. [KEEP THIS?]
+
+ Also, for compatibility with the verifier, a boolean may be undergo
+ widening or narrowing conversion to any other primitive type. [KEEP THIS?]
+ */
+
+ /**
* Produce a method handle which adapts the calling sequence of the
* given method handle to a new type, by reordering the arguments.
- * The resulting method handle is guaranteed to confess a type
+ * The resulting method handle is guaranteed to report a type
* which is equal to the desired new type.
*
* The given array controls the reordering.
@@ -1092,22 +1175,42 @@ public class MethodHandles {
* outgoing argument will be taken from the {@code I}-th incoming
* argument, where {@code I} is {@code reorder[N]}.
*
+ * No argument or return value conversions are applied.
+ * The type of each incoming argument, as determined by {@code newType},
+ * must be identical to the type of the corresponding outgoing argument
+ * or arguments in the target method handle.
+ * The return type of {@code newType} must be identical to the return
+ * type of the original target.
+ *
* The reordering array need not specify an actual permutation.
* An incoming argument will be duplicated if its index appears
* more than once in the array, and an incoming argument will be dropped
* if its index does not appear in the array.
- *
- * Pairwise conversions are applied as needed to arguments and return
- * values, as with {@link #convertArguments}.
+ * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
+ * incoming arguments which are not mentioned in the reordering array
+ * are may be any type, as determined only by {@code newType}.
+ *
* @param target the method handle to invoke after arguments are reordered
* @param newType the expected type of the new method handle
* @param reorder a string which controls the reordering
- * @return a method handle which delegates to {@code target} after performing
- * any necessary argument motion and conversions, and arranges for any
- * necessary return value conversions
+ * @return a method handle which delegates to {@code target} after it
+ * drops unused arguments and moves and/or duplicates the other arguments
*/
public static
- MethodHandle permuteArguments(MethodHandle target, MethodType newType, int[] reorder) {
+ MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
MethodType oldType = target.type();
checkReorder(reorder, newType, oldType);
return MethodHandleImpl.convertArguments(IMPL_TOKEN, target,
@@ -1130,33 +1233,21 @@ public class MethodHandles {
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
- * Produce a method handle which adapts the type of the
- * given method handle to a new type, by spreading the final argument.
- * The resulting method handle is guaranteed to confess a type
- * which is equal to the desired new type.
- *
- * The final parameter type of the new type must be an array type T[].
- * This is the type of what is called the spread argument.
- * All other arguments of the new type are called ordinary arguments.
- *
- * The ordinary arguments of the new type are pairwise converted
- * to the initial parameter types of the old type, according to the
- * rules in {@link #convertArguments}.
- * Any additional arguments in the old type
- * are converted from the array element type T,
- * again according to the rules in {@link #convertArguments}.
- * The return value is converted according likewise.
- *
- * The call verifies that the spread argument is in fact an array
- * of exactly the type length, i.e., the excess number of
- * arguments in the old type over the ordinary arguments in the new type.
- * If there are no excess arguments, the spread argument is also
- * allowed to be null.
- * @param target the method handle to invoke after the argument is prepended
+ * METHOD WILL BE REMOVED FOR PFD:
+ * Equivalent to the following code:
+ *
+ * @param target the method handle to invoke after argument spreading
* @param newType the expected type of the new method handle
- * @return a new method handle which spreads its final argument,
+ * @return a method handle which spreads its final argument,
* before calling the original method handle
+ * @deprecated Use {@link MethodHandle#asSpreader}
*/
public static
MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
@@ -1176,21 +1267,22 @@ public class MethodHandles {
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
- * Produce a method handle which adapts the type of the
- * given method handle to a new type, by collecting a series of
- * trailing arguments as elements to a single argument array.
- *
- * This method may be used as an inverse to {@link #spreadArguments}.
- * The final parameter type of the old type must be an array type T[],
- * which is the type of what is called the spread argument.
- * The trailing arguments of the new type which correspond to
- * the spread argument are all converted to type T and collected
- * into an array before the original method is called.
- * @param target the method handle to invoke after the argument is prepended
+ * METHOD WILL BE REMOVED FOR PFD:
+ * Equivalent to the following code:
+ *
+ * @param target the method handle to invoke after argument collection
* @param newType the expected type of the new method handle
- * @return a new method handle which collects some trailing argument
+ * @return a method handle which collects some trailing argument
* into an array, before calling the original method handle
+ * @deprecated Use {@link MethodHandle#asCollector} instead.
*/
public static
MethodHandle collectArguments(MethodHandle target, MethodType newType) {
@@ -1209,7 +1301,88 @@ public class MethodHandles {
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
+ * Produce a method handle of the requested return type which returns the given
+ * constant value every time it is invoked.
+ *
+ * Before the method handle is returned, the passed-in value is converted to the requested type.
+ * If the requested type is primitive, widening primitive conversions are attempted,
+ * else reference conversions are attempted.
+ *
The returned method handle is equivalent to {@code identity(type).bindTo(value)},
+ * unless the type is {@code void}, in which case it is {@code identity(type)}.
+ * @param type the return type of the desired method handle
+ * @param value the value to return
+ * @return a method handle of the given return type and no arguments, which always returns the given value
+ * @throws WrongMethodTypeException if the value cannot be converted to the required return type
+ */
+ public static
+ MethodHandle constant(Class> type, Object value) {
+ if (type.isPrimitive()) {
+ if (type == void.class) return identity(type);
+ Wrapper w = Wrapper.forPrimitiveType(type);
+ return identity(type).bindTo(w.convert(value, type));
+ } else {
+ return identity(type).bindTo(type.cast(value));
+ }
+ }
+
+ /**
+ * Produce a method handle of the requested type which returns the given
+ * constant value every time it is invoked.
+ *
+ * Before the method handle is returned, the passed-in value is converted to the requested return type,
+ * as if by {@link #explicitCastArguments #explicitCastArguments}.
+ * That is, if the return type is primitive, the value is unboxed,
+ * and the primitive value is widened and/or narrowed.
+ * Otherwise, reference conversions are attempted.
+ * @param type the type of the desired method handle
+ * @param value the value to return
+ * @return a method handle of the given return type and no arguments, which always returns the given value
+ * @throws WrongMethodTypeException if the value cannot be converted to the required return type
+ */
+ public static
+ MethodHandle constant(MethodType type, Object value) {
+ MethodHandle target = constant(type.returnType(), value);
+ int len = type.parameterCount();
+ if (len == 0)
+ return target.asType(type);
+ target = target.asType(type.dropParameterTypes(0, len));
+ return dropArguments(target, 0, type.parameterList().subList(0, len));
+ }
+
+ /**
+ * Produce a method handle which returns its sole argument when invoked.
+ *
The identity function for {@code void} takes no arguments and returns no values.
+ * @param type the type of the sole parameter and return value of the desired method handle
+ * @return a unary method handle which accepts and returns the given type
+ */
+ public static
+ MethodHandle identity(Class> type) {
+ return ValueConversions.identity(type);
+ }
+
+ /**
+ * Produce a method handle of the requested type which returns its argument when invoked.
+ * If the return type differs from the first argument type, the argument will be
+ * converted as if by {@link #explicitCastArguments explicitCastArguments}.
+ * If there are additional arguments beyond the first, they are discarded.
+ *
The identity function for {@code void} discards all its arguments.
+ * @param type the type of the desired method handle
+ * @return a method handle of the given type, which always returns its first argument
+ * @throws WrongMethodTypeException if the first argument cannot be converted to the required return type
+ */
+ public static
+ MethodHandle identity(MethodType type) {
+ MethodHandle target = identity(type.returnType());
+ int len = type.parameterCount();
+ if (len == 1)
+ return explicitCastArguments(target, type);
+ if (len == 0)
+ throw new IllegalArgumentException("not enough arguments");
+ target = explicitCastArguments(target, type.dropParameterTypes(1, len));
+ return dropArguments(target, 1, type.parameterList().subList(1, len));
+ }
+
+ /**
* Produce a method handle which calls the original method handle {@code target},
* after inserting the given argument(s) at the given position.
* The formal parameters to {@code target} which will be supplied by those
@@ -1229,8 +1402,9 @@ public class MethodHandles {
* @param target the method handle to invoke after the argument is inserted
* @param pos where to insert the argument (zero for the first)
* @param values the series of arguments to insert
- * @return a new method handle which inserts an additional argument,
+ * @return a method handle which inserts an additional argument,
* before calling the original method handle
+ * @see MethodHandle#bindTo
*/
public static
MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
@@ -1263,14 +1437,7 @@ public class MethodHandles {
return result;
}
- @Deprecated // "use MethodHandles.insertArguments instead"
- public static
- MethodHandle insertArgument(MethodHandle target, int pos, Object value) {
- return insertArguments(target, pos, value);
- }
-
/**
- * PROVISIONAL API, WORK IN PROGRESS:
* Produce a method handle which calls the original method handle,
* after dropping the given argument(s) at the given position.
* The type of the new method handle will insert the given argument
@@ -1283,25 +1450,25 @@ public class MethodHandles {
*
- * @param target the method handle to invoke after the argument is dropped
- * @param valueTypes the type(s) of the argument to drop
- * @param pos which argument to drop (zero for the first)
- * @return a new method handle which drops an argument of the given type,
+ * @param target the method handle to invoke after the arguments are dropped
+ * @param valueTypes the type(s) of the argument(s) to drop
+ * @param pos position of first argument to drop (zero for the leftmost)
+ * @return a method handle which drops arguments of the given types,
* before calling the original method handle
*/
public static
@@ -1319,23 +1486,36 @@ public class MethodHandles {
return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos);
}
+ /**
+ * Produce a method handle which calls the original method handle,
+ * after dropping the given argument(s) at the given position.
+ * The type of the new method handle will insert the given argument
+ * type(s), at that position, into the original handle's type.
+ * This method is equivalent to the following code:
+ *
+ * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
+ *
+ * @param target the method handle to invoke after the arguments are dropped
+ * @param valueTypes the type(s) of the argument(s) to drop
+ * @param pos position of first argument to drop (zero for the leftmost)
+ * @return a method handle which drops arguments of the given types,
+ * before calling the original method handle
+ */
public static
MethodHandle dropArguments(MethodHandle target, int pos, Class>... valueTypes) {
return dropArguments(target, pos, Arrays.asList(valueTypes));
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
* Adapt a target method handle {@code target} by pre-processing
* one or more of its arguments, each with its own unary filter function,
* and then calling the target with each pre-processed argument
* replaced by the result of its corresponding filter function.
*
* The pre-processing is performed by one or more method handles,
- * specified in the non-null elements of the {@code filters} array.
- * (If there are no such elements, the original target is returned.)
- * Each filter (that is, each non-null element of {@code filters})
- * is applied to the corresponding argument of the adapter.
+ * specified in the elements of the {@code filters} array.
+ * (If there are no elements in the array, the original target is returned.)
+ * Each filter is applied to the corresponding argument of the adapter.
*
* If a filter {@code F} applies to the {@code N}th argument of
* the method handle, then {@code F} must be a method handle which
@@ -1345,46 +1525,49 @@ public class MethodHandles {
* The return type of {@code F} must be identical to the corresponding
* parameter type of the target.
*
- * It is an error if there are non-null elements of {@code filters}
+ * It is an error if there are elements of {@code filters}
* which do not correspond to argument positions in the target.
- * The actual length of the target array may be any number, it need
- * not be the same as the parameter count of the target type.
- * (This provides an easy way to filter just the first argument or two
- * of a target method handle.)
- *
Here is pseudocode for the resulting adapter:
- *
- * // there are N arguments in the A sequence
- * T target(A[N]...);
- * [i<N] V[i] filter[i](B[i]) = filters[i] ?: identity;
- * T adapter(B[N]... b) {
- * A[N] a...;
- * [i<N] a[i] = filter[i](b[i]);
- * return target(a...);
- * }
+ * Example:
+ *
* @param target the method handle to invoke after arguments are filtered
+ * @param pos the position of the first argument to filter
* @param filters method handles to call initially on filtered arguments
* @return method handle which incorporates the specified argument filtering logic
- * @throws IllegalArgumentException if a non-null element of {@code filters}
- * does not match a corresponding argument type of {@code target}
+ * @throws IllegalArgumentException if an element of {@code filters} is null or
+ * does not match a corresponding argument type of {@code target} as described above
*/
public static
- MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) {
+ MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
MethodType targetType = target.type();
MethodHandle adapter = target;
MethodType adapterType = targetType;
- int pos = -1, maxPos = targetType.parameterCount();
+ int maxPos = targetType.parameterCount();
+ int curPos = pos;
for (MethodHandle filter : filters) {
- pos += 1;
- if (filter == null) continue;
- if (pos >= maxPos)
+ if (curPos >= maxPos)
throw newIllegalArgumentException("too many filters");
MethodType filterType = filter.type();
if (filterType.parameterCount() != 1
- || filterType.returnType() != targetType.parameterType(pos))
+ || filterType.returnType() != targetType.parameterType(curPos))
throw newIllegalArgumentException("target and filter types do not match");
- adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0));
- adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter);
+ adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
+ adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, curPos, filter);
+ curPos += 1;
}
MethodType midType = adapter.type();
if (midType != adapterType)
@@ -1393,7 +1576,48 @@ public class MethodHandles {
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
+ * Adapt a target method handle {@code target} by post-processing
+ * its return value with a unary filter function.
+ *
+ * If a filter {@code F} applies to the return value of
+ * the target method handle, then {@code F} must be a method handle which
+ * takes exactly one argument. The return type of {@code F}
+ * replaces the return type of the target
+ * in the resulting adapted method handle.
+ * The argument type of {@code F} must be identical to the
+ * return type of the target.
+ * Example:
+ *
+ * @param target the method handle to invoke before filtering the return value
+ * @param filter method handle to call on the return value
+ * @return method handle which incorporates the specified return value filtering logic
+ * @throws IllegalArgumentException if {@code filter} is null or
+ * does not match the return type of {@code target} as described above
+ */
+ public static
+ MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
+ MethodType targetType = target.type();
+ MethodType filterType = filter.type();
+ if (filterType.parameterCount() != 1
+ || filterType.parameterType(0) != targetType.returnType())
+ throw newIllegalArgumentException("target and filter types do not match");
+ // FIXME: Too many nodes here.
+ MethodHandle returner = dropArguments(filter, 0, targetType.parameterList());
+ return foldArguments(returner, exactInvoker(target.type()).bindTo(target));
+ }
+
+ /**
* Adapt a target method handle {@code target} by pre-processing
* some of its arguments, and then calling the target with
* the result of the pre-processing, plus all original arguments.
@@ -1410,10 +1634,10 @@ public class MethodHandles {
* The resulting adapter is the same type as the target, except that the
* initial argument type of the target is dropped.
*
- * (Note that {@link #dropArguments} can be used to remove any arguments
+ * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
* that either the {@code combiner} or {@code target} does not wish to receive.
* If some of the incoming arguments are destined only for the combiner,
- * consider using {@link #collectArguments} instead, since those
+ * consider using {@link MethodHandle#asCollector} instead, since those
* arguments will not need to be live on the stack on entry to the
* target.)
*
@@ -1434,7 +1658,7 @@ public class MethodHandles {
* @return method handle which incorporates the specified argument folding logic
* @throws IllegalArgumentException if the first argument type of
* {@code target} is not the same as {@code combiner}'s return type,
- * or if the next {@code foldArgs} argument types of {@code target}
+ * or if the following argument types of {@code target}
* are not identical with the argument types of {@code combiner}
*/
public static
@@ -1443,6 +1667,10 @@ public class MethodHandles {
MethodType combinerType = combiner.type();
int foldArgs = combinerType.parameterCount();
boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
+ if (ok && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1)))
+ ok = false;
+ if (ok && !combinerType.returnType().equals(targetType.parameterType(0)))
+ ok = false;
if (!ok)
throw misMatchedTypes("target and combiner types", targetType, combinerType);
MethodType newType = targetType.dropParameterTypes(0, 1);
@@ -1450,7 +1678,6 @@ public class MethodHandles {
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
* Make a method handle which adapts a target method handle,
* by guarding it with a test, a boolean-valued method handle.
* If the guard fails, a fallback handle is called instead.
@@ -1470,6 +1697,9 @@ public class MethodHandles {
* return fallback(a..., b...);
* }
*
+ * Note that the test arguments ({@code a...} in the pseudocode) cannot
+ * be modified by execution of the test, and so are passed unchanged
+ * from the caller to the target or fallback as appropriate.
* @param test method handle used for test, must return boolean
* @param target method handle to call if test passes
* @param fallback method handle to call if test fails
@@ -1485,40 +1715,19 @@ public class MethodHandles {
MethodType gtype = test.type();
MethodType ttype = target.type();
MethodType ftype = fallback.type();
- if (ttype != ftype)
+ if (!ttype.equals(ftype))
throw misMatchedTypes("target and fallback types", ttype, ftype);
- MethodType gtype2 = ttype.changeReturnType(boolean.class);
- if (gtype2 != gtype) {
- if (gtype.returnType() != boolean.class)
- throw newIllegalArgumentException("guard type is not a predicate "+gtype);
- int gpc = gtype.parameterCount(), tpc = ttype.parameterCount();
- if (gpc < tpc) {
- test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc));
- gtype = test.type();
- }
- if (gtype2 != gtype)
+ if (gtype.returnType() != boolean.class)
+ throw newIllegalArgumentException("guard type is not a predicate "+gtype);
+ List> targs = ttype.parameterList();
+ List> gargs = gtype.parameterList();
+ if (!targs.equals(gargs)) {
+ int gpc = gargs.size(), tpc = targs.size();
+ if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
throw misMatchedTypes("target and test types", ttype, gtype);
+ test = dropArguments(test, gpc, targs.subList(gpc, tpc));
+ gtype = test.type();
}
- /* {
- MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type());
- static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) {
- return z ? t : f;
- }
- static MethodHandle compose(MethodHandle f, MethodHandle g) {
- Class> initargs = g.type().parameterArray();
- f = dropArguments(f, 1, initargs); // ignore 2nd copy of args
- return combineArguments(f, g);
- }
- // choose = \z.(z ? target : fallback)
- MethodHandle choose = findVirtual(MethodHandles.class, "choose",
- MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class));
- choose = appendArgument(choose, target);
- choose = appendArgument(choose, fallback);
- MethodHandle dispatch = compose(choose, test);
- // dispatch = \(a...).(test(a...) ? target : fallback)
- return combineArguments(invoke, dispatch, 0);
- // return \(a...).((test(a...) ? target : fallback).invokeExact(a...))
- } */
return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback);
}
@@ -1527,29 +1736,38 @@ public class MethodHandles {
}
/**
- * PROVISIONAL API, WORK IN PROGRESS:
* Make a method handle which adapts a target method handle,
* by running it inside an exception handler.
* If the target returns normally, the adapter returns that value.
* If an exception matching the specified type is thrown, the fallback
* handle is called instead on the exception, plus the original arguments.
*
- * The handler must have leading parameter of {@code exType} or a supertype,
- * followed by arguments which correspond (how? TBD) to
- * all the parameters of the target.
- * The target and handler must return the same type.
+ * The target and handler must have the same corresponding
+ * argument and return types, except that handler may omit trailing arguments
+ * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
+ * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
*
Here is pseudocode for the resulting adapter:
*
- * T target(A...);
+ * T target(A..., B...);
* T handler(ExType, A...);
- * T adapter(A... a) {
+ * T adapter(A... a, B... b) {
* try {
- * return target(a...);
+ * return target(a..., b...);
* } catch (ExType ex) {
* return handler(ex, a...);
* }
* }
*
+ * Note that the saved arguments ({@code a...} in the pseudocode) cannot
+ * be modified by execution of the target, and so are passed unchanged
+ * from the caller to the handler, if the handler is invoked.
+ *
+ * The target and handler must return the same type, even if the handler
+ * always throws. (This might happen, for instance, because the handler
+ * is simulating a {@code finally} clause).
+ * To create such a throwing handler, compose the handler creation logic
+ * with {@link #throwException throwException},
+ * in order to create a method handle of the correct return type.
* @param target method handle to call
* @param exType the type of exception which the handler will catch
* @param handler method handle to call if a matching exception is thrown
@@ -1563,16 +1781,23 @@ public class MethodHandles {
MethodHandle catchException(MethodHandle target,
Class extends Throwable> exType,
MethodHandle handler) {
- MethodType targetType = target.type();
- MethodType handlerType = handler.type();
- boolean ok = (targetType.parameterCount() ==
- handlerType.parameterCount() - 1);
-// for (int i = 0; ok && i < numExArgs; i++) {
-// if (targetType.parameterType(i) != handlerType.parameterType(1+i))
-// ok = false;
-// }
- if (!ok)
- throw newIllegalArgumentException("target and handler types do not match");
+ MethodType ttype = target.type();
+ MethodType htype = handler.type();
+ if (htype.parameterCount() < 1 ||
+ !htype.parameterType(0).isAssignableFrom(exType))
+ throw newIllegalArgumentException("handler does not accept exception type "+exType);
+ if (htype.returnType() != ttype.returnType())
+ throw misMatchedTypes("target and handler return types", ttype, htype);
+ List> targs = ttype.parameterList();
+ List> hargs = htype.parameterList();
+ hargs = hargs.subList(1, hargs.size()); // omit leading parameter from handler
+ if (!targs.equals(hargs)) {
+ int hpc = hargs.size(), tpc = targs.size();
+ if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
+ throw misMatchedTypes("target and handler types", ttype, htype);
+ handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
+ htype = handler.type();
+ }
return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler);
}
@@ -1590,10 +1815,11 @@ public class MethodHandles {
}
/**
- * Produce a wrapper instance of the given "SAM" type which redirects its calls to the given method handle.
- * A SAM type is a type which declares a single abstract method.
- * Additionally, it must have either no constructor (as an interface)
- * or have a public or protected constructor of zero arguments (as a class).
+ * PROVISIONAL API, WORK IN PROGRESS:
+ * Produce a wrapper instance of the given "SAM" interface which redirects
+ * its calls to the given method handle.
+ * A SAM interface is an interface which declares a single abstract method.
+ * The type must be public. (No additional access checks are performed.)
*
* The resulting instance of the required SAM type will respond to
* invocation of the SAM type's single abstract method by calling
@@ -1605,9 +1831,9 @@ public class MethodHandles {
* The method handle may throw an undeclared exception,
* which means any checked exception (or other checked throwable)
* not declared by the SAM type's single abstract method.
- * If this happens, the throwable will be wrapped in an instance
- * of {@link UndeclaredThrowableException} and thrown in that
- * wrapped form.
+ * If this happens, the throwable will be wrapped in an instance of
+ * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
+ * and thrown in that wrapped form.
*
* The wrapper instance is guaranteed to be of a non-public
* implementation class C in a package containing no classes
@@ -1618,19 +1844,36 @@ public class MethodHandles {
*
the SAM type itself and any methods in the SAM type
*
the supertypes of the SAM type (if any) and their methods
*
{@link Object} and its methods
- *
{@link MethodHandleProvider} and its methods
+ *
{@link java.dyn.AsInstanceObject AsInstanceObject} and its methods
*
*
+ * (Note: When determining the unique abstract method of a SAM interface,
+ * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
+ * are disregarded. For example, {@link java.util.Comparator} is a SAM interface,
+ * even though it re-declares the {@code Object.equals} method.)
+ *
* No stable mapping is promised between the SAM type and
* the implementation class C. Over time, several implementation
* classes might be used for the same SAM type.
*
* This method is not guaranteed to return a distinct
- * wrapper object for each separate call. If the JVM is able
- * to prove that a wrapper has already been created for a given
+ * wrapper object for each separate call. If the implementation is able
+ * to prove that a wrapper of the required SAM type
+ * has already been created for a given
* method handle, or for another method handle with the
- * same behavior, the JVM may return that wrapper in place of
+ * same behavior, the implementation may return that wrapper in place of
* a new wrapper.
+ *
+ * This method is designed to apply to common use cases
+ * where a single method handle must interoperate with
+ * a type (class or interface) that implements a function-like
+ * API. Additional variations, such as SAM classes with
+ * private constructors, or interfaces with multiple but related
+ * entry points, must be covered by hand-written or automatically
+ * generated adapter classes. In those cases, consider implementing
+ * {@link java.dyn.MethodHandles.AsInstanceObject AsInstanceObject}
+ * in the adapters, so that generic code can extract the underlying
+ * method handle without knowing where the SAM adapter came from.
* @param target the method handle to invoke from the wrapper
* @param samType the desired type of the wrapper, a SAM type
* @return a correctly-typed wrapper for the given {@code target}
@@ -1639,38 +1882,93 @@ public class MethodHandles {
*/
// ISSUE: Should we delegate equals/hashCode to the targets?
// Not useful unless there is a stable equals/hashCode behavior
- // for MethodHandle, and for MethodHandleProvider.asMethodHandle.
+ // for MethodHandle, but there isn't.
public static
- T asInstance(MethodHandle target, Class samType) {
+ T asInstance(final MethodHandle target, final Class samType) {
// POC implementation only; violates the above contract several ways
final Method sam = getSamMethod(samType);
if (sam == null)
throw new IllegalArgumentException("not a SAM type: "+samType.getName());
MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
if (!samMT.equals(target.type()))
- throw new IllegalArgumentException("wrong method type");
- final MethodHandle mh = target;
+ throw new IllegalArgumentException("wrong method type: "+target+" should match "+sam);
return samType.cast(Proxy.newProxyInstance(
samType.getClassLoader(),
- new Class[]{ samType, MethodHandleProvider.class },
+ new Class[]{ samType, AsInstanceObject.class },
new InvocationHandler() {
+ private Object getArg(String name) {
+ if ((Object)name == "getAsInstanceTarget") return target;
+ if ((Object)name == "getAsInstanceType") return samType;
+ throw new AssertionError();
+ }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if (method.getDeclaringClass() == MethodHandleProvider.class) {
- return method.invoke(mh, args);
- }
- assert method.equals(sam) : method;
- return mh.invokeVarargs(args);
+ if (method.getDeclaringClass() == AsInstanceObject.class)
+ return getArg(method.getName());
+ if (method.equals(sam))
+ return target.invokeVarargs(args);
+ if (isObjectMethod(method))
+ return callObjectMethod(this, method, args);
+ throw new InternalError();
}
}));
}
+ /**
+ * PROVISIONAL API, WORK IN PROGRESS:
+ * Interface implemented by every object which is produced by {@link #asInstance asInstance}.
+ * The methods of this interface allow a caller to recover the parameters
+ * to {@code asInstance}.
+ * This allows applications to repeatedly convert between method handles
+ * and SAM objects, without the risk of creating unbounded delegation chains.
+ */
+ public interface AsInstanceObject {
+ /** Produce or recover a target method handle which is behaviorally
+ * equivalent to the SAM method of this object.
+ */
+ public MethodHandle getAsInstanceTarget();
+ /** Recover the SAM type for which this object was created.
+ */
+ public Class> getAsInstanceType();
+ }
+
+ private static
+ boolean isObjectMethod(Method m) {
+ switch (m.getName()) {
+ case "toString":
+ return (m.getReturnType() == String.class
+ && m.getParameterTypes().length == 0);
+ case "hashCode":
+ return (m.getReturnType() == int.class
+ && m.getParameterTypes().length == 0);
+ case "equals":
+ return (m.getReturnType() == boolean.class
+ && m.getParameterTypes().length == 1
+ && m.getParameterTypes()[0] == Object.class);
+ }
+ return false;
+ }
+
+ private static
+ Object callObjectMethod(Object self, Method m, Object[] args) {
+ assert(isObjectMethod(m)) : m;
+ switch (m.getName()) {
+ case "toString":
+ return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
+ case "hashCode":
+ return System.identityHashCode(self);
+ case "equals":
+ return (self == args[0]);
+ }
+ return null;
+ }
+
private static
Method getSamMethod(Class> samType) {
Method sam = null;
for (Method m : samType.getMethods()) {
int mod = m.getModifiers();
if (Modifier.isAbstract(mod)) {
- if (sam != null)
+ if (sam != null && !isObjectMethod(sam))
return null; // too many abstract methods
sam = m;
}
@@ -1691,4 +1989,9 @@ public class MethodHandles {
}
return null;
}
+
+ /*non-public*/
+ static MethodHandle withTypeHandler(MethodHandle target, MethodHandle typeHandler) {
+ return MethodHandleImpl.withTypeHandler(IMPL_TOKEN, target, typeHandler);
+ }
}
diff --git a/jdk/src/share/classes/java/dyn/MethodType.java b/jdk/src/share/classes/java/dyn/MethodType.java
index e7e948bdb7e..9045c8319a7 100644
--- a/jdk/src/share/classes/java/dyn/MethodType.java
+++ b/jdk/src/share/classes/java/dyn/MethodType.java
@@ -56,21 +56,33 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
*
* This type can be created only by factory methods.
* All factory methods may cache values, though caching is not guaranteed.
+ * Some factory methods are static, while others are virtual methods which
+ * modify precursor method types, e.g., by changing a selected parameter.
+ *
+ * Factory methods which operate on groups of parameter types
+ * are systematically presented in two versions, so that both Java arrays and
+ * Java lists can be used to work with groups of parameter types.
+ * The query methods {@code parameterArray} and {@code parameterList}
+ * also provide a choice between arrays and lists.
*
* {@code MethodType} objects are sometimes derived from bytecode instructions
* such as {@code invokedynamic}, specifically from the type descriptor strings associated
* with the instructions in a class file's constant pool.
- * When this occurs, any classes named in the descriptor strings must be loaded.
- * (But they need not be initialized.)
- * This loading may occur at any time before the {@code MethodType} object is first derived.
*
- * Like classes and strings, method types can be represented directly
- * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
- * Loading such a constant causes its component classes to be loaded as necessary.
+ * Like classes and strings, method types can also be represented directly
+ * in a class file's constant pool as constants. The may be loaded by an {@code ldc}
+ * instruction which refers to a suitable {@code CONSTANT_MethodType} constant pool entry.
+ * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
+ * For more details, see the package summary.
+ *
+ * When the JVM materializes a {@code MethodType} from a descriptor string,
+ * all classes named in the descriptor must be accessible, and will be loaded.
+ * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
+ * This loading may occur at any time before the {@code MethodType} object is first derived.
* @author John Rose, JSR 292 EG
*/
public final
-class MethodType implements java.lang.reflect.Type {
+class MethodType {
private final Class> rtype;
private final Class>[] ptypes;
private MethodTypeForm form; // erased form, plus cached data about primitives
@@ -119,7 +131,7 @@ class MethodType implements java.lang.reflect.Type {
for (Class> ptype : ptypes) {
ptype.equals(ptype); // null check
if (ptype == void.class)
- throw newIllegalArgumentException("void parameter: "+this);
+ throw newIllegalArgumentException("parameter type cannot be void");
}
}
@@ -139,10 +151,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType methodType(Class> rtype, Class>[] ptypes) {
return makeImpl(rtype, ptypes, false);
}
- @Deprecated public static
- MethodType make(Class> rtype, Class>[] ptypes) {
- return methodType(rtype, ptypes);
- }
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */
public static
@@ -150,10 +158,6 @@ class MethodType implements java.lang.reflect.Type {
boolean notrust = false; // random List impl. could return evil ptypes array
return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
}
- @Deprecated public static
- MethodType make(Class> rtype, List extends Class>> ptypes) {
- return methodType(rtype, ptypes);
- }
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The leading parameter type is prepended to the remaining array.
@@ -165,10 +169,6 @@ class MethodType implements java.lang.reflect.Type {
System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
return makeImpl(rtype, ptypes1, true);
}
- @Deprecated public static
- MethodType make(Class> rtype, Class> ptype0, Class>... ptypes) {
- return methodType(rtype, ptype0, ptypes);
- }
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has no parameter types.
@@ -177,10 +177,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType methodType(Class> rtype) {
return makeImpl(rtype, NO_PTYPES, true);
}
- @Deprecated public static
- MethodType make(Class> rtype) {
- return methodType(rtype);
- }
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has the single given parameter type.
@@ -189,10 +185,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType methodType(Class> rtype, Class> ptype0) {
return makeImpl(rtype, new Class>[]{ ptype0 }, true);
}
- @Deprecated public static
- MethodType make(Class> rtype, Class> ptype0) {
- return methodType(rtype, ptype0);
- }
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has the same parameter types as {@code ptypes},
@@ -202,10 +194,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType methodType(Class> rtype, MethodType ptypes) {
return makeImpl(rtype, ptypes.ptypes, true);
}
- @Deprecated public static
- MethodType make(Class> rtype, MethodType ptypes) {
- return methodType(rtype, ptypes);
- }
/**
* Sole factory method to find or create an interned method type.
@@ -275,10 +263,6 @@ class MethodType implements java.lang.reflect.Type {
}
return mt;
}
- @Deprecated public static
- MethodType makeGeneric(int objectArgCount, boolean varargs) {
- return genericMethodType(objectArgCount, varargs);
- }
/**
* All parameters and the return type will be Object.
@@ -290,10 +274,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType genericMethodType(int objectArgCount) {
return genericMethodType(objectArgCount, false);
}
- @Deprecated public static
- MethodType makeGeneric(int objectArgCount) {
- return genericMethodType(objectArgCount);
- }
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the index (zero-based) of the parameter type to change
@@ -307,18 +287,6 @@ class MethodType implements java.lang.reflect.Type {
return makeImpl(rtype, nptypes, true);
}
- /** Convenience method for {@link #insertParameterTypes}.
- * @deprecated Use {@link #insertParameterTypes} instead.
- */
- @Deprecated
- public MethodType insertParameterType(int num, Class> nptype) {
- int len = ptypes.length;
- Class>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1);
- System.arraycopy(nptypes, num, nptypes, num+1, len-num);
- nptypes[num] = nptype;
- return makeImpl(rtype, nptypes, true);
- }
-
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the position (zero-based) of the inserted parameter type(s)
* @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
@@ -336,6 +304,22 @@ class MethodType implements java.lang.reflect.Type {
return makeImpl(rtype, nptypes, true);
}
+ /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
+ * @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list
+ * @return the same type, except with the selected parameter(s) appended
+ */
+ public MethodType appendParameterTypes(Class>... ptypesToInsert) {
+ return insertParameterTypes(parameterCount(), ptypesToInsert);
+ }
+
+ /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
+ * @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list
+ * @return the same type, except with the selected parameter(s) appended
+ */
+ public MethodType appendParameterTypes(List> ptypesToInsert) {
+ return insertParameterTypes(parameterCount(), ptypesToInsert);
+ }
+
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the position (zero-based) of the inserted parameter type(s)
* @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
@@ -377,14 +361,6 @@ class MethodType implements java.lang.reflect.Type {
return makeImpl(rtype, nptypes, true);
}
- /** Convenience method for {@link #dropParameterTypes}.
- * @deprecated Use {@link #dropParameterTypes} instead.
- */
- @Deprecated
- public MethodType dropParameterType(int num) {
- return dropParameterTypes(num, num+1);
- }
-
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param nrtype a return parameter type to replace the old one with
* @return the same type, except with the return type change
@@ -552,7 +528,9 @@ class MethodType implements java.lang.reflect.Type {
* parenthesis enclosed, comma separated list of type names,
* followed immediately by the return type.
*
- * If a type name is array, it the base type followed
+ * Each type is represented by its
+ * {@link java.lang.Class#getSimpleName simple name}.
+ * If a type name name is array, it the base type followed
* by [], rather than the Class.getName of the array type.
*/
@Override
@@ -561,35 +539,13 @@ class MethodType implements java.lang.reflect.Type {
sb.append("(");
for (int i = 0; i < ptypes.length; i++) {
if (i > 0) sb.append(",");
- putName(sb, ptypes[i]);
+ sb.append(ptypes[i].getSimpleName());
}
sb.append(")");
- putName(sb, rtype);
+ sb.append(rtype.getSimpleName());
return sb.toString();
}
- static void putName(StringBuilder sb, Class> cls) {
- int brackets = 0;
- while (cls.isArray()) {
- cls = cls.getComponentType();
- brackets++;
- }
- String n = cls.getName();
- /*
- if (n.startsWith("java.lang.")) {
- String nb = n.substring("java.lang.".length());
- if (nb.indexOf('.') < 0) n = nb;
- } else if (n.indexOf('.') < 0) {
- n = "."+n; // anonymous package
- }
- */
- sb.append(n);
- while (brackets > 0) {
- sb.append("[]");
- brackets--;
- }
- }
-
/// Queries which have to do with the bytecode architecture
/** The number of JVM stack slots required to invoke a method
@@ -690,14 +646,4 @@ class MethodType implements java.lang.reflect.Type {
public String toMethodDescriptorString() {
return BytecodeDescriptor.unparse(this);
}
-
- /** Temporary alias for toMethodDescriptorString; delete after M3. */
- public String toBytecodeString() {
- return toMethodDescriptorString();
- }
- /** Temporary alias for fromMethodDescriptorString; delete after M3. */
- public static MethodType fromBytecodeString(String descriptor, ClassLoader loader)
- throws IllegalArgumentException, TypeNotPresentException {
- return fromMethodDescriptorString(descriptor, loader);
- }
}
diff --git a/jdk/src/share/classes/java/dyn/MutableCallSite.java b/jdk/src/share/classes/java/dyn/MutableCallSite.java
new file mode 100644
index 00000000000..b33c41c1a5a
--- /dev/null
+++ b/jdk/src/share/classes/java/dyn/MutableCallSite.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.dyn;
+
+import sun.dyn.*;
+import sun.dyn.empty.Empty;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A {@code MutableCallSite} is a {@link CallSite} whose target variable
+ * behaves like an ordinary field.
+ * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
+ * all calls to the site's current target.
+ * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
+ * also delegates each call to the site's current target.
+ *
+ * Here is an example of a mutable call site which introduces a
+ * state variable into a method handle chain.
+ *
+MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
+MethodHandle MH_name = name.dynamicInvoker();
+MethodType MT_str2 = MethodType.methodType(String.class, String.class);
+MethodHandle MH_upcase = MethodHandles.lookup()
+ .findVirtual(String.class, "toUpperCase", MT_str2);
+MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
+name.setTarget(MethodHandles.constant(String.class, "Rocky"));
+assertEquals("ROCKY", (String) worker1.invokeExact());
+name.setTarget(MethodHandles.constant(String.class, "Fred"));
+assertEquals("FRED", (String) worker1.invokeExact());
+// (mutation can be continued indefinitely)
+ *
+ *
+ * The same call site may be used in several places at once.
+ *
+ * Non-synchronization of target values:
+ * A write to a mutable call site's target does not force other threads
+ * to become aware of the updated value. Threads which do not perform
+ * suitable synchronization actions relative to the updated call site
+ * may cache the old target value and delay their use of the new target
+ * value indefinitely.
+ * (This is a normal consequence of the Java Memory Model as applied
+ * to object fields.)
+ *
+ * The {@link #sync sync} operation provides a way to force threads
+ * to accept a new target value, even if there is no other synchronization.
+ *
+ * For target values which will be frequently updated, consider using
+ * a {@linkplain VolatileCallSite volatile call site} instead.
+ * @author John Rose, JSR 292 EG
+ */
+public class MutableCallSite extends CallSite {
+ /**
+ * Make a blank call site object with the given method type.
+ * An initial target method is supplied which will throw
+ * an {@link IllegalStateException} if called.
+ *
+ * Before this {@code CallSite} object is returned from a bootstrap method,
+ * it is usually provided with a more useful target method,
+ * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
+ * @throws NullPointerException if the proposed type is null
+ */
+ public MutableCallSite(MethodType type) {
+ super(type);
+ }
+
+ /**
+ * Make a blank call site object, possibly equipped with an initial target method handle.
+ * @param target the method handle which will be the initial target of the call site
+ * @throws NullPointerException if the proposed target is null
+ */
+ public MutableCallSite(MethodHandle target) {
+ super(target);
+ }
+
+ /**
+ * Perform a synchronization operation on each call site in the given array,
+ * forcing all other threads to throw away any cached values previously
+ * loaded from the target of any of the call sites.
+ *
+ * This operation does not reverse any calls that have already started
+ * on an old target value.
+ * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
+ *
+ * The overall effect is to force all future readers of each call site's target
+ * to accept the most recently stored value.
+ * ("Most recently" is reckoned relative to the {@code sync} itself.)
+ * Conversely, the {@code sync} call may block until all readers have
+ * (somehow) decached all previous versions of each call site's target.
+ *
+ * To avoid race conditions, calls to {@code setTarget} and {@code sync}
+ * should generally be performed under some sort of mutual exclusion.
+ * Note that reader threads may observe an updated target as early
+ * as the {@code setTarget} call that install the value
+ * (and before the {@code sync} that confirms the value).
+ * On the other hand, reader threads may observe previous versions of
+ * the target until the {@code sync} call returns
+ * (and after the {@code setTarget} that attempts to convey the updated version).
+ *
+ * In terms of the Java Memory Model, this operation performs a synchronization
+ * action which is comparable in effect to the writing of a volatile variable
+ * by the current thread, and an eventual volatile read by every other thread
+ * that may access one of the affected call sites.
+ *
+ * The following effects are apparent, for each individual call site {@code S}:
+ *
+ *
A new volatile variable {@code V} is created, and written by the current thread.
+ * As defined by the JMM, this write is a global synchronization event.
+ *
As is normal with thread-local ordering of write events,
+ * every action already performed by the current thread is
+ * taken to happen before the volatile write to {@code V}.
+ * (In some implementations, this means that the current thread
+ * performs a global release operation.)
+ *
Specifically, the write to the current target of {@code S} is
+ * taken to happen before the volatile write to {@code V}.
+ *
The volatile write to {@code V} is placed
+ * (in an implementation specific manner)
+ * in the global synchronization order.
+ *
Consider an arbitrary thread {@code T} (other than the current thread).
+ * If {@code T} executes a synchronization action {@code A}
+ * after the volatile write to {@code V} (in the global synchronization order),
+ * it is therefore required to see either the current target
+ * of {@code S}, or a later write to that target,
+ * if it executes a read on the target of {@code S}.
+ * (This constraint is called "synchronization-order consistency".)
+ *
The JMM specifically allows optimizing compilers to elide
+ * reads or writes of variables that are known to be useless.
+ * Such elided reads and writes have no effect on the happens-before
+ * relation. Regardless of this fact, the volatile {@code V}
+ * will not be elided, even though its written value is
+ * indeterminate and its read value is not used.
+ *
+ * Because of the last point, the implementation behaves as if a
+ * volatile read of {@code V} were performed by {@code T}
+ * immediately after its action {@code A}. In the local ordering
+ * of actions in {@code T}, this read happens before any future
+ * read of the target of {@code S}. It is as if the
+ * implementation arbitrarily picked a read of {@code S}'s target
+ * by {@code T}, and forced a read of {@code V} to precede it,
+ * thereby ensuring communication of the new target value.
+ *
+ * As long as the constraints of the Java Memory Model are obeyed,
+ * implementations may delay the completion of a {@code sync}
+ * operation while other threads ({@code T} above) continue to
+ * use previous values of {@code S}'s target.
+ * However, implementations are (as always) encouraged to avoid
+ * livelock, and to eventually require all threads to take account
+ * of the updated target.
+ *
+ * This operation is likely to be expensive and should be used sparingly.
+ * If possible, it should be buffered for batch processing on sets of call sites.
+ *
+ * (This is a static method on a set of call sites, not a
+ * virtual method on a single call site, for performance reasons.
+ * Some implementations may incur a large fixed overhead cost
+ * for processing one or more synchronization operations,
+ * but a small incremental cost for each additional call site.
+ * In any case, this operation is likely to be costly, since
+ * other threads may have to be somehow interrupted
+ * in order to make them notice the updated target value.
+ * However, it may be observed that a single call to synchronize
+ * several sites has the same formal effect as many calls,
+ * each on just one of the sites.)
+ *
+ * Simple implementations of {@code MutableCallSite} may use
+ * a volatile variable for the target of a mutable call site.
+ * In such an implementation, the {@code sync} method can be a no-op,
+ * and yet it will conform to the JMM behavior documented above.
+ */
+ public static void sync(MutableCallSite[] sites) {
+ STORE_BARRIER.lazySet(0);
+ // FIXME: NYI
+ }
+ private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
+}
diff --git a/jdk/src/share/classes/java/dyn/Switcher.java b/jdk/src/share/classes/java/dyn/Switcher.java
new file mode 100644
index 00000000000..b0838764b44
--- /dev/null
+++ b/jdk/src/share/classes/java/dyn/Switcher.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.dyn;
+
+/**
+ *
+ * A {@code Switcher} is an object which can publish state transitions to other threads.
+ * A switcher is initially in the valid state, but may at any time be
+ * changed to the invalid state. Invalidation cannot be reversed.
+ *
+ * A single switcher may be used to create any number of guarded method handle pairs.
+ * Each guarded pair is wrapped in a new method handle {@code M},
+ * which is permanently associated with the switcher that created it.
+ * Each pair consists of a target {@code T} and a fallback {@code F}.
+ * While the switcher is valid, invocations to {@code M} are delegated to {@code T}.
+ * After it is invalidated, invocations are delegated to {@code F}.
+ *
+ * Invalidation is global and immediate, as if the switcher contained a
+ * volatile boolean variable consulted on every call to {@code M}.
+ * The invalidation is also permanent, which means the switcher
+ * can change state only once.
+ *
+ * Here is an example of a switcher in action:
+ *
+MethodType MT_str2 = MethodType.methodType(String.class, String.class);
+MethodHandle MH_strcat = MethodHandles.lookup()
+ .findVirtual(String.class, "concat", MT_str2);
+Switcher switcher = new Switcher();
+// the following steps may be repeated to re-use the same switcher:
+MethodHandle worker1 = strcat;
+MethodHandle worker2 = MethodHandles.permuteArguments(strcat, MT_str2, 1, 0);
+MethodHandle worker = switcher.guardWithTest(worker1, worker2);
+assertEquals("method", (String) worker.invokeExact("met", "hod"));
+switcher.invalidate();
+assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
+ *
+ *
+ * Implementation Note:
+ * A switcher behaves as if implemented on top of {@link MutableCallSite},
+ * approximately as follows:
+ *
+public class Switcher {
+ private static final MethodHandle
+ K_true = MethodHandles.constant(boolean.class, true),
+ K_false = MethodHandles.constant(boolean.class, false);
+ private final MutableCallSite mcs;
+ private final MethodHandle mcsInvoker;
+ public Switcher() {
+ this.mcs = new MutableCallSite(K_true);
+ this.mcsInvoker = mcs.dynamicInvoker();
+ }
+ public MethodHandle guardWithTest(
+ MethodHandle target, MethodHandle fallback) {
+ // Note: mcsInvoker is of type boolean().
+ // Target and fallback may take any arguments, but must have the same type.
+ return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
+ }
+ public static void invalidateAll(Switcher[] switchers) {
+ List mcss = new ArrayList<>();
+ for (Switcher s : switchers) mcss.add(s.mcs);
+ for (MutableCallSite mcs : mcss) mcs.setTarget(K_false);
+ MutableCallSite.sync(mcss.toArray(new MutableCallSite[0]));
+ }
+}
+ *
+ * @author Remi Forax, JSR 292 EG
+ */
+public class Switcher {
+ private static final MethodHandle
+ K_true = MethodHandles.constant(boolean.class, true),
+ K_false = MethodHandles.constant(boolean.class, false);
+
+ private final MutableCallSite mcs;
+ private final MethodHandle mcsInvoker;
+
+ /** Create a switcher. */
+ public Switcher() {
+ this.mcs = new MutableCallSite(K_true);
+ this.mcsInvoker = mcs.dynamicInvoker();
+ }
+
+ /**
+ * Return a method handle which always delegates either to the target or the fallback.
+ * The method handle will delegate to the target exactly as long as the switcher is valid.
+ * After that, it will permanently delegate to the fallback.
+ *
+ * The target and fallback must be of exactly the same method type,
+ * and the resulting combined method handle will also be of this type.
+ * @see MethodHandles#guardWithTest
+ */
+ public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
+ if (mcs.getTarget() == K_false)
+ return fallback; // already invalid
+ return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
+ }
+
+ /** Set all of the given switchers into the invalid state. */
+ public static void invalidateAll(Switcher[] switchers) {
+ MutableCallSite[] sites = new MutableCallSite[switchers.length];
+ int fillp = 0;
+ for (Switcher switcher : switchers) {
+ sites[fillp++] = switcher.mcs;
+ switcher.mcs.setTarget(K_false);
+ }
+ MutableCallSite.sync(sites);
+ }
+}
diff --git a/jdk/src/share/classes/java/dyn/VolatileCallSite.java b/jdk/src/share/classes/java/dyn/VolatileCallSite.java
new file mode 100644
index 00000000000..8c603b91915
--- /dev/null
+++ b/jdk/src/share/classes/java/dyn/VolatileCallSite.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.dyn;
+
+import java.util.List;
+
+/**
+ * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
+ * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
+ * to its call site target immediately, even if the update occurs in another thread.
+ * There may be a performance penalty for such tight coupling between threads.
+ *
+ * Unlike {@code MutableCallSite}, there is no
+ * {@linkplain MutableCallSite#sync sync operation} on volatile
+ * call sites, since every write to a volatile variable is implicitly
+ * synchronized with reader threads.
+ *
+ * In other respects, a {@code VolatileCallSite} is interchangeable
+ * with {@code MutableCallSite}.
+ * @see MutableCallSite
+ * @author John Rose, JSR 292 EG
+ */
+public class VolatileCallSite extends CallSite {
+ /** Create a call site with a volatile target.
+ * The initial target is set to a method handle
+ * of the given type which will throw {@code IllegalStateException}.
+ * @throws NullPointerException if the proposed type is null
+ */
+ public VolatileCallSite(MethodType type) {
+ super(type);
+ }
+
+ /** Create a call site with a volatile target.
+ * The target is set to the given value.
+ * @throws NullPointerException if the proposed target is null
+ */
+ public VolatileCallSite(MethodHandle target) {
+ super(target);
+ }
+
+ /** Internal override to nominally final getTarget. */
+ @Override
+ MethodHandle getTarget0() {
+ return getTargetVolatile();
+ }
+
+ /**
+ * Set the target method of this call site, as a volatile variable.
+ * Has the same effect as {@link CallSite#setTarget CallSite.setTarget}, with the additional
+ * effects associated with volatiles, in the Java Memory Model.
+ */
+ @Override public void setTarget(MethodHandle newTarget) {
+ checkTargetChange(getTargetVolatile(), newTarget);
+ setTargetVolatile(newTarget);
+ }
+}
diff --git a/jdk/src/share/classes/java/dyn/package-info.java b/jdk/src/share/classes/java/dyn/package-info.java
index 37555be14b4..41d97b8b155 100644
--- a/jdk/src/share/classes/java/dyn/package-info.java
+++ b/jdk/src/share/classes/java/dyn/package-info.java
@@ -24,7 +24,6 @@
*/
/**
- * PROVISIONAL API, WORK IN PROGRESS:
* This package contains dynamic language support provided directly by
* the Java core class libraries and virtual machine.
*
@@ -42,13 +41,6 @@
* argument and return value conversions are applied.
*
*
- *
In source code, the class {@link java.dyn.InvokeDynamic InvokeDynamic} appears to accept
- * any static method invocation, of any name and any signature.
- * But instead of emitting
- * an {@code invokestatic} instruction for such a call, the Java compiler emits
- * an {@code invokedynamic} instruction with the given name and signature.
- *
- *
*
The JVM bytecode format supports immediate constants of
* the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
*
@@ -56,51 +48,68 @@
*
*
Corresponding JVM bytecode format changes
* The following low-level information is presented here as a preview of
- * changes being made to the Java Virtual Machine specification for JSR 292.
+ * changes being made to the Java Virtual Machine specification for JSR 292.
+ * This information will be incorporated in a future version of the JVM specification.
*
- *
{@code invokedynamic} instruction format
+ *
{@code invokedynamic} instruction format
* In bytecode, an {@code invokedynamic} instruction is formatted as five bytes.
* The first byte is the opcode 186 (hexadecimal {@code BA}).
* The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
* The final two bytes are reserved for future use and required to be zero.
* The constant pool reference of an {@code invokedynamic} instruction is to a entry
- * with tag {@code CONSTANT_InvokeDynamic} (decimal 17). See below for its format.
- * The entry specifies the bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant),
- * the dynamic invocation name, and the argument types and return type of the call.
+ * with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format.
+ * (The tag value 17 is also temporarily allowed. See below.)
+ * The entry specifies the following information:
+ *
+ *
a bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant)
+ *
the dynamic invocation name (a UTF8 string)
+ *
the argument and return types of the call (encoded as a signature in a UTF8 string)
+ *
optionally, a sequence of additional static arguments to the bootstrap method ({@code ldc}-type constants)
+ *
*
* Each instance of an {@code invokedynamic} instruction is called a dynamic call site.
* Multiple instances of an {@code invokedynamic} instruction can share a single
* {@code CONSTANT_InvokeDynamic} entry.
* In any case, distinct call sites always have distinct linkage state.
*
- * Moreover, for the purpose of distinguishing dynamic call sites,
- * the JVM is allowed (but not required) to make internal copies
- * of {@code invokedynamic} instructions, each one
- * constituting a separate dynamic call site with its own linkage state.
- * Such copying, if it occurs, cannot be observed except indirectly via
- * execution of bootstrap methods and target methods.
- *
* A dynamic call site is originally in an unlinked state. In this state, there is
* no target method for the call site to invoke.
* A dynamic call site is linked by means of a bootstrap method,
* as described below.
- *
- * (Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
- * instead of a {@code CONSTANT_InvokeDynamic}. In earlier, obsolete versions of this API, the
- * bootstrap method was specified dynamically, in a per-class basis, during class initialization.)
*
- *
constant pool entries for {@code invokedynamic} instructions
- * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 17),
- * it must contain exactly four more bytes.
- * The first two bytes after the tag must be an index to a {@code CONSTANT_MethodHandle}
- * entry, and the second two bytes must be an index to a {@code CONSTANT_NameAndType}.
+ *
+ * (Historic Note: Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
+ * instead of a {@code CONSTANT_InvokeDynamic}. In earlier, obsolete versions of this API, the
+ * bootstrap method was specified dynamically, in a per-class basis, during class initialization.)
+ *
+ *
constant pool entries for {@code invokedynamic} instructions
+ * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
+ * it must contain exactly four more bytes after the tag.
+ * These bytes are interpreted as two 16-bit indexes, in the usual {@code u2} format.
+ * The first pair of bytes after the tag must be an index into a side table called the
+ * bootstrap method table, which is stored in the {@code BootstrapMethods}
+ * attribute as described below.
+ * The second pair of bytes must be an index to a {@code CONSTANT_NameAndType}.
+ * This table is not part of the constant pool. Instead, it is stored
+ * in a class attribute named {@code BootstrapMethods}, described below.
+ *
* The first index specifies a bootstrap method used by the associated dynamic call sites.
* The second index specifies the method name, argument types, and return type of the dynamic call site.
* The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
- * except that the {@code CONSTANT_Class} reference in a {@code CONSTANT_Methodref} entry
- * is replaced by a bootstrap method reference.
+ * except that the bootstrap method specifier reference replaces
+ * the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
+ *
+ * Some older JVMs may allow an older constant pool entry tag of decimal 17.
+ * The format and behavior of a constant pool entry with this tag is identical to
+ * an entry with a tag of decimal 18, except that the first index refers directly
+ * to a {@code CONSTANT_MethodHandle} to use as the bootstrap method.
+ * This format does not require the bootstrap method table.
*
- *
constant pool entries for {@code MethodType}s
+ *
+ * (Note: The Proposed Final Draft of this specification is likely to support
+ * only the tag 18, not the tag 17.)
+ *
+ *
constant pool entries for {@linkplain java.dyn.MethodType method types}
* If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
* it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
* entry which represents a method type signature.
@@ -113,7 +122,7 @@
* Access checking and error reporting is performed exactly as it is for
* references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
*
- *
constant pool entries for {@code MethodHandle}s
+ *
constant pool entries for {@linkplain java.dyn.MethodHandle method handles}
* If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
* it must contain exactly three more bytes. The first byte after the tag is a subtag
* value which must be in the range 1 through 9, and the last two must be an index to a
@@ -129,7 +138,7 @@
*
* As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
* the {@code Class} or {@code MethodType} object which reifies the field or method's
- * type is created. Any classes mentioned in this reificaiton will be loaded if necessary,
+ * type is created. Any classes mentioned in this reification will be loaded if necessary,
* but not initialized, and access checking and error reporting performed as usual.
*
* The method handle itself will have a type and behavior determined by the subtag as follows:
@@ -148,16 +157,45 @@
*
*
*
- * The special names {@code } and {@code } are not allowed except for subtag 8 as shown.
+ * The special name {@code } is not allowed.
+ * The special name {@code } is not allowed except for subtag 8 as shown.
*
- * The verifier applies the same access checks and restrictions for these references as for the hypothetical
+ * The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical
* bytecode instructions specified in the last column of the table. In particular, method handles to
* private and protected members can be created in exactly those classes for which the corresponding
* normal accesses are legal.
*
- * None of these constant types force class initialization.
- * Method handles for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
+ * A constant may refer to a method or constructor with the {@code varargs}
+ * bit (hexadecimal {@code 80}) set in its modifier bitmask.
+ * The method handle constant produced for such a method behaves the same
+ * as if the {@code varargs} bit were not set.
+ * The argument-collecting behavior of {@code varargs} can be emulated by
+ * adapting the method handle constant with
+ * {@link java.dyn.MethodHandle#asCollector asCollector}.
+ * There is no provision for doing this automatically.
+ *
+ * Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types
+ * resolve class names, they do not force class initialization.
+ * Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
* may force class initialization on their first invocation, just like the corresponding bytecodes.
+ *
+ * The rules of section 5.4.3 of the
+ * JVM Specification
+ * apply to the resolution of {@code CONSTANT_MethodType}, {@code CONSTANT_MethodHandle},
+ * and {@code CONSTANT_InvokeDynamic} constants,
+ * by the execution of {@code invokedynamic} and {@code ldc} instructions.
+ * (Roughly speaking, this means that every use of a constant pool entry
+ * must lead to the same outcome.
+ * If the resoultion succeeds, the same object reference is produced
+ * by every subsequent execution of the same instruction.
+ * If the resolution of the constant causes an error to occur,
+ * the same error will be re-thrown on every subsequent attempt
+ * to use this particular constant.)
+ *
+ * Constants created by the resolution of these constant pool types are not necessarily
+ * interned. Except for {@link CONSTANT_Class} and {@link CONSTANT_String} entries,
+ * two distinct constant pool entries might not resolve to the same reference
+ * even if they contain the same symbolic reference.
*
*
Bootstrap Methods
* Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
@@ -181,24 +219,36 @@
* call site execution.
* Linkage does not trigger class initialization.
*
- * Next, the bootstrap method call is started, with four values being stacked:
+ * Next, the bootstrap method call is started, with four or five values being stacked:
*
*
a {@code MethodHandle}, the resolved bootstrap method itself
- *
a {@code Class}, the caller class in which dynamic call site occurs
+ *
a {@code MethodHandles.Lookup}, a lookup object on the caller class in which dynamic call site occurs
*
a {@code String}, the method name mentioned in the call site
*
a {@code MethodType}, the resolved type signature of the call
* The method handle is then applied to the other values as if by
- * {@linkplain java.dyn.MethodHandle#invokeGeneric the invokeGeneric method}.
- * The returned result must be a {@link java.dyn.CallSite CallSite}, a {@link java.dyn.MethodHandle MethodHandle},
- * or another {@link java.dyn.MethodHandleProvider MethodHandleProvider} value.
- * The method {@linkplain java.dyn.MethodHandleProvider#asMethodHandle asMethodHandle}
- * is then called on the returned value. The result of that second
- * call is the {@code MethodHandle} which becomes the
- * permanent binding for the dynamic call site.
- * That method handle's type must be exactly equal to the type
+ * {@link java.dyn.MethodHandle#invokeGeneric invokeGeneric}.
+ * The returned result must be a {@link java.dyn.CallSite CallSite} (or a subclass).
+ * The type of the call site's target must be exactly equal to the type
* derived from the dynamic call site signature and passed to
* the bootstrap method.
+ * The call site then becomes permanently linked to the dynamic call site.
+ *
+ * As long as each bootstrap method can be correctly invoked
+ * by invokeGeneric, its detailed type is arbitrary.
+ * For example, the first argument could be {@code Object}
+ * instead of {@code MethodHandles.Lookup}, and the return type
+ * could also be {@code Object} instead of {@code CallSite}.
+ *
+ * As with any method handle constant, a {@code varargs} modifier bit
+ * on the bootstrap method is ignored.
+ *
+ * Note that the first argument of the bootstrap method cannot be
+ * a simple {@code Class} reference. (This is a change from earlier
+ * versions of this specification. If the caller class is needed,
+ * it is easy to {@linkplain java.dyn.MethodHandles.Lookup#lookupClass() extract it}
+ * from the {@code Lookup} object.)
*
* After resolution, the linkage process may fail in a variety of ways.
* All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
@@ -206,81 +256,209 @@
* site execution.
* The following circumstances will cause this:
*
+ *
the index to the bootstrap method specifier is out of range
+ *
the bootstrap method cannot be resolved
+ *
the {@code MethodType} to pass to the bootstrap method cannot be resolved
+ *
a static argument to the bootstrap method cannot be resolved
+ * (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
+ * or {@code CONSTANT_MethodHandle} argument cannot be linked)
+ *
the bootstrap method has the wrong arity,
+ * causing {@code invokeGeneric} to throw {@code WrongMethodTypeException}
+ *
the bootstrap method has a wrong argument or return type
*
the bootstrap method invocation completes abnormally
*
the result from the bootstrap invocation is not a reference to
- * an object of type {@link java.dyn.MethodHandleProvider MethodHandleProvider}
- *
the call to {@code asMethodHandle} completes abnormally
- *
the call to {@code asMethodHandle} fails to return a reference to
- * an object of type {@link java.dyn.MethodHandle MethodHandle}
- *
the method handle produced by {@code asMethodHandle} does not have
+ * an object of type {@link java.dyn.CallSite CallSite}
+ *
the target of the {@code CallSite} does not have a target of
* the expected {@code MethodType}
*
- *
timing of linkage
+ *
+ *
timing of linkage
* A dynamic call site is linked just before its first execution.
* The bootstrap method call implementing the linkage occurs within
* a thread that is attempting a first execution.
*
- * If there are several such threads, the JVM picks one thread
- * and runs the bootstrap method while the others wait for the
- * invocation to terminate normally or abnormally.
- *
- * After a bootstrap method is called and a method handle target
- * successfully extracted, the JVM attempts to link the instruction
- * being executed to the target method handle.
- * This may fail if there has been intervening linkage
- * or invalidation event for the same instruction.
- * If such a failure occurs, the dynamic call site must be
- * re-executed from the beginning, either re-linking it
- * (if it has been invalidated) or invoking the target
- * (if it the instruction has been linked by some other means).
- *
- * If the instruction is linked successfully, the target method
- * handle is invoked to complete the instruction execution.
- * The state of linkage continues until the method containing the
- * dynamic call site is garbage collected, or the dynamic call site
- * is invalidated by an explicit request,
- * such as {@link java.dyn.Linkage#invalidateCallerClass Linkage.invalidateCallerClass}.
+ * If there are several such threads, the bootstrap method may be
+ * invoked in several threads concurrently.
+ * Therefore, bootstrap methods which access global application
+ * data must take the usual precautions against race conditions.
+ * In any case, every {@code invokedynamic} instruction is either
+ * unlinked or linked to a unique {@code CallSite} object.
*
* In an application which requires dynamic call sites with individually
* mutable behaviors, their bootstrap methods should produce distinct
* {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
- *
- * If a class containing {@code invokedynamic} instructions
- * is {@linkplain java.dyn.Linkage#invalidateCallerClass(Class) invalidated},
- * subsequent execution of those {@code invokedynamic} instructions
- * will require linking.
- * It is as if they had never been executed in the first place.
- * (However, invalidation does not cause constant pool entries to be
- * resolved a second time.)
- *
- * Invalidation events and bootstrap method calls for a particular
- * dynamic call site are globally ordered relative to each other.
- * When an invokedynamic instruction is invalidated, if there is
- * simultaneously a bootstrap method invocation in process
- * (in the same thread or a different thread), the result
- * eventually returned must not be used to link the call site.
- * Put another way, when a call site is invalidated, its
- * subsequent linkage (if any) must be performed by a bootstrap method
- * call initiated after the invalidation occurred.
+ * Alternatively, an application can link a single {@code CallSite} object
+ * to several {@code invokedynamic} instructions, in which case
+ * a change to the target method will become visible at each of
+ * the instructions.
*
* If several threads simultaneously execute a bootstrap method for a single dynamic
- * call site, the JVM must choose one target object and installs it visibly to
+ * call site, the JVM must choose one {@code CallSite} object and install it visibly to
* all threads. Any other bootstrap method calls are allowed to complete, but their
* results are ignored, and their dynamic call site invocations proceed with the originally
* chosen target object.
+ *
+ *
+ * (Historic Note: Unlike some previous versions of this specification,
+ * these rules do not enable the JVM to duplicate dynamic call sites,
+ * or to issue “causeless” bootstrap method calls.
+ * Every dynamic call site transitions at most once from unlinked to linked,
+ * just before its first invocation.)
+ *
+ *
+ * Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
+ * a bootstrap method specifier; all such specifiers are contained in a separate array.
+ * This array is defined by a class attribute named {@code BootstrapMethods}.
+ * The body of this attribute consists of a sequence of byte pairs, all interpreted as
+ * as 16-bit counts or constant pool indexes, in the {@code u2} format.
+ * The attribute body starts with a count of bootstrap method specifiers,
+ * which is immediately followed by the sequence of specifiers.
*
- * The JVM is free to duplicate dynamic call sites.
- * This means that, even if a class contains just one {@code invokedynamic}
- * instruction, its bootstrap method may be executed several times,
- * once for each duplicate. Thus, bootstrap method code should not
- * assume an exclusive one-to-one correspondence between particular occurrences
- * of {@code invokedynamic} bytecodes in class files and linkage events.
+ * Each bootstrap method specifier contains an index to a
+ * {@code CONSTANT_MethodHandle} constant, which is the bootstrap
+ * method itself.
+ * This is followed by a count, and then a sequence (perhaps empty) of
+ * indexes to additional static arguments
+ * for the bootstrap method.
*
- * In principle, each individual execution of an {@code invokedynamic}
- * instruction could be deemed (by a conforming implementation) to be a separate
- * duplicate, requiring its own execution of the bootstrap method.
- * However, implementations are expected to perform code duplication
- * (if at all) in order to improve performance, not make it worse.
+ * During class loading, the verifier must check the structure of the
+ * {@code BootstrapMethods} attribute. In particular, each constant
+ * pool index must be of the correct type. A bootstrap method index
+ * must refer to a {@code CONSTANT_MethodHandle} (tag 15).
+ * Every other index must refer to a valid operand of an
+ * {@code ldc_w} or {@code ldc2_w} instruction (tag 3..8 or 15..16).
+ *
+ *
+ * An {@code invokedynamic} instruction specifies at least three arguments
+ * to pass to its bootstrap method:
+ * The caller class (expressed as a {@link java.dyn.MethodHandles.Lookup Lookup object},
+ * the name (extracted from the {@code CONSTANT_NameAndType} entry),
+ * and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
+ * The {@code invokedynamic} instruction may specify additional metadata values
+ * to pass to its bootstrap method.
+ * Collectively, these values are called static arguments to the
+ * {@code invokedynamic} instruction, because they are used once at link
+ * time to determine the instruction's behavior on subsequent sets of
+ * dynamic arguments.
+ *
+ * Static arguments are used to communicate application-specific meta-data
+ * to the bootstrap method.
+ * Drawn from the constant pool, they may include references to classes, method handles,
+ * strings, or numeric data that may be relevant to the task of linking that particular call site.
+ *
+ * Static arguments are specified constant pool indexes stored in the {@code BootstrapMethods} attribute.
+ * Before the bootstrap method is invoked, each index is used to compute an {@code Object}
+ * reference to the indexed value in the constant pool.
+ * If the value is a primitive type, it is converted to a reference by boxing conversion.
+ * The valid constant pool entries are listed in this table:
+ *
+ *
+ *
entry type
argument type
argument value
+ *
CONSTANT_String
java.lang.String
the indexed string literal
+ *
CONSTANT_Class
java.lang.Class
the indexed class, resolved
+ *
CONSTANT_Integer
java.lang.Integer
the indexed int value
+ *
CONSTANT_Long
java.lang.Long
the indexed long value
+ *
CONSTANT_Float
java.lang.Float
the indexed float value
+ *
CONSTANT_Double
java.lang.Double
the indexed double value
+ *
CONSTANT_MethodHandle
java.dyn.MethodHandle
the indexed method handle constant
+ *
CONSTANT_MethodType
java.dyn.MethodType
the indexed method type constant
+ *
+ *
+ *
+ * If a given {@code invokedynamic} instruction specifies no static arguments,
+ * the instruction's bootstrap method will be invoked on three arguments,
+ * conveying the instruction's caller class, name, and method type.
+ * If the {@code invokedynamic} instruction specifies one or more static arguments,
+ * a fourth argument will be passed to the bootstrap argument,
+ * either an {@code Object} reference to the sole extra argument (if there is one)
+ * or an {@code Object} array of references to all the arguments (if there are two or more),
+ * as if the bootstrap method is a variable-arity method.
+ *
+ *
+ * The argument and return types listed here are used by the {@code invokeGeneric}
+ * call to the bootstrap method.
+ * As noted above, the actual method type of the bootstrap method can vary.
+ * For example, the fourth argument could be {@code MethodHandle},
+ * if that is the type of the corresponding constant in
+ * the {@code CONSTANT_InvokeDynamic} entry.
+ * In that case, the {@code invokeGeneric} call will pass the extra method handle
+ * constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
+ * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
+ * (If a string constant were passed instead, by badly generated code, that cast would then fail.)
+ *
+ * If the fourth argument is an array, the array element type must be {@code Object},
+ * since object arrays (as produced by the JVM at this point) cannot be converted
+ * to other array types.
+ *
+ * If an array is provided, it will appear to be freshly allocated.
+ * That is, the same array will not appear to two bootstrap method calls.
+ *
+ * Extra bootstrap method arguments are intended to allow language implementors
+ * to safely and compactly encode metadata.
+ * In principle, the name and extra arguments are redundant,
+ * since each call site could be given its own unique bootstrap method.
+ * Such a practice is likely to produce large class files and constant pools.
+ *
+ *
+ * PROVISIONAL API, WORK IN PROGRESS:
+ * (Usage Note: There is no mechanism for specifying five or more positional arguments to the bootstrap method.
+ * If there are two or more arguments, the Java code of the bootstrap method is required to extract them from
+ * a varargs-style object array.
+ * This design uses varargs because it anticipates some use cases where bootstrap arguments
+ * contribute components of variable-length structures, such as virtual function tables
+ * or interpreter token streams.
+ * Such parameters would be awkward or impossible to manage if represented
+ * as normal positional method arguments,
+ * since there would need to be one Java method per length.
+ * On balance, leaving out the varargs feature would cause more trouble to users than keeping it.
+ * Also, this design allows bootstrap methods to be called in a limited JVM stack depth.
+ * At both the user and JVM level, the difference between varargs and non-varargs
+ * calling sequences can easily be bridged via the
+ * {@link java.dyn.MethodHandle#asSpreader asSpreader}
+ * and {@link java.dyn.MethodHandle#asSpreader asCollector} methods.)
+ *
+ *
Structure Summary
+ *
// summary of constant and attribute structures
+struct CONSTANT_MethodHandle_info {
+ u1 tag = 15;
+ u1 reference_kind; // 1..8 (one of REF_invokeVirtual, etc.)
+ u2 reference_index; // index to CONSTANT_Fieldref or *Methodref
+}
+struct CONSTANT_MethodType_info {
+ u1 tag = 16;
+ u2 descriptor_index; // index to CONSTANT_Utf8, as in NameAndType
+}
+struct CONSTANT_InvokeDynamic_17_info {
+ u1 tag = 17;
+ u2 bootstrap_method_index; // index to CONSTANT_MethodHandle
+ u2 name_and_type_index; // same as for CONSTANT_Methodref, etc.
+}
+struct CONSTANT_InvokeDynamic_info {
+ u1 tag = 18;
+ u2 bootstrap_method_attr_index; // index into BootstrapMethods_attr
+ u2 name_and_type_index; // index to CONSTANT_NameAndType, as in Methodref
+}
+struct BootstrapMethods_attr {
+ u2 name; // CONSTANT_Utf8 = "BootstrapMethods"
+ u4 size;
+ u2 bootstrap_method_count;
+ struct bootstrap_method_specifier {
+ u2 bootstrap_method_ref; // index to CONSTANT_MethodHandle
+ u2 bootstrap_argument_count;
+ u2 bootstrap_arguments[bootstrap_argument_count]; // constant pool indexes
+ } bootstrap_methods[bootstrap_method_count];
+}
+ *
+ *
+ * Note: The Proposed Final Draft of JSR 292 may remove the constant tag 17,
+ * for the sake of simplicity.
*
* @author John Rose, JSR 292 EG
*/
diff --git a/jdk/src/share/classes/java/io/FileOutputStream.java b/jdk/src/share/classes/java/io/FileOutputStream.java
index 71bdee89f3b..70f6851d732 100644
--- a/jdk/src/share/classes/java/io/FileOutputStream.java
+++ b/jdk/src/share/classes/java/io/FileOutputStream.java
@@ -56,7 +56,15 @@ class FileOutputStream extends OutputStream
*/
private final FileDescriptor fd;
- private FileChannel channel= null;
+ /**
+ * True if the file is opened for append.
+ */
+ private final boolean append;
+
+ /**
+ * The associated channel, initalized lazily.
+ */
+ private FileChannel channel;
private final Object closeLock = new Object();
private volatile boolean closed = false;
@@ -196,7 +204,9 @@ class FileOutputStream extends OutputStream
if (name == null) {
throw new NullPointerException();
}
- fd = new FileDescriptor();
+ this.fd = new FileDescriptor();
+ this.append = append;
+
fd.incrementAndGetUseCount();
open(name, append);
}
@@ -232,7 +242,8 @@ class FileOutputStream extends OutputStream
if (security != null) {
security.checkWrite(fdObj);
}
- fd = fdObj;
+ this.fd = fdObj;
+ this.append = false;
/*
* FileDescriptor is being shared by streams.
@@ -250,6 +261,15 @@ class FileOutputStream extends OutputStream
private native void open(String name, boolean append)
throws FileNotFoundException;
+ /**
+ * Writes the specified byte to this file output stream.
+ *
+ * @param b the byte to be written.
+ * @param append {@code true} if the write operation first
+ * advances the position to the end of file
+ */
+ private native void write(int b, boolean append) throws IOException;
+
/**
* Writes the specified byte to this file output stream. Implements
* the write method of OutputStream.
@@ -257,16 +277,21 @@ class FileOutputStream extends OutputStream
* @param b the byte to be written.
* @exception IOException if an I/O error occurs.
*/
- public native void write(int b) throws IOException;
+ public void write(int b) throws IOException {
+ write(b, append);
+ }
/**
* Writes a sub array as a sequence of bytes.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
+ * @param append {@code true} to first advance the position to the
+ * end of file
* @exception IOException If an I/O error has occurred.
*/
- private native void writeBytes(byte b[], int off, int len) throws IOException;
+ private native void writeBytes(byte b[], int off, int len, boolean append)
+ throws IOException;
/**
* Writes b.length bytes from the specified byte array
@@ -276,7 +301,7 @@ class FileOutputStream extends OutputStream
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[]) throws IOException {
- writeBytes(b, 0, b.length);
+ writeBytes(b, 0, b.length, append);
}
/**
@@ -289,7 +314,7 @@ class FileOutputStream extends OutputStream
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[], int off, int len) throws IOException {
- writeBytes(b, off, len);
+ writeBytes(b, off, len, append);
}
/**
@@ -372,7 +397,7 @@ class FileOutputStream extends OutputStream
public FileChannel getChannel() {
synchronized (this) {
if (channel == null) {
- channel = FileChannelImpl.open(fd, false, true, this);
+ channel = FileChannelImpl.open(fd, false, true, append, this);
/*
* Increment fd's use count. Invoking the channel's close()
diff --git a/jdk/src/share/classes/java/io/ObjectInputStream.java b/jdk/src/share/classes/java/io/ObjectInputStream.java
index 2ed505f3b07..3ec3cd4fbdc 100644
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java
@@ -3498,8 +3498,8 @@ public class ObjectInputStream
return ((int[]) array).clone();
} else if (array instanceof long[]) {
return ((long[]) array).clone();
- } else if (array instanceof double[]) {
- return ((double[]) array).clone();
+ } else if (array instanceof short[]) {
+ return ((short[]) array).clone();
} else {
throw new AssertionError();
}
diff --git a/jdk/src/share/classes/java/lang/Character.java b/jdk/src/share/classes/java/lang/Character.java
index b833dab838e..f8be10ec5c3 100644
--- a/jdk/src/share/classes/java/lang/Character.java
+++ b/jdk/src/share/classes/java/lang/Character.java
@@ -6371,15 +6371,15 @@ class Character implements java.io.Serializable, Comparable {
* This method returns true for the following five
* characters only:
*
- *
'\t'
'\u0009'
+ *
'\t'
U+0009
*
HORIZONTAL TABULATION
- *
'\n'
'\u000A'
+ *
'\n'
U+000A
*
NEW LINE
- *
'\f'
'\u000C'
+ *
'\f'
U+000C
*
FORM FEED
- *
'\r'
'\u000D'
+ *
'\r'
U+000D
*
CARRIAGE RETURN
- *
' '
'\u0020'
+ *
' '
U+0020
*
SPACE
*
*
@@ -6463,15 +6463,15 @@ class Character implements java.io.Serializable, Comparable {
* LINE_SEPARATOR, or PARAGRAPH_SEPARATOR)
* but is not also a non-breaking space ('\u00A0',
* '\u2007', '\u202F').
- *
Note: Although the language tag created by this
* method is well-formed (satisfies the syntax requirements
@@ -1327,7 +1325,7 @@ public final class Locale implements Cloneable, Serializable {
*
*
* Locale loc;
- * loc = Locale.forLanguageTag("en-US-x-lvariant-POSIX);
+ * loc = Locale.forLanguageTag("en-US-x-lvariant-POSIX");
* loc.getVariant(); // returns "POSIX"
* loc.getExtension('x'); // returns null
*
@@ -1355,10 +1353,10 @@ public final class Locale implements Cloneable, Serializable {
* extensions are added as though the constructor had been called:
*
*
This implements the 'Language-Tag' production of BCP47, and
@@ -1428,7 +1426,12 @@ public final class Locale implements Cloneable, Serializable {
LanguageTag tag = LanguageTag.parse(languageTag, null);
InternalLocaleBuilder bldr = new InternalLocaleBuilder();
bldr.setLanguageTag(tag);
- return getInstance(bldr.getBaseLocale(), bldr.getLocaleExtensions());
+ BaseLocale base = bldr.getBaseLocale();
+ LocaleExtensions exts = bldr.getLocaleExtensions();
+ if (exts.isEmpty() && base.getVariant().length() > 0) {
+ exts = getCompatibilityExtensions(base.getLanguage(), base.getScript(), base.getRegion(), base.getVariant());
+ }
+ return getInstance(base, exts);
}
/**
@@ -2487,6 +2490,10 @@ public final class Locale implements Cloneable, Serializable {
public Locale build() {
BaseLocale baseloc = _locbld.getBaseLocale();
LocaleExtensions extensions = _locbld.getLocaleExtensions();
+ if (extensions.isEmpty() && baseloc.getVariant().length() > 0) {
+ extensions = getCompatibilityExtensions(baseloc.getLanguage(), baseloc.getScript(),
+ baseloc.getRegion(), baseloc.getVariant());
+ }
return Locale.getInstance(baseloc, extensions);
}
}
diff --git a/jdk/src/share/classes/java/util/Random.java b/jdk/src/share/classes/java/util/Random.java
index 833cfbbe256..8f217833bfe 100644
--- a/jdk/src/share/classes/java/util/Random.java
+++ b/jdk/src/share/classes/java/util/Random.java
@@ -77,9 +77,9 @@ class Random implements java.io.Serializable {
*/
private final AtomicLong seed;
- private final static long multiplier = 0x5DEECE66DL;
- private final static long addend = 0xBL;
- private final static long mask = (1L << 48) - 1;
+ private static final long multiplier = 0x5DEECE66DL;
+ private static final long addend = 0xBL;
+ private static final long mask = (1L << 48) - 1;
/**
* Creates a new random number generator. This constructor sets
@@ -285,7 +285,7 @@ class Random implements java.io.Serializable {
* @return the next pseudorandom, uniformly distributed {@code int}
* value between {@code 0} (inclusive) and {@code n} (exclusive)
* from this random number generator's sequence
- * @exception IllegalArgumentException if n is not positive
+ * @throws IllegalArgumentException if n is not positive
* @since 1.2
*/
diff --git a/jdk/src/share/classes/java/util/Stack.java b/jdk/src/share/classes/java/util/Stack.java
index 9c17b31a75b..8dd2ebddbbe 100644
--- a/jdk/src/share/classes/java/util/Stack.java
+++ b/jdk/src/share/classes/java/util/Stack.java
@@ -73,9 +73,9 @@ class Stack extends Vector {
* Removes the object at the top of this stack and returns that
* object as the value of this function.
*
- * @return The object at the top of this stack (the last item
- * of the Vector object).
- * @exception EmptyStackException if this stack is empty.
+ * @return The object at the top of this stack (the last item
+ * of the Vector object).
+ * @throws EmptyStackException if this stack is empty.
*/
public synchronized E pop() {
E obj;
@@ -91,9 +91,9 @@ class Stack extends Vector {
* Looks at the object at the top of this stack without removing it
* from the stack.
*
- * @return the object at the top of this stack (the last item
- * of the Vector object).
- * @exception EmptyStackException if this stack is empty.
+ * @return the object at the top of this stack (the last item
+ * of the Vector object).
+ * @throws EmptyStackException if this stack is empty.
*/
public synchronized E peek() {
int len = size();
diff --git a/jdk/src/share/classes/java/util/TimSort.java b/jdk/src/share/classes/java/util/TimSort.java
index 6940883d02a..6d4727ac4e7 100644
--- a/jdk/src/share/classes/java/util/TimSort.java
+++ b/jdk/src/share/classes/java/util/TimSort.java
@@ -239,7 +239,7 @@ class TimSort {
* @param lo the index of the first element in the range to be sorted
* @param hi the index after the last element in the range to be sorted
* @param start the index of the first element in the range that is
- * not already known to be sorted (@code lo <= start <= hi}
+ * not already known to be sorted ({@code lo <= start <= hi})
* @param c comparator to used for the sort
*/
@SuppressWarnings("fallthrough")
@@ -278,7 +278,7 @@ class TimSort {
*/
int n = start - left; // The number of elements to move
// Switch is just an optimization for arraycopy in default case
- switch(n) {
+ switch (n) {
case 2: a[left + 2] = a[left + 1];
case 1: a[left + 1] = a[left];
break;
@@ -308,7 +308,7 @@ class TimSort {
* @param a the array in which a run is to be counted and possibly reversed
* @param lo index of the first element in the run
* @param hi index after the last element that may be contained in the run.
- It is required that @code{lo < hi}.
+ It is required that {@code lo < hi}.
* @param c the comparator to used for the sort
* @return the length of the run beginning at the specified position in
* the specified array
@@ -322,7 +322,7 @@ class TimSort {
// Find end of run, and reverse range if descending
if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
- while(runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
+ while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
runHi++;
reverseRange(a, lo, runHi);
} else { // Ascending
diff --git a/jdk/src/share/classes/java/util/TreeMap.java b/jdk/src/share/classes/java/util/TreeMap.java
index b0c9aa7d67a..8c055d8ce98 100644
--- a/jdk/src/share/classes/java/util/TreeMap.java
+++ b/jdk/src/share/classes/java/util/TreeMap.java
@@ -1056,11 +1056,11 @@ public class TreeMap
public Comparator super E> comparator() { return m.comparator(); }
public E pollFirst() {
Map.Entry e = m.pollFirstEntry();
- return e == null? null : e.getKey();
+ return (e == null) ? null : e.getKey();
}
public E pollLast() {
Map.Entry e = m.pollLastEntry();
- return e == null? null : e.getKey();
+ return (e == null) ? null : e.getKey();
}
public boolean remove(Object o) {
int oldSize = size();
@@ -1196,7 +1196,7 @@ public class TreeMap
* Test two values for equality. Differs from o1.equals(o2) only in
* that it copes with {@code null} o1 properly.
*/
- final static boolean valEquals(Object o1, Object o2) {
+ static final boolean valEquals(Object o1, Object o2) {
return (o1==null ? o2==null : o1.equals(o2));
}
@@ -1204,7 +1204,7 @@ public class TreeMap
* Return SimpleImmutableEntry for entry, or null if null
*/
static Map.Entry exportEntry(TreeMap.Entry e) {
- return e == null? null :
+ return (e == null) ? null :
new AbstractMap.SimpleImmutableEntry(e);
}
@@ -1212,7 +1212,7 @@ public class TreeMap
* Return key for entry, or null if null
*/
static K keyOrNull(TreeMap.Entry e) {
- return e == null? null : e.key;
+ return (e == null) ? null : e.key;
}
/**
@@ -1237,7 +1237,7 @@ public class TreeMap
/**
* @serial include
*/
- static abstract class NavigableSubMap extends AbstractMap
+ abstract static class NavigableSubMap extends AbstractMap
implements NavigableMap, java.io.Serializable {
/**
* The backing map.
@@ -1412,11 +1412,11 @@ public class TreeMap
}
public final V get(Object key) {
- return !inRange(key)? null : m.get(key);
+ return !inRange(key) ? null : m.get(key);
}
public final V remove(Object key) {
- return !inRange(key)? null : m.remove(key);
+ return !inRange(key) ? null : m.remove(key);
}
public final Map.Entry ceilingEntry(K key) {
@@ -1559,7 +1559,8 @@ public class TreeMap
if (!inRange(key))
return false;
TreeMap.Entry node = m.getEntry(key);
- if (node!=null && valEquals(node.getValue(),entry.getValue())){
+ if (node!=null && valEquals(node.getValue(),
+ entry.getValue())) {
m.deleteEntry(node);
return true;
}
@@ -1724,7 +1725,7 @@ public class TreeMap
false, toKey, inclusive);
}
- public NavigableMap tailMap(K fromKey, boolean inclusive){
+ public NavigableMap tailMap(K fromKey, boolean inclusive) {
if (!inRange(fromKey, inclusive))
throw new IllegalArgumentException("fromKey out of range");
return new AscendingSubMap(m,
@@ -1805,7 +1806,7 @@ public class TreeMap
toEnd, hi, hiInclusive);
}
- public NavigableMap tailMap(K fromKey, boolean inclusive){
+ public NavigableMap tailMap(K fromKey, boolean inclusive) {
if (!inRange(fromKey, inclusive))
throw new IllegalArgumentException("fromKey out of range");
return new DescendingSubMap(m,
@@ -2143,7 +2144,7 @@ public class TreeMap
// If strictly internal, copy successor's element to p and then make p
// point to successor.
if (p.left != null && p.right != null) {
- Entry s = successor (p);
+ Entry s = successor(p);
p.key = s.key;
p.value = s.value;
p = s;
diff --git a/jdk/src/share/classes/java/util/TreeSet.java b/jdk/src/share/classes/java/util/TreeSet.java
index 99e3f313ad6..c2e2bdf8ffd 100644
--- a/jdk/src/share/classes/java/util/TreeSet.java
+++ b/jdk/src/share/classes/java/util/TreeSet.java
@@ -452,7 +452,7 @@ public class TreeSet extends AbstractSet
*/
public E pollFirst() {
Map.Entry e = m.pollFirstEntry();
- return (e == null)? null : e.getKey();
+ return (e == null) ? null : e.getKey();
}
/**
@@ -460,7 +460,7 @@ public class TreeSet extends AbstractSet
*/
public E pollLast() {
Map.Entry e = m.pollLastEntry();
- return (e == null)? null : e.getKey();
+ return (e == null) ? null : e.getKey();
}
/**
diff --git a/jdk/src/share/classes/java/util/Vector.java b/jdk/src/share/classes/java/util/Vector.java
index e508aa5b5c0..f1a9c172a27 100644
--- a/jdk/src/share/classes/java/util/Vector.java
+++ b/jdk/src/share/classes/java/util/Vector.java
@@ -919,7 +919,7 @@ public class Vector
* elements (optional), or if the specified collection is null
* @since 1.2
*/
- public synchronized boolean retainAll(Collection> c) {
+ public synchronized boolean retainAll(Collection> c) {
return super.retainAll(c);
}
diff --git a/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java b/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java
index 3a43617b0be..0322289e52e 100644
--- a/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java
+++ b/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java
@@ -51,20 +51,20 @@ import java.util.*;
*
Extension example. Here is a sketch of a class
* that customizes {@link ThreadPoolExecutor} to use
* a CustomTask class instead of the default FutureTask:
- *
+ *
{@code
* public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
*
- * static class CustomTask<V> implements RunnableFuture<V> {...}
+ * static class CustomTask implements RunnableFuture {...}
*
- * protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
- * return new CustomTask<V>(c);
+ * protected RunnableFuture newTaskFor(Callable c) {
+ * return new CustomTask(c);
* }
- * protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
- * return new CustomTask<V>(r, v);
+ * protected RunnableFuture newTaskFor(Runnable r, V v) {
+ * return new CustomTask(r, v);
* }
* // ... add constructors, etc.
- * }
- *
+ * }}
+ *
* @since 1.5
* @author Doug Lea
*/
@@ -106,7 +106,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
*/
public Future> submit(Runnable task) {
if (task == null) throw new NullPointerException();
- RunnableFuture