--- ./.hgtags Tue Mar 18 12:29:21 2014 -0700
+++ ./.hgtags Wed May 07 19:25:50 2014 -0700
@@ -357,6 +357,7 @@
3af81bfe320c12758234233da6fa27c3c0ffcdc4 jdk7u40-b42
1d53bd8fd2a62bcf336727ebec377ef7498dd4a6 jdk7u40-b43
dc1e099cd62d250b4a997ce694b47fe2f50d2905 jdk7u40-b60
+11147a12bd8c6b02f98016a8d1151e56f42a43b6 jdk7u60-b00
6359fa34199c9619dfec0f41d2eb22a4083ce610 jdk7u40-b61
a2605cf03226ce2fef7a899ce41521c654300975 jdk7u40-b62
07e41ff8674c9438cb1124cf78eed8636ed5d4fa jdk7u45-b02
@@ -414,3 +415,26 @@
f4ace62029de00d2497058c3c0e1d26e019cde30 jdk7u55-b11
de268da51b54a4f36bcc1a9af60faea285e94330 jdk7u55-b12
d972a2d9e4f3f864d26c33ccfdacd8269e0f29a8 jdk7u55-b13
+0820b4707cfa75f8211b88b0daa67bba8475f498 jdk7u55-b30
+997ab3897d6ede80b0decdda94b569e57dd7dd90 jdk7u55-b14
+1f52edec29fd44c8bacce11ba7440287b37d04d1 jdk7u55-b31
+11147a12bd8c6b02f98016a8d1151e56f42a43b6 jdk7u60-b00
+88113cabda386320a087b288d43e792f523cc0ba jdk7u60-b01
+6bdacebbc97f0a03be45be48a6d5b5cf2f7fe77d jdk7u60-b02
+87f2193da40d3a2eedca95108ae78403c7bdcd49 jdk7u60-b03
+d4397128f8b65eb96287128575dd1a3da6a7825b jdk7u60-b04
+ea798405286d97f643ef809abcb1e13024b4f951 jdk7u60-b05
+b0940b205cab942512b5bca1338ab96a45a67832 jdk7u60-b06
+cae7bacaa13bb8c42a42fa35b156a7660874e907 jdk7u60-b07
+1af0560611469ad2a068a03774ecd0d7790db7b7 jdk7u60-b08
+662dc3b6467488b8c175a4423ba7a4991ad87d94 jdk7u60-b09
+023f8eb40d371d5cb761f7e60ba7b396b3fdf886 jdk7u60-b10
+798468b91bcbb81684aea8620dbb31eaceb24c6c jdk7u60-b11
+e40360c10b2ce5b24b1eea63160b78e112aa5d3f jdk7u60-b12
+5e540a4d55916519f5604a422bfbb7a0967d0594 jdk7u60-b13
+1ca6a368aec38ee91a41dc03899d7dc1037de44d jdk7u60-b14
+a95b821a2627295b90fb4ae8f3b8bc2ff9c64acc jdk7u60-b15
+19a3f6f48c541a8cf144eedffa0e52e108052e82 jdk7u60-b16
+472f5930e6cc8f307b5508995ee2edcf9913a852 jdk7u60-b18
+472f5930e6cc8f307b5508995ee2edcf9913a852 jdk7u60-b17
+2a7a5e774023944f291ee27ca5b3ad89e0e62aaf jdk7u60-b19
--- ./make/scripts/webrev.ksh Tue Mar 18 12:29:21 2014 -0700
+++ ./make/scripts/webrev.ksh Wed May 07 19:25:50 2014 -0700
@@ -2695,11 +2695,11 @@
rm -f $WDIR/$DIR/$F.html
its_a_jar=
- if expr $F : '.*\.jar' >/dev/null; then
+ if expr $F : '.*\.jar' \| $F : '.*\.zip' >/dev/null; then
its_a_jar=1
- # It's a JAR file, let's do it differntly
+ # It's a JAR or ZIP file, let's do it differently
if [[ -z $JAR ]]; then
- print "No access to jar, so can't produce diffs for jar files"
+ print "No access to jar, so can't produce diffs for jar or zip files"
else
if [ -f $ofile ]; then
$JAR -tvf $ofile >"$ofile".lst
--- ./corba/.hgtags Tue Mar 18 12:29:47 2014 -0700
+++ ./corba/.hgtags Wed May 07 19:25:52 2014 -0700
@@ -417,3 +417,26 @@
cbd5b4b07e0c8a5f61eff396b7622e7b04d2a164 jdk7u55-b11
3cce2a49d18d93dfca2634db32368486ebbb1590 jdk7u55-b12
8efa6e66c13a5329c312d1a521ffab75d9a330e3 jdk7u55-b13
+e041c52fe69128ec3439d26afef9b0fcba00684c jdk7u55-b30
+a0bfd0e80ae0ae6e3a29bf527b5911c83163b3f5 jdk7u55-b14
+55ff6957449cf6c79f5d5bb159df27f51ece1659 jdk7u55-b31
+c5b5886004e6446b8b27ccdc1fd073354c1dc614 jdk7u60-b00
+a531112cc6d0b0a1e7d4ffdaa3ba53addcd25cf4 jdk7u60-b01
+d81370c5b863acc19e8fb07315b1ec687ac1136a jdk7u60-b02
+d7e98ed925a3885380226f8375fe109a9a25397f jdk7u60-b03
+1a3aa4637b80fabbd069ae88c241efcb3520fc49 jdk7u60-b04
+753698a910167cc29c01490648a2adbcea1314cc jdk7u60-b05
+9852efe6d6b992b73fdbf59e36fb3547a9535051 jdk7u60-b06
+84a18429f247774fc7f1bc81de271da20b40845b jdk7u60-b07
+8469bc00ddca4de366b20b32d42548c882656cd8 jdk7u60-b08
+7abca119f9543489280d560dc11256d439004f0f jdk7u60-b09
+1861f1f599728c4f15a85a5980edef916552747b jdk7u60-b10
+a429ff635395688ded6c52cd21c0b4ce75e62168 jdk7u60-b11
+d581875525aaf618afe901da31d679195ee35f4b jdk7u60-b12
+2c8ba5f9487b0ac085874afd38f4c10a4127f62c jdk7u60-b13
+02bdeb33754315f589bd650dde656d2c9947976d jdk7u60-b14
+e5946b2cf82bdea3a4b85917e903168e65a543a7 jdk7u60-b15
+e424fb8452851b56db202488a4e9a283934c4887 jdk7u60-b16
+b96d90694be873372cc417b38b01afed6ac1b239 jdk7u60-b18
+b96d90694be873372cc417b38b01afed6ac1b239 jdk7u60-b17
+5d1b39fe68944cff6380db56fbe2fbaa28091bf6 jdk7u60-b19
--- ./corba/src/share/classes/com/sun/corba/se/impl/copyobject/JavaInputStream.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,528 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.sun.corba.se.impl.encoding;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.nio.ByteBuffer;
-
-import org.omg.CORBA.TypeCode;
-import org.omg.CORBA.Principal;
-import org.omg.CORBA.Any;
-
-import com.sun.org.omg.SendingContext.CodeBase;
-
-import com.sun.corba.se.pept.protocol.MessageMediator;
-
-import com.sun.corba.se.spi.logging.CORBALogDomains;
-import com.sun.corba.se.spi.orb.ORB;
-import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
-import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
-
-import com.sun.corba.se.impl.logging.ORBUtilSystemException;
-import com.sun.corba.se.impl.encoding.CodeSetConversion;
-import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
-
-/**
- * This is delegates to the real implementation.
- *
- * NOTE:
- *
- * Before using the stream for valuetype unmarshaling, one must call
- * performORBVersionSpecificInit().
- */
-public abstract class CDRInputStream
- extends org.omg.CORBA_2_3.portable.InputStream
- implements com.sun.corba.se.impl.encoding.MarshalInputStream,
- org.omg.CORBA.DataInputStream, org.omg.CORBA.portable.ValueInputStream
-{
- protected CorbaMessageMediator messageMediator;
- private CDRInputStreamBase impl;
-
- // We can move this out somewhere later. For now, it serves its purpose
- // to create a concrete CDR delegate based on the GIOP version.
- private static class InputStreamFactory {
-
- public static CDRInputStreamBase newInputStream(ORB orb, GIOPVersion version)
- {
- switch(version.intValue()) {
- case GIOPVersion.VERSION_1_0:
- return new CDRInputStream_1_0();
- case GIOPVersion.VERSION_1_1:
- return new CDRInputStream_1_1();
- case GIOPVersion.VERSION_1_2:
- return new CDRInputStream_1_2();
- default:
- ORBUtilSystemException wrapper = ORBUtilSystemException.get( orb,
- CORBALogDomains.RPC_ENCODING ) ;
- throw wrapper.unsupportedGiopVersion( version ) ;
- }
- }
- }
-
- // Required for the case when a ClientResponseImpl is
- // created with a SystemException due to a dead server/closed
- // connection with no warning. Note that the stream will
- // not be initialized in this case.
- //
- // Probably also required by ServerRequestImpl.
- //
- // REVISIT.
- public CDRInputStream() {
- }
-
- public CDRInputStream(CDRInputStream is) {
- impl = is.impl.dup();
- impl.setParent(this);
- }
-
- public CDRInputStream(org.omg.CORBA.ORB orb,
- ByteBuffer byteBuffer,
- int size,
- boolean littleEndian,
- GIOPVersion version,
- BufferManagerRead bufMgr)
- {
- impl = InputStreamFactory.newInputStream( (ORB)orb, version);
-
- impl.init(orb, byteBuffer, size, littleEndian, bufMgr);
-
- impl.setParent(this);
- }
-
- // org.omg.CORBA.portable.InputStream
- public final boolean read_boolean() {
- return impl.read_boolean();
- }
-
- public final char read_char() {
- return impl.read_char();
- }
-
- public final char read_wchar() {
- return impl.read_wchar();
- }
-
- public final byte read_octet() {
- return impl.read_octet();
- }
-
- public final short read_short() {
- return impl.read_short();
- }
-
- public final short read_ushort() {
- return impl.read_ushort();
- }
-
- public final int read_long() {
- return impl.read_long();
- }
-
- public final int read_ulong() {
- return impl.read_ulong();
- }
-
- public final long read_longlong() {
- return impl.read_longlong();
- }
-
- public final long read_ulonglong() {
- return impl.read_ulonglong();
- }
-
- public final float read_float() {
- return impl.read_float();
- }
-
- public final double read_double() {
- return impl.read_double();
- }
-
- public final String read_string() {
- return impl.read_string();
- }
-
- public final String read_wstring() {
- return impl.read_wstring();
- }
-
- public final void read_boolean_array(boolean[] value, int offset, int length) {
- impl.read_boolean_array(value, offset, length);
- }
-
- public final void read_char_array(char[] value, int offset, int length) {
- impl.read_char_array(value, offset, length);
- }
-
- public final void read_wchar_array(char[] value, int offset, int length) {
- impl.read_wchar_array(value, offset, length);
- }
-
- public final void read_octet_array(byte[] value, int offset, int length) {
- impl.read_octet_array(value, offset, length);
- }
-
- public final void read_short_array(short[] value, int offset, int length) {
- impl.read_short_array(value, offset, length);
- }
-
- public final void read_ushort_array(short[] value, int offset, int length) {
- impl.read_ushort_array(value, offset, length);
- }
-
- public final void read_long_array(int[] value, int offset, int length) {
- impl.read_long_array(value, offset, length);
- }
-
- public final void read_ulong_array(int[] value, int offset, int length) {
- impl.read_ulong_array(value, offset, length);
- }
-
- public final void read_longlong_array(long[] value, int offset, int length) {
- impl.read_longlong_array(value, offset, length);
- }
-
- public final void read_ulonglong_array(long[] value, int offset, int length) {
- impl.read_ulonglong_array(value, offset, length);
- }
-
- public final void read_float_array(float[] value, int offset, int length) {
- impl.read_float_array(value, offset, length);
- }
-
- public final void read_double_array(double[] value, int offset, int length) {
- impl.read_double_array(value, offset, length);
- }
-
- public final org.omg.CORBA.Object read_Object() {
- return impl.read_Object();
- }
-
- public final TypeCode read_TypeCode() {
- return impl.read_TypeCode();
- }
- public final Any read_any() {
- return impl.read_any();
- }
-
- public final Principal read_Principal() {
- return impl.read_Principal();
- }
-
- public final int read() throws java.io.IOException {
- return impl.read();
- }
-
- public final java.math.BigDecimal read_fixed() {
- return impl.read_fixed();
- }
-
- public final org.omg.CORBA.Context read_Context() {
- return impl.read_Context();
- }
-
- public final org.omg.CORBA.Object read_Object(java.lang.Class clz) {
- return impl.read_Object(clz);
- }
-
- public final org.omg.CORBA.ORB orb() {
- return impl.orb();
- }
-
- // org.omg.CORBA_2_3.portable.InputStream
- public final java.io.Serializable read_value() {
- return impl.read_value();
- }
-
- public final java.io.Serializable read_value(java.lang.Class clz) {
- return impl.read_value(clz);
- }
-
- public final java.io.Serializable read_value(org.omg.CORBA.portable.BoxedValueHelper factory) {
- return impl.read_value(factory);
- }
-
- public final java.io.Serializable read_value(java.lang.String rep_id) {
- return impl.read_value(rep_id);
- }
-
- public final java.io.Serializable read_value(java.io.Serializable value) {
- return impl.read_value(value);
- }
-
- public final java.lang.Object read_abstract_interface() {
- return impl.read_abstract_interface();
- }
-
- public final java.lang.Object read_abstract_interface(java.lang.Class clz) {
- return impl.read_abstract_interface(clz);
- }
- // com.sun.corba.se.impl.encoding.MarshalInputStream
-
- public final void consumeEndian() {
- impl.consumeEndian();
- }
-
- public final int getPosition() {
- return impl.getPosition();
- }
-
- // org.omg.CORBA.DataInputStream
-
- public final java.lang.Object read_Abstract () {
- return impl.read_Abstract();
- }
-
- public final java.io.Serializable read_Value () {
- return impl.read_Value();
- }
-
- public final void read_any_array (org.omg.CORBA.AnySeqHolder seq, int offset, int length) {
- impl.read_any_array(seq, offset, length);
- }
-
- public final void read_boolean_array (org.omg.CORBA.BooleanSeqHolder seq, int offset, int length) {
- impl.read_boolean_array(seq, offset, length);
- }
-
- public final void read_char_array (org.omg.CORBA.CharSeqHolder seq, int offset, int length) {
- impl.read_char_array(seq, offset, length);
- }
-
- public final void read_wchar_array (org.omg.CORBA.WCharSeqHolder seq, int offset, int length) {
- impl.read_wchar_array(seq, offset, length);
- }
-
- public final void read_octet_array (org.omg.CORBA.OctetSeqHolder seq, int offset, int length) {
- impl.read_octet_array(seq, offset, length);
- }
-
- public final void read_short_array (org.omg.CORBA.ShortSeqHolder seq, int offset, int length) {
- impl.read_short_array(seq, offset, length);
- }
-
- public final void read_ushort_array (org.omg.CORBA.UShortSeqHolder seq, int offset, int length) {
- impl.read_ushort_array(seq, offset, length);
- }
-
- public final void read_long_array (org.omg.CORBA.LongSeqHolder seq, int offset, int length) {
- impl.read_long_array(seq, offset, length);
- }
-
- public final void read_ulong_array (org.omg.CORBA.ULongSeqHolder seq, int offset, int length) {
- impl.read_ulong_array(seq, offset, length);
- }
-
- public final void read_ulonglong_array (org.omg.CORBA.ULongLongSeqHolder seq, int offset, int length) {
- impl.read_ulonglong_array(seq, offset, length);
- }
-
- public final void read_longlong_array (org.omg.CORBA.LongLongSeqHolder seq, int offset, int length) {
- impl.read_longlong_array(seq, offset, length);
- }
-
- public final void read_float_array (org.omg.CORBA.FloatSeqHolder seq, int offset, int length) {
- impl.read_float_array(seq, offset, length);
- }
-
- public final void read_double_array (org.omg.CORBA.DoubleSeqHolder seq, int offset, int length) {
- impl.read_double_array(seq, offset, length);
- }
-
- // org.omg.CORBA.portable.ValueBase
- public final String[] _truncatable_ids() {
- return impl._truncatable_ids();
- }
-
- // java.io.InputStream
- public final int read(byte b[]) throws IOException {
- return impl.read(b);
- }
-
- public final int read(byte b[], int off, int len) throws IOException {
- return impl.read(b, off, len);
- }
-
- public final long skip(long n) throws IOException {
- return impl.skip(n);
- }
-
- public final int available() throws IOException {
- return impl.available();
- }
-
- public final void close() throws IOException {
- impl.close();
- }
-
- public final void mark(int readlimit) {
- impl.mark(readlimit);
- }
-
- public final void reset() {
- impl.reset();
- }
-
- public final boolean markSupported() {
- return impl.markSupported();
- }
-
- public abstract CDRInputStream dup();
-
- // Needed by TCUtility
- public final java.math.BigDecimal read_fixed(short digits, short scale) {
- return impl.read_fixed(digits, scale);
- }
-
- public final boolean isLittleEndian() {
- return impl.isLittleEndian();
- }
-
- protected final ByteBuffer getByteBuffer() {
- return impl.getByteBuffer();
- }
-
- protected final void setByteBuffer(ByteBuffer byteBuffer) {
- impl.setByteBuffer(byteBuffer);
- }
-
- protected final void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
- impl.setByteBufferWithInfo(bbwi);
- }
-
- public final int getBufferLength() {
- return impl.getBufferLength();
- }
-
- protected final void setBufferLength(int value) {
- impl.setBufferLength(value);
- }
-
- protected final int getIndex() {
- return impl.getIndex();
- }
-
- protected final void setIndex(int value) {
- impl.setIndex(value);
- }
-
- public final void orb(org.omg.CORBA.ORB orb) {
- impl.orb(orb);
- }
-
- public final GIOPVersion getGIOPVersion() {
- return impl.getGIOPVersion();
- }
-
- public final BufferManagerRead getBufferManager() {
- return impl.getBufferManager();
- }
-
- // This should be overridden by any stream (ex: IIOPInputStream)
- // which wants to read values. Thus, TypeCodeInputStream doesn't
- // have to do this.
- public CodeBase getCodeBase() {
- return null;
- }
-
- // Use Latin-1 for GIOP 1.0 or when code set negotiation was not
- // performed.
- protected CodeSetConversion.BTCConverter createCharBTCConverter() {
- return CodeSetConversion.impl().getBTCConverter(OSFCodeSetRegistry.ISO_8859_1,
- impl.isLittleEndian());
- }
-
- // Subclasses must decide what to do here. It's inconvenient to
- // make the class and this method abstract because of dup().
- protected abstract CodeSetConversion.BTCConverter createWCharBTCConverter();
-
- // Prints the current buffer in a human readable form
- void printBuffer() {
- impl.printBuffer();
- }
-
- /**
- * Aligns the current position on the given octet boundary
- * if there are enough bytes available to do so. Otherwise,
- * it just returns. This is used for some (but not all)
- * GIOP 1.2 message headers.
- */
- public void alignOnBoundary(int octetBoundary) {
- impl.alignOnBoundary(octetBoundary);
- }
-
- // Needed by request and reply messages for GIOP versions >= 1.2 only.
- public void setHeaderPadding(boolean headerPadding) {
- impl.setHeaderPadding(headerPadding);
- }
-
- /**
- * This must be called after determining the proper ORB version,
- * and setting it on the stream's ORB instance. It can be called
- * after reading the service contexts, since that is the only place
- * we can get the ORB version info.
- *
- * Trying to unmarshal things requiring repository IDs before calling
- * this will result in NullPtrExceptions.
- */
- public void performORBVersionSpecificInit() {
- // In the case of SystemExceptions, a stream is created
- // with its default constructor (and thus no impl is set).
- if (impl != null)
- impl.performORBVersionSpecificInit();
- }
-
- /**
- * Resets any internal references to code set converters.
- * This is useful for forcing the CDR stream to reacquire
- * converters (probably from its subclasses) when state
- * has changed.
- */
- public void resetCodeSetConverters() {
- impl.resetCodeSetConverters();
- }
-
- public void setMessageMediator(MessageMediator messageMediator)
- {
- this.messageMediator = (CorbaMessageMediator) messageMediator;
- }
-
- public MessageMediator getMessageMediator()
- {
- return messageMediator;
- }
-
- // ValueInputStream -----------------------------
-
- public void start_value() {
- impl.start_value();
- }
-
- public void end_value() {
- impl.end_value();
- }
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/copyobject/JavaOutputStream.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,435 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.sun.corba.se.impl.encoding;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.nio.ByteBuffer;
-
-import org.omg.CORBA.TypeCode;
-import org.omg.CORBA.Principal;
-import org.omg.CORBA.Any;
-
-import com.sun.corba.se.pept.protocol.MessageMediator;
-
-import com.sun.corba.se.spi.orb.ORB;
-import com.sun.corba.se.spi.logging.CORBALogDomains;
-import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
-import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
-
-import com.sun.corba.se.impl.encoding.CodeSetConversion;
-import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
-import com.sun.corba.se.impl.orbutil.ORBConstants;
-import com.sun.corba.se.impl.logging.ORBUtilSystemException;
-
-/**
- * This is delegates to the real implementation.
- */
-public abstract class CDROutputStream
- extends org.omg.CORBA_2_3.portable.OutputStream
- implements com.sun.corba.se.impl.encoding.MarshalOutputStream,
- org.omg.CORBA.DataOutputStream, org.omg.CORBA.portable.ValueOutputStream
-{
-/*
- private CDROutputStreamBase impl;
- protected ORB orb ;
- protected ORBUtilSystemException wrapper ;
- protected CorbaMessageMediator corbaMessageMediator;
-
-
- // We can move this out somewhere later. For now, it serves its purpose
- // to create a concrete CDR delegate based on the GIOP version.
- private static class OutputStreamFactory {
-
- public static CDROutputStreamBase newOutputStream(ORB orb, GIOPVersion version)
- {
- switch(version.intValue()) {
- case GIOPVersion.VERSION_1_0:
- return new CDROutputStream_1_0();
- case GIOPVersion.VERSION_1_1:
- return new CDROutputStream_1_1();
- case GIOPVersion.VERSION_1_2:
- return new CDROutputStream_1_2();
- default:
- ORBUtilSystemException wrapper = ORBUtilSystemException.get( orb,
- CORBALogDomains.RPC_ENCODING ) ;
- // REVISIT - what is appropriate? INTERNAL exceptions
- // are really hard to track later.
- throw wrapper.unsupportedGiopVersion( version ) ;
- }
- }
- }
-
- // REVISIT - These two constructors should be re-factored to better hide
- // the fact that someone extending this class 'can' construct a CDROutputStream
- // that does not use pooled ByteBuffers. Right now, only EncapsOutputStream
- // does _not_ use pooled ByteBuffers, see EncapsOutputStream.
-
- // NOTE: When a stream is constructed for non-channel-backed sockets
- // it notifies the constructor not to use pooled (i.e, direct)
- // ByteBuffers.
-
- public CDROutputStream(ORB orb,
- GIOPVersion version,
- boolean littleEndian,
- BufferManagerWrite bufferManager,
- byte streamFormatVersion,
- boolean usePooledByteBuffers)
- {
- impl = OutputStreamFactory.newOutputStream(orb, version);
- impl.init(orb, littleEndian, bufferManager, streamFormatVersion, usePooledByteBuffers);
-
- impl.setParent(this);
- this.orb = orb ;
- this.wrapper = ORBUtilSystemException.get( orb,
- CORBALogDomains.RPC_ENCODING ) ;
- }
-
- public CDROutputStream(ORB orb,
- GIOPVersion version,
- boolean littleEndian,
- BufferManagerWrite bufferManager,
- byte streamFormatVersion)
- {
- this(orb, version, littleEndian, bufferManager, streamFormatVersion, true);
- }
-*/
-
- private ByteArrayOutputStream bos ;
- private ObjectOutputStream oos ;
-
- public JavaOutputStream()
- {
- bos = new ByteArrayOutputStream() ;
- oos = new ObjectOutputStream( bos ) ;
- }
-
- // Provided by IIOPOutputStream and EncapsOutputStream
- public org.omg.CORBA.portable.InputStream create_input_stream()
- {
- ObjectInputStream ois = new ByteArrayInputStream( bos.toByteArray() ) ;
-
- return new JavaInputStream( ois ) ;
- }
-
- public final void write_boolean(boolean value) {
- impl.write_boolean(value);
- }
- public final void write_char(char value) {
- impl.write_char(value);
- }
- public final void write_wchar(char value) {
- impl.write_wchar(value);
- }
- public final void write_octet(byte value) {
- impl.write_octet(value);
- }
- public final void write_short(short value) {
- impl.write_short(value);
- }
- public final void write_ushort(short value) {
- impl.write_ushort(value);
- }
- public final void write_long(int value) {
- impl.write_long(value);
- }
- public final void write_ulong(int value) {
- impl.write_ulong(value);
- }
- public final void write_longlong(long value) {
- impl.write_longlong(value);
- }
- public final void write_ulonglong(long value) {
- impl.write_ulonglong(value);
- }
- public final void write_float(float value) {
- impl.write_float(value);
- }
- public final void write_double(double value) {
- impl.write_double(value);
- }
- public final void write_string(String value) {
- impl.write_string(value);
- }
- public final void write_wstring(String value) {
- impl.write_wstring(value);
- }
-
- public final void write_boolean_array(boolean[] value, int offset, int length) {
- impl.write_boolean_array(value, offset, length);
- }
- public final void write_char_array(char[] value, int offset, int length) {
- impl.write_char_array(value, offset, length);
- }
- public final void write_wchar_array(char[] value, int offset, int length) {
- impl.write_wchar_array(value, offset, length);
- }
- public final void write_octet_array(byte[] value, int offset, int length) {
- impl.write_octet_array(value, offset, length);
- }
- public final void write_short_array(short[] value, int offset, int length) {
- impl.write_short_array(value, offset, length);
- }
- public final void write_ushort_array(short[] value, int offset, int length){
- impl.write_ushort_array(value, offset, length);
- }
- public final void write_long_array(int[] value, int offset, int length) {
- impl.write_long_array(value, offset, length);
- }
- public final void write_ulong_array(int[] value, int offset, int length) {
- impl.write_ulong_array(value, offset, length);
- }
- public final void write_longlong_array(long[] value, int offset, int length) {
- impl.write_longlong_array(value, offset, length);
- }
- public final void write_ulonglong_array(long[] value, int offset,int length) {
- impl.write_ulonglong_array(value, offset, length);
- }
- public final void write_float_array(float[] value, int offset, int length) {
- impl.write_float_array(value, offset, length);
- }
- public final void write_double_array(double[] value, int offset, int length) {
- impl.write_double_array(value, offset, length);
- }
- public final void write_Object(org.omg.CORBA.Object value) {
- impl.write_Object(value);
- }
- public final void write_TypeCode(TypeCode value) {
- impl.write_TypeCode(value);
- }
- public final void write_any(Any value) {
- impl.write_any(value);
- }
-
- public final void write_Principal(Principal value) {
- impl.write_Principal(value);
- }
-
- public final void write(int b) throws java.io.IOException {
- impl.write(b);
- }
-
- public final void write_fixed(java.math.BigDecimal value) {
- impl.write_fixed(value);
- }
-
- public final void write_Context(org.omg.CORBA.Context ctx,
- org.omg.CORBA.ContextList contexts) {
- impl.write_Context(ctx, contexts);
- }
-
- public final org.omg.CORBA.ORB orb() {
- return impl.orb();
- }
-
- // org.omg.CORBA_2_3.portable.OutputStream
- public final void write_value(java.io.Serializable value) {
- impl.write_value(value);
- }
-
- public final void write_value(java.io.Serializable value, java.lang.Class clz) {
- impl.write_value(value, clz);
- }
-
- public final void write_value(java.io.Serializable value, String repository_id) {
- impl.write_value(value, repository_id);
- }
-
- public final void write_value(java.io.Serializable value,
- org.omg.CORBA.portable.BoxedValueHelper factory) {
- impl.write_value(value, factory);
- }
-
- public final void write_abstract_interface(java.lang.Object obj) {
- impl.write_abstract_interface(obj);
- }
-
- // java.io.OutputStream
- public final void write(byte b[]) throws IOException {
- impl.write(b);
- }
-
- public final void write(byte b[], int off, int len) throws IOException {
- impl.write(b, off, len);
- }
-
- public final void flush() throws IOException {
- impl.flush();
- }
-
- public final void close() throws IOException {
- impl.close();
- }
-
- // com.sun.corba.se.impl.encoding.MarshalOutputStream
- public final void start_block() {
- impl.start_block();
- }
-
- public final void end_block() {
- impl.end_block();
- }
-
- public final void putEndian() {
- impl.putEndian();
- }
-
- public void writeTo(java.io.OutputStream s)
- throws IOException
- {
- impl.writeTo(s);
- }
-
- public final byte[] toByteArray() {
- return impl.toByteArray();
- }
-
- // org.omg.CORBA.DataOutputStream
- public final void write_Abstract (java.lang.Object value) {
- impl.write_Abstract(value);
- }
-
- public final void write_Value (java.io.Serializable value) {
- impl.write_Value(value);
- }
-
- public final void write_any_array(org.omg.CORBA.Any[] seq, int offset, int length) {
- impl.write_any_array(seq, offset, length);
- }
-
- public void setMessageMediator(MessageMediator messageMediator)
- {
- this.corbaMessageMediator = (CorbaMessageMediator) messageMediator;
- }
-
- public MessageMediator getMessageMediator()
- {
- return corbaMessageMediator;
- }
-
- // org.omg.CORBA.portable.ValueBase
- public final String[] _truncatable_ids() {
- return impl._truncatable_ids();
- }
-
- // Other
- protected final int getSize() {
- return impl.getSize();
- }
-
- protected final int getIndex() {
- return impl.getIndex();
- }
-
- protected int getRealIndex(int index) {
- // Used in indirections. Overridden by TypeCodeOutputStream.
- return index;
- }
-
- protected final void setIndex(int value) {
- impl.setIndex(value);
- }
-
- protected final ByteBuffer getByteBuffer() {
- return impl.getByteBuffer();
- }
-
- protected final void setByteBuffer(ByteBuffer byteBuffer) {
- impl.setByteBuffer(byteBuffer);
- }
-
- public final boolean isLittleEndian() {
- return impl.isLittleEndian();
- }
-
- // XREVISIT - return to final if possible
- // REVISIT - was protected - need access from msgtypes test.
- public ByteBufferWithInfo getByteBufferWithInfo() {
- return impl.getByteBufferWithInfo();
- }
-
- protected void setByteBufferWithInfo(ByteBufferWithInfo bbwi) {
- impl.setByteBufferWithInfo(bbwi);
- }
-
- // REVISIT: was protected - but need to access from xgiop.
- public final BufferManagerWrite getBufferManager() {
- return impl.getBufferManager();
- }
-
- public final void write_fixed(java.math.BigDecimal bigDecimal, short digits, short scale) {
- impl.write_fixed(bigDecimal, digits, scale);
- }
-
- public final void writeOctetSequenceTo(org.omg.CORBA.portable.OutputStream s) {
- impl.writeOctetSequenceTo(s);
- }
-
- public final GIOPVersion getGIOPVersion() {
- return impl.getGIOPVersion();
- }
-
- public final void writeIndirection(int tag, int posIndirectedTo) {
- impl.writeIndirection(tag, posIndirectedTo);
- }
-
- // Use Latin-1 for GIOP 1.0 or when code set negotiation was not
- // performed.
- protected CodeSetConversion.CTBConverter createCharCTBConverter() {
- return CodeSetConversion.impl().getCTBConverter(OSFCodeSetRegistry.ISO_8859_1);
- }
-
- // Subclasses must decide what to do here. It's inconvenient to
- // make the class and this method abstract because of dup().
- protected abstract CodeSetConversion.CTBConverter createWCharCTBConverter();
-
- protected final void freeInternalCaches() {
- impl.freeInternalCaches();
- }
-
- void printBuffer() {
- impl.printBuffer();
- }
-
- public void alignOnBoundary(int octetBoundary) {
- impl.alignOnBoundary(octetBoundary);
- }
-
- // Needed by request and reply messages for GIOP versions >= 1.2 only.
- public void setHeaderPadding(boolean headerPadding) {
- impl.setHeaderPadding(headerPadding);
- }
-
- // ValueOutputStream -----------------------------
-
- public void start_value(String rep_id) {
- impl.start_value(rep_id);
- }
-
- public void end_value() {
- impl.end_value();
- }
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/interceptors/ThreadCurrentStack.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.corba.se.impl.interceptors;
-
-import com.sun.corba.se.impl.corba.AnyImpl;
-import org.omg.PortableInterceptor.Current;
-import org.omg.PortableInterceptor.InvalidSlot;
-
-import com.sun.corba.se.impl.util.MinorCodes;
-import com.sun.corba.se.impl.core.ORB;
-
-/**
- * ThreadCurrentStack is the container of PICurrent instances for each thread
- */
-public class ThreadCurrentStack
-{
- // PICurrentPool is the container for reusable PICurrents
- private class PICurrentPool {
-
- // Contains a list of reusable PICurrents
- private java.util.ArrayList pool;
-
- // High water mark for the pool
- // If the pool size reaches this limit then putPICurrent will
- // not put PICurrent to the pool.
- private static final int HIGH_WATER_MARK = 5;
-
- // currentIndex points to the last PICurrent in the list
- private int currentIndex;
-
- PICurrentPool( ) {
- pool = new java.util.ArrayList( HIGH_WATER_MARK );
- currentIndex = 0;
- }
-
- /**
- * Puts PICurrent to the re-usable pool.
- */
- void putPICurrent( PICurrent current ) {
- // If there are enough PICurrents in the pool, then don't add
- // this current to the pool.
- if( currentIndex >= HIGH_WATER_MARK ) {
- return;
- }
- pool.add(currentIndex , current);
- currentIndex++;
- }
-
- /**
- * Gets PICurrent from the re-usable pool.
- */
- PICurrent getPICurrent( ) {
- // If there are no entries in the pool then return null
- if( currentIndex == 0 ) {
- return null;
- }
- // Works like a stack, Gets the last one added first
- currentIndex--;
- return (PICurrent) pool.get(currentIndex);
- }
- }
-
- // Contains all the active PICurrents for each thread.
- // The ArrayList is made to behave like a stack.
- private java.util.ArrayList currentContainer;
-
- // Keeps track of number of PICurrents in the stack.
- private int currentIndex;
-
- // For Every Thread there will be a pool of re-usable ThreadCurrent's
- // stored in PICurrentPool
- private PICurrentPool currentPool;
-
- // The orb associated with this ThreadCurrentStack
- private ORB piOrb;
-
- /**
- * Constructs the stack and and PICurrentPool
- */
- ThreadCurrentStack( ORB piOrb, PICurrent current ) {
- this.piOrb = piOrb;
- currentIndex = 0;
- currentContainer = new java.util.ArrayList( );
- currentPool = new PICurrentPool( );
- currentContainer.add( currentIndex, current );
- currentIndex++;
- }
-
-
- /**
- * pushPICurrent goes through the following steps
- * 1: Checks to see if there is any PICurrent in PICurrentPool
- * If present then use that instance to push into the ThreadCurrentStack
- *
- * 2:If there is no PICurrent in the pool, then creates a new one and pushes
- * that into the ThreadCurrentStack
- */
- void pushPICurrent( ) {
- PICurrent current = currentPool.getPICurrent( );
- if( current == null ) {
- // get an existing PICurrent to get the slotSize
- PICurrent currentTemp = peekPICurrent();
- current = new PICurrent( piOrb, currentTemp.getSlotSize( ));
- }
- currentContainer.add( currentIndex, current );
- currentIndex++;
- }
-
- /**
- * popPICurrent does the following
- * 1: pops the top PICurrent in the ThreadCurrentStack
- *
- * 2: resets the slots in the PICurrent which resets the slotvalues to
- * null if there are any previous sets.
- *
- * 3: pushes the reset PICurrent into the PICurrentPool to reuse
- */
- void popPICurrent( ) {
- // Do not pop the PICurrent, If there is only one.
- // This should not happen, But an extra check for safety.
- if( currentIndex <= 1 ) {
- throw new org.omg.CORBA.INTERNAL(
- "Cannot pop the only PICurrent in the stack",
- MinorCodes.CANT_POP_ONLY_CURRENT_2,
- CompletionStatus.COMPLETED_NO );
- }
- currentIndex--;
- PICurrent current = (PICurrent)currentContainer.get( currentIndex );
- current.resetSlots( );
- currentPool.putPICurrent( current );
- }
-
- /**
- * peekPICurrent gets the top PICurrent in the ThreadCurrentStack without
- * popping.
- */
- PICurrent peekPICurrent( ) {
- return (PICurrent) currentContainer.get( currentIndex - 1);
- }
-
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/orbutil/DefineWrapper.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-package com.sun.corba.se.impl.orbutil ;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-/** This class provides just a main method. Its purpose is to allow -D arguments to
-* set up the system properties when starting programs with tools like OptimizeIt that
-* make this difficult or impossible.
-*
-* Invocation: {java launcher of some kind} DefineClass -Dxxx=yyy -Dxxx=yyy ... {class name} arg0, arg1, ...
-* Result: updates system properties with -D args, then uses reflection to invoke {class name}.main with the args
-*/
-
-class DefineWrapper {
- public static void main( String[] args )
- {
- int numberDefines = args.length ;
- String className = null ;
-
- for (int ctr=0; ctr \n\nem que inclui:\n -port porta de ativa\u00E7\u00E3o na qual o ORBD deve ser iniciado, default 1049 (opcional)\n -defaultdb diret\u00F3rio dos arquivos ORBD, default "./orb.db" (opcional)\n -serverid id do servidor para ORBD, default 1 (opcional)\n -ORBInitialPort porta inicial (obrigat\u00F3rio)\n -ORBInitialHost nome de host inicial (obrigat\u00F3rio)\n
+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 (obrigat\u00F3rio)\n -ORBInitialHost nome de host inicial (obrigat\u00F3rio)\n
servertool.usage=Uso: {0} \n\nem que inclui:\n -ORBInitialPort porta inicial (obrigat\u00F3rio)\n -ORBInitialHost nome de host inicial (obrigat\u00F3rio)\n
servertool.banner=\n\nBem-vindo \u00E0 Ferramenta de Servidor IDL Java \ninsira os comandos no prompt \n
--- ./corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLNameTranslatorImpl_save.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,909 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.corba.se.impl.presentation.rmi ;
-
-import java.lang.reflect.Method;
-
-import java.math.BigInteger;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-
-import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;
-
-import com.sun.corba.se.impl.presentation.rmi.IDLType ;
-import com.sun.corba.se.impl.presentation.rmi.IDLTypeException ;
-import com.sun.corba.se.impl.presentation.rmi.IDLTypesUtil ;
-import com.sun.corba.se.impl.orbutil.ObjectUtility ;
-
-/**
- * Bidirectional translator between RMI-IIOP interface methods and
- * and IDL Names.
- */
-public class IDLNameTranslatorImpl implements IDLNameTranslator {
-
- // From CORBA Spec, Table 6 Keywords.
- // Note that since all IDL identifiers are case
- // insensitive, java identifier comparisons to these
- // will be case insensitive also.
- private static String[] IDL_KEYWORDS = {
-
- "abstract", "any", "attribute", "boolean", "case", "char",
- "const", "context", "custom", "default", "double", "enum",
- "exception", "factory", "FALSE", "fixed", "float", "in", "inout",
- "interface", "long", "module", "native", "Object", "octet",
- "oneway", "out", "private", "public", "raises", "readonly", "sequence",
- "short", "string", "struct", "supports", "switch", "TRUE", "truncatable",
- "typedef", "unsigned", "union", "ValueBase", "valuetype", "void",
- "wchar", "wstring"
-
- };
-
- private static char[] HEX_DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F'
- };
-
- private static final String UNDERSCORE = "_";
-
- // used to mangle java inner class names
- private static final String INNER_CLASS_SEPARATOR =
- UNDERSCORE + UNDERSCORE;
-
- // used to form IDL array type names
- private static final String[] BASE_IDL_ARRAY_MODULE_TYPE=
- new String[] { "org", "omg", "boxedRMI" } ;
-
- private static final String BASE_IDL_ARRAY_ELEMENT_TYPE = "seq";
-
- // used to mangling java identifiers that have a leading underscore
- private static final String LEADING_UNDERSCORE_CHAR = "J";
- private static final String ID_CONTAINER_CLASH_CHAR = UNDERSCORE;
-
- // separator used between types in a mangled overloaded method name
- private static final String OVERLOADED_TYPE_SEPARATOR =
- UNDERSCORE + UNDERSCORE;
-
- // string appended to attribute if it clashes with a method name
- private static final String ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS =
- UNDERSCORE + UNDERSCORE;
-
- private static Set idlKeywords_;
-
- static {
-
- idlKeywords_ = new HashSet();
- for(int i = 0; i < IDL_KEYWORDS.length; i++) {
- String next = (String) IDL_KEYWORDS[i];
- // Convert keyword to all caps to ease equality
- // check.
- String keywordAllCaps = next.toUpperCase();
- idlKeywords_.add(keywordAllCaps);
- }
-
- }
-
- //
- // Instance state
- //
-
- // Remote interface for name translation.
- private Class[] interf_;
-
- // Maps used to hold name translations. These do not need to be
- // synchronized since the translation is never modified after
- // initialization.
- private Map methodToIDLNameMap_;
- private Map IDLNameToMethodMap_;
- private Method[] methods_;
-
- /**
- * Return an IDLNameTranslator for the given interface.
- *
- * @throws IllegalStateException if given class is not a valid
- * RMI/IIOP Remote Interface
- */
- public static IDLNameTranslator get( Class interf )
- {
-
- return new IDLNameTranslatorImpl(new Class[] { interf } );
-
- }
-
- /**
- * Return an IDLNameTranslator for the given interfacex.
- *
- * @throws IllegalStateException if given classes are not valid
- * RMI/IIOP Remote Interfaces
- */
- public static IDLNameTranslator get( Class[] interfaces )
- {
-
- return new IDLNameTranslatorImpl(interfaces );
-
- }
-
- public static String getExceptionId( Class cls )
- {
- // Requirements for this method:
- // 1. cls must be an exception but not a RemoteException.
- // 2. If cls has an IDL keyword name, an underscore is prepended (1.3.2.2).
- // 3. If cls jas a leading underscore, J is prepended (1.3.2.3).
- // 4. If cls has an illegal IDL ident char, it is mapped to UXXXX where
- // XXXX is the unicode value in hex of the char (1.3.2.4).
- // 5. double underscore for inner class (1.3.2.5).
- // 6. The ID is "IDL:" + name with / separators + ":1.0".
- IDLType itype = classToIDLType( cls ) ;
- return itype.getExceptionName() ;
- }
-
- public Class[] getInterfaces()
- {
- return interf_;
- }
-
- public Method[] getMethods()
- {
- return methods_ ;
- }
-
- public Method getMethod( String idlName )
- {
- return (Method) IDLNameToMethodMap_.get(idlName);
- }
-
- public String getIDLName( Method method )
- {
- return (String) methodToIDLNameMap_.get(method);
- }
-
- /**
- * Initialize an IDLNameTranslator for the given interface.
- *
- * @throws IllegalStateException if given class is not a valid
- * RMI/IIOP Remote Interface
- */
- private IDLNameTranslatorImpl(Class[] interfaces)
- {
-
- try {
- IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
- for (int ctr=0; ctr and get methods.
-
-
- //
- // Perform case sensitivity test first. This applies to all
- // method names AND attributes. Compare each method name and
- // attribute to all other method names and attributes. If names
- // differ only in case, apply mangling as defined in section 1.3.2.7
- // of Java2IDL spec. Note that we compare using the original names.
- //
- for(Iterator outerIter=allMethodInfo.values().iterator();
- outerIter.hasNext();) {
- IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
- for(Iterator innerIter = allMethodInfo.values().iterator();
- innerIter.hasNext();) {
- IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
-
- if( (outer != inner) &&
- (!outer.originalName.equals(inner.originalName)) &&
- outer.originalName.equalsIgnoreCase(inner.originalName) ) {
- outer.mangledName =
- mangleCaseSensitiveCollision(outer.originalName);
- break;
- }
-
- }
- }
-
- for(Iterator iter = allMethodInfo.values().iterator();
- iter.hasNext();) {
- IDLMethodInfo next = (IDLMethodcurrentInfo) iter.next();
- next.mangledName =
- mangleIdentifier(next.mangledName,
- next.propertyType != null);
- }
-
- //
- // Now check for overloaded method names and apply 1.3.2.6.
- //
- for(Iterator outerIter=allMethodInfo.values().iterator();
- outerIter.hasNext();) {
- IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
- if (outer.propertyType != null) {
- continue;
- }
- for(Iterator innerIter = allMethodInfo.values().iterator();
- innerIter.hasNext();) {
- IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
-
- if( (outer != inner) &&
- (inner.propertyType == null) &&
- outer.originalName.equals(inner.originalName) ) {
- outer.mangledName = mangleOverloadedMethod
- (outer.mangledName, outer.method);
- break;
- }
- }
- }
-
- //
- // Now mangle any properties that clash with method names.
- //
- for(Iterator outerIter=allMethodInfo.values().iterator();
- outerIter.hasNext();) {
- IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
- if(outer.propertyType == null) {
- continue;
- }
- for(Iterator innerIter = allMethodInfo.values().iterator();
- innerIter.hasNext();) {
- IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
- if( (outer != inner) &&
- (inner.propertyType == null) &&
- outer.mangledName.equals(inner.mangledName) ) {
- outer.mangledName = outer.mangledName +
- ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS;
- break;
- }
- }
- }
-
- //
- // Ensure that no mapped method names clash with mapped name
- // of container(1.3.2.9). This is a case insensitive comparison.
- //
- for (int ctr=0; ctr and get,
- // map only is to an attribute, and leave the
- // get method alone.
- if( IDLNameToMethodMap_.containsKey(idlName) ) {
- // @@@ I18N
- Method clash = (Method) IDLNameToMethodMap_.get(idlName);
- MethodInfo clashMethodInfo =
- (MethodInfo)allMethodInfo.get( clash ) ;
- if (clashMethodInfo.isBooleanProperty() &&
- next.isReadProperty()) {
- // fix idlName
- } else if (clashMethodInfo.isReadProperty() &&
- next.isBooleanProperty()) {
- // Remove entry under idlName
- // put entry into table under correct name
- } else {
- throw new IllegalStateException("Error : methods " +
- clash + " and " + next.method +
- " both result in IDL name '" + idlName + "'");
- }
- }
-
- IDLNameToMethodMap_.put(idlName, next.method);
- }
-
- return;
-
- }
-
-
- /**
- * Perform all necessary stand-alone identifier mangling operations
- * on a java identifier that is being transformed into an IDL name.
- * That is, mangling operations that don't require looking at anything
- * else but the identifier itself. This covers sections 1.3.2.2, 1.3.2.3,
- * and 1.3.2.4 of the Java2IDL spec. Method overloading and
- * case-sensitivity checks are handled elsewhere.
- */
-
- private static String mangleIdentifier(String identifier) {
- return mangleIdentifier(identifier, false);
- }
-
- private static String mangleIdentifier(String identifier, boolean attribute) {
-
- String mangledName = identifier;
-
- //
- // Apply leading underscore test (1.3.2.3)
- // This should be done before IDL Keyword clash test, since clashing
- // IDL keywords are mangled by adding a leading underscore.
- //
- if( hasLeadingUnderscore(mangledName) ) {
- mangledName = mangleLeadingUnderscore(mangledName);
- }
-
- //
- // Apply IDL keyword clash test (1.3.2.2).
- // This is not needed for attributes since when the full property
- // name is composed it cannot clash with an IDL keyword.
- // (Also, rmic doesn't do it.)
- //
-
- if( !attribute && isIDLKeyword(mangledName) ) {
- mangledName = mangleIDLKeywordClash(mangledName);
- }
-
- //
- // Replace illegal IDL identifier characters (1.3.2.4)
- // for all method names and attributes.
- //
- if( !isIDLIdentifier(mangledName) ) {
- mangledName = mangleUnicodeChars(mangledName);
- }
-
- return mangledName;
- }
-
- /**
- * Checks whether a java identifier clashes with an
- * IDL keyword. Note that this is a case-insensitive
- * comparison.
- *
- * Used to implement section 1.3.2.2 of Java2IDL spec.
- */
- private static boolean isIDLKeyword(String identifier) {
-
- String identifierAllCaps = identifier.toUpperCase();
-
- return idlKeywords_.contains(identifierAllCaps);
- }
-
- private static String mangleIDLKeywordClash(String identifier) {
- return UNDERSCORE + identifier;
- }
-
- private static String mangleLeadingUnderscore(String identifier) {
- return LEADING_UNDERSCORE_CHAR + identifier;
- }
-
- /**
- * Checks whether a java identifier starts with an underscore.
- * Used to implement section 1.3.2.3 of Java2IDL spec.
- */
- private static boolean hasLeadingUnderscore(String identifier) {
- return identifier.startsWith(UNDERSCORE);
- }
-
- /**
- * Implements Section 1.3.2.4 of Java2IDL Mapping.
- * All non-IDL identifier characters must be replaced
- * with their Unicode representation.
- */
- static String mangleUnicodeChars(String identifier) {
- StringBuffer mangledIdentifier = new StringBuffer();
-
- for(int i = 0; i < identifier.length(); i++) {
- char nextChar = identifier.charAt(i);
- if( isIDLIdentifierChar(nextChar) ) {
- mangledIdentifier.append(nextChar);
- } else {
- String unicode = charToUnicodeRepresentation(nextChar);
- mangledIdentifier.append(unicode);
- }
- }
-
- return mangledIdentifier.toString();
- }
-
- /**
- * Implements mangling portion of Section 1.3.2.7 of Java2IDL spec.
- * This method only deals with the actual mangling. Decision about
- * whether case-sensitive collision mangling is required is made
- * elsewhere.
- *
- *
- * "...a mangled name is generated consisting of the original name
- * followed by an underscore separated list of decimal indices
- * into the string, where the indices identify all the upper case
- * characters in the original string. Indices are zero based."
- *
- */
- String mangleCaseSensitiveCollision(String identifier) {
-
- StringBuffer mangledIdentifier = new StringBuffer(identifier);
-
- // There is always at least one trailing underscore, whether or
- // not the identifier has uppercase letters.
- mangledIdentifier.append(UNDERSCORE);
-
- boolean needUnderscore = false;
- for(int i = 0; i < identifier.length(); i++) {
- char next = identifier.charAt(i);
- if( Character.isUpperCase(next) ) {
- // This bit of logic is needed to ensure that we have
- // an underscore separated list of indices but no
- // trailing underscores. Basically, after we have at least
- // one uppercase letter, we always put an undercore before
- // printing the next one.
- if( needUnderscore ) {
- mangledIdentifier.append(UNDERSCORE);
- }
- mangledIdentifier.append(i);
- needUnderscore = true;
- }
- }
-
- return mangledIdentifier.toString();
- }
-
- private static String mangleContainerClash(String identifier) {
- return identifier + ID_CONTAINER_CLASH_CHAR;
- }
-
- /**
- * Implements Section 1.3.2.9 of Java2IDL Mapping. Container in this
- * context means the name of the java Class(excluding package) in which
- * the identifier is defined. Comparison is case-insensitive.
- */
- private static boolean identifierClashesWithContainer
- (String mappedContainerName, String identifier) {
-
- return identifier.equalsIgnoreCase(mappedContainerName);
- }
-
- /**
- * Returns Unicode mangling as defined in Section 1.3.2.4 of
- * Java2IDL spec.
- *
- * "For Java identifiers that contain illegal OMG IDL identifier
- * characters such as '$' or Unicode characters outside of ISO Latin 1,
- * any such illegal characters are replaced by "U" followed by the
- * 4 hexadecimal characters(in upper case) representing the Unicode
- * value. So, the Java name a$b is mapped to aU0024b and
- * x\u03bCy is mapped to xU03BCy."
- */
- public static String charToUnicodeRepresentation(char c) {
-
- int orig = (int) c;
- StringBuffer hexString = new StringBuffer();
-
- int value = orig;
-
- while( value > 0 ) {
- int div = value / 16;
- int mod = value % 16;
- hexString.insert(0, HEX_DIGITS[mod]);
- value = div;
- }
-
- int numZerosToAdd = 4 - hexString.length();
- for(int i = 0; i < numZerosToAdd; i++) {
- hexString.insert(0, "0");
- }
-
- hexString.insert(0, "U");
- return hexString.toString();
- }
-
- private static boolean isIDLIdentifier(String identifier) {
-
- boolean isIdentifier = true;
-
- for(int i = 0; i < identifier.length(); i++) {
- char nextChar = identifier.charAt(i);
- // 1st char must be alphbetic.
- isIdentifier = (i == 0) ?
- isIDLAlphabeticChar(nextChar) :
- isIDLIdentifierChar(nextChar);
- if( !isIdentifier ) {
- break;
- }
- }
-
- return isIdentifier;
-
- }
-
- private static boolean isIDLIdentifierChar(char c) {
- return (isIDLAlphabeticChar(c) ||
- isIDLDecimalDigit(c) ||
- isUnderscore(c));
- }
-
- /**
- * True if character is one of 114 Alphabetic characters as
- * specified in Table 2 of Chapter 3 in CORBA spec.
- */
- private static boolean isIDLAlphabeticChar(char c) {
-
- // NOTE that we can't use the java.lang.Character
- // isUpperCase, isLowerCase, etc. methods since they
- // include many characters other than the Alphabetic list in
- // the CORBA spec. Instead, we test for inclusion in the
- // Unicode value ranges for the corresponding legal characters.
-
- boolean alphaChar =
- (
- // A - Z
- ((c >= 0x0041) && (c <= 0x005A))
-
- ||
-
- // a - z
- ((c >= 0x0061) && (c <= 0x007A))
-
- ||
-
- // other letter uppercase, other letter lowercase, which is
- // the entire upper half of C1 Controls except X and /
- ((c >= 0x00C0) && (c <= 0x00FF)
- && (c != 0x00D7) && (c != 0x00F7)));
-
- return alphaChar;
- }
-
- /**
- * True if character is one of 10 Decimal Digits
- * specified in Table 3 of Chapter 3 in CORBA spec.
- */
- private static boolean isIDLDecimalDigit(char c) {
- return ( (c >= 0x0030) && (c <= 0x0039) );
- }
-
- private static boolean isUnderscore(char c) {
- return ( c == 0x005F );
- }
-
- /**
- * Mangle an overloaded method name as defined in Section 1.3.2.6 of
- * Java2IDL spec. Current value of method name is passed in as argument.
- * We can't start from original method name since the name might have
- * been partially mangled as a result of the other rules.
- */
- private static String mangleOverloadedMethod(String mangledName, Method m) {
-
- IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
-
- // Start by appending the separator string
- String newMangledName = mangledName + OVERLOADED_TYPE_SEPARATOR;
-
- Class[] parameterTypes = m.getParameterTypes();
-
- for(int i = 0; i < parameterTypes.length; i++) {
- Class nextParamType = parameterTypes[i];
-
- if( i > 0 ) {
- newMangledName = newMangledName + OVERLOADED_TYPE_SEPARATOR;
- }
- IDLType idlType = classToIDLType(nextParamType);
-
- String moduleName = idlType.getModuleName();
- String memberName = idlType.getMemberName();
-
- String typeName = (moduleName.length() > 0) ?
- moduleName + UNDERSCORE + memberName : memberName;
-
- if( !idlTypesUtil.isPrimitive(nextParamType) &&
- (idlTypesUtil.getSpecialCaseIDLTypeMapping(nextParamType)
- == null) &&
- isIDLKeyword(typeName) ) {
- typeName = mangleIDLKeywordClash(typeName);
- }
-
- typeName = mangleUnicodeChars(typeName);
-
- newMangledName = newMangledName + typeName;
- }
-
- return newMangledName;
- }
-
-
- private static IDLType classToIDLType(Class c) {
-
- IDLType idlType = null;
- IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
-
- if( idlTypesUtil.isPrimitive(c) ) {
-
- idlType = idlTypesUtil.getPrimitiveIDLTypeMapping(c);
-
- } else if( c.isArray() ) {
-
- // Calculate array depth, as well as base element type.
- Class componentType = c.getComponentType();
- int numArrayDimensions = 1;
- while(componentType.isArray()) {
- componentType = componentType.getComponentType();
- numArrayDimensions++;
- }
- IDLType componentIdlType = classToIDLType(componentType);
-
- String[] modules = BASE_IDL_ARRAY_MODULE_TYPE;
- if( componentIdlType.hasModule() ) {
- modules = (String[])ObjectUtility.concatenateArrays( modules,
- componentIdlType.getModules() ) ;
- }
-
- String memberName = BASE_IDL_ARRAY_ELEMENT_TYPE +
- numArrayDimensions + UNDERSCORE +
- componentIdlType.getMemberName();
-
- idlType = new IDLType(c, modules, memberName);
-
- } else {
- idlType = idlTypesUtil.getSpecialCaseIDLTypeMapping(c);
-
- if (idlType == null) {
- // Section 1.3.2.5 of Java2IDL spec defines mangling rules for
- // inner classes.
- String memberName = getUnmappedContainerName(c);
-
- // replace inner class separator with double underscore
- memberName = memberName.replaceAll("\\$",
- INNER_CLASS_SEPARATOR);
-
- if( hasLeadingUnderscore(memberName) ) {
- memberName = mangleLeadingUnderscore(memberName);
- }
-
- // Get raw package name. If there is a package, it
- // will still have the "." separators and none of the
- // mangling rules will have been applied.
- String packageName = getPackageName(c);
-
- if (packageName == null) {
- idlType = new IDLType( c, memberName ) ;
- } else {
- // If this is a generated IDL Entity Type we need to
- // prepend org_omg_boxedIDL per sections 1.3.5 and 1.3.9
- if (idlTypesUtil.isEntity(c)) {
- packageName = "org.omg.boxedIDL." + packageName ;
- }
-
- // Section 1.3.2.1 and 1.3.2.6 of Java2IDL spec defines
- // rules for mapping java packages to IDL modules and for
- // mangling module name portion of type name. NOTE that
- // of the individual identifier mangling rules,
- // only the leading underscore test is done here.
- // The other two(IDL Keyword, Illegal Unicode chars) are
- // done in mangleOverloadedMethodName.
- StringTokenizer tokenizer =
- new StringTokenizer(packageName, ".");
-
- String[] modules = new String[ tokenizer.countTokens() ] ;
- int index = 0 ;
- while (tokenizer.hasMoreElements()) {
- String next = tokenizer.nextToken();
- String nextMangled = hasLeadingUnderscore(next) ?
- mangleLeadingUnderscore(next) : next;
-
- modules[index++] = nextMangled ;
- }
-
- idlType = new IDLType(c, modules, memberName);
- }
- }
- }
-
- return idlType;
- }
-
- /**
- * Return Class' package name or null if there is no package.
- */
- private static String getPackageName(Class c) {
- Package thePackage = c.getPackage();
- String packageName = null;
-
- // Try to get package name by introspection. Some classloaders might
- // not provide this information, so check for null.
- if( thePackage != null ) {
- packageName = thePackage.getName();
- } else {
- // brute force method
- String fullyQualifiedClassName = c.getName();
- int lastDot = fullyQualifiedClassName.indexOf('.');
- packageName = (lastDot == -1) ? null :
- fullyQualifiedClassName.substring(0, lastDot);
- }
- return packageName;
- }
-
- private static String getMappedContainerName(Class c) {
- String unmappedName = getUnmappedContainerName(c);
-
- return mangleIdentifier(unmappedName);
- }
-
- /**
- * Return portion of class name excluding package name.
- */
- private static String getUnmappedContainerName(Class c) {
-
- String memberName = null;
- String packageName = getPackageName(c);
-
- String fullyQualifiedClassName = c.getName();
-
- if( packageName != null ) {
- int packageLength = packageName.length();
- memberName = fullyQualifiedClassName.substring(packageLength + 1);
- } else {
- memberName = fullyQualifiedClassName;
-
- }
-
- return memberName;
- }
-
- /**
- * Internal helper class for tracking information related to each
- * interface method while we're building the name translation table.
- */
- private static class IDLMethodInfo
- {
- public Method method;
- public String propertyType;
-
- // If this is a property, originalName holds the original
- // attribute name. Otherwise, it holds the original method name.
- public String originalName;
-
- // If this is a property, mangledName holds the mangled attribute
- // name. Otherwise, it holds the mangled method name.
- public String mangledName;
-
- }
-
- public String toString() {
-
- StringBuffer contents = new StringBuffer();
- contents.append("IDLNameTranslator[" );
- for( int ctr=0; ctr 0 ) {
- String className = args[0];
- try {
- remoteInterface = Class.forName(className);
- } catch(Exception e) {
- e.printStackTrace();
- System.exit(-1);
- }
- }
-
- System.out.println("Building name translation for " + remoteInterface);
- try {
- IDLNameTranslator nameTranslator =
- IDLNameTranslatorImpl.get(remoteInterface);
- System.out.println(nameTranslator);
- } catch(IllegalStateException ise) {
- ise.printStackTrace();
- }
- }
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLTypesUtil_save.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,520 +0,0 @@
-
-package com.sun.corba.se.impl.presentation.rmi ;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Field;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Iterator;
-
-/**
- * Utility class for testing RMI/IDL Types as defined in
- * Section 1.2 of The Java Language to IDL Mapping. Note that
- * these are static checks only. Runtime checks, such as those
- * described in Section 1.2.3, #3, are not covered.
- */
-public class IDLTypesUtil {
-
- public static final String JAVA_GET_PROPERTY_PREFIX = "get";
- public static final String JAVA_SET_PROPERTY_PREFIX = "set";
- public static final String JAVA_IS_PROPERTY_PREFIX = "is";
-
- public static final int VALID_TYPE = 0;
- public static final int INVALID_TYPE = 1;
-
- /**
- * Validate a class to ensure it conforms to the rules for a
- * Java RMI/IIOP interface.
- *
- * @throws IDLTypeException if not a valid RMI/IIOP interface.
- */
- public void validateRemoteInterface(Class c) throws IDLTypeException
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- if( !c.isInterface() ) {
- String msg = "Class " + c + " must be a java interface.";
- throw new IDLTypeException(msg);
- }
-
- if( !java.rmi.Remote.class.isAssignableFrom(c) ) {
- String msg = "Class " + c + " must extend java.rmi.Remote, " +
- "either directly or indirectly.";
- throw new IDLTypeException(msg);
- }
-
- // Get all methods, including super-interface methods.
- Method[] methods = c.getMethods();
-
- for(int i = 0; i < methods.length; i++) {
- Method next = methods[i];
- validateExceptions(next);
- }
-
- // Removed because of bug 4989053
- // validateDirectInterfaces(c);
- validateConstants(c);
-
- return;
- }
-
- public boolean isRemoteInterface(Class c)
- {
- boolean remoteInterface = true;
- try {
- validateRemoteInterface(c);
- } catch(IDLTypeException ite) {
- remoteInterface = false;
- }
-
- return remoteInterface;
- }
-
- /**
- * Section 1.2.2 Primitive Types
- */
- public boolean isPrimitive(Class c)
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- return c.isPrimitive();
- }
-
- /**
- * Section 1.2.4
- */
- public boolean isValue(Class c)
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- return
- (!c.isInterface() &&
- java.io.Serializable.class.isAssignableFrom(c) &&
- !java.rmi.Remote.class.isAssignableFrom(c));
- }
-
- /**
- * Section 1.2.5
- */
- public boolean isArray(Class c)
- {
- boolean arrayType = false;
-
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- if( c.isArray() ) {
- Class componentType = c.getComponentType();
- arrayType =
- (isPrimitive(componentType) || isRemoteInterface(componentType) ||
- isEntity(componentType) || isException(componentType) ||
- isValue(componentType) || isObjectReference(componentType) );
- }
-
- return arrayType;
- }
-
- /**
- * Section 1.2.6
- */
- public boolean isException(Class c)
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- // Must be a checked exception, not including RemoteException or
- // its subclasses.
- return isCheckedException(c) && !isRemoteException(c) && isValue(c);
- }
-
- public boolean isRemoteException(Class c)
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- return java.rmi.RemoteException.class.isAssignableFrom(c) ;
- }
-
- public boolean isCheckedException(Class c)
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- return Throwable.class.isAssignableFrom(c) &&
- !RuntimeException.class.isAssignableFrom(c) &&
- !Error.class.isAssignableFrom(c) ;
- }
-
- /**
- * Section 1.2.7
- */
- public boolean isObjectReference(Class c)
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- return (c.isInterface() &&
- org.omg.CORBA.Object.class.isAssignableFrom(c));
- }
-
- /**
- * Section 1.2.8
- */
- public boolean isEntity(Class c)
- {
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- Class superClass = c.getSuperclass();
- return (!c.isInterface() &&
- (superClass != null) &&
- (org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(c)));
- }
-
- public String javaPropertyPrefixToIDL( String javaPrefix )
- {
- return "_" + javaPrefix + "_" ;
- }
-
- /**
- * Return the property type if given method is legal property accessor as defined in
- * Section 1.3.4.3 of Java2IDL spec. Result is one of: JAVA_GET_PROPERTY_PREFIX,
- * JAVA_SET_PROPERTY_PREFIX, JAVA_IS_PROPERTY_PREFIX.
- */
- public String propertyAccessorMethodType(Method m, Class c) {
-
- String methodName = m.getName();
- Class returnType = m.getReturnType();
- Class[] parameters = m.getParameterTypes();
- Class[] exceptionTypes = m.getExceptionTypes();
- String propertyType = null;
-
- if( methodName.startsWith(JAVA_GET_PROPERTY_PREFIX) ) {
-
- if((parameters.length == 0) && (returnType != Void.TYPE) &&
- !hasCorrespondingReadProperty(m, c, JAVA_IS_PROPERTY_PREFIX) {
- propertyType = JAVA_GET_PROPERTY_PREFIX;
- }
-
- } else if( methodName.startsWith(JAVA_SET_PROPERTY_PREFIX) ) {
-
- if((returnType == Void.TYPE) && (parameters.length == 1)) {
- if (hasCorrespondingReadProperty(m, c, JAVA_GET_PROPERTY_PREFIX) ||
- hasCorrespondingReadProperty(m, c, JAVA_IS_PROPERTY_PREFIX)) {
- propertyType = JAVA_SET_PROPERTY_PREFIX;
- }
- }
-
- } else if( methodName.startsWith(JAVA_IS_PROPERTY_PREFIX) ) {
- if((parameters.length == 0) && (returnType == Boolean.TYPE)) {
- propertyType = JAVA_IS_PROPERTY_PREFIX;
- }
- }
-
- // Some final checks that apply to all properties.
- if( propertyType != null ) {
- if(!validPropertyExceptions(m) ||
- (methodName.length() <= propertyType.length())) {
- propertyType = null;
- }
- }
-
- return propertyType ;
- }
-
- private boolean hasCorrespondingReadProperty
- (Method writeProperty, Class c, String readPropertyPrefix) {
-
- String writePropertyMethodName = writeProperty.getName();
- Class[] writePropertyParameters = writeProperty.getParameterTypes();
- boolean foundReadProperty = false;
-
- try {
- // Look for a valid corresponding Read property
- String readPropertyMethodName =
- writePropertyMethodName.replaceFirst
- (JAVA_SET_PROPERTY_PREFIX, readPropertyPrefix);
- Method readPropertyMethod = c.getMethod(readPropertyMethodName,
- new Class[] {});
- foundReadProperty =
- ((propertyAccessorMethodType(readPropertyMethod, c) != null) &&
- (readPropertyMethod.getReturnType() ==
- writePropertyParameters[0]));
- } catch(Exception e) {
- // ignore. this means we didn't find a corresponding get property.
- }
-
- return foundReadProperty;
- }
-
- public String getAttributeNameForProperty(String propertyName) {
- String attributeName = null;
- String prefix = null;
-
- if( propertyName.startsWith(JAVA_GET_PROPERTY_PREFIX) ) {
- prefix = JAVA_GET_PROPERTY_PREFIX;
- } else if( propertyName.startsWith(JAVA_SET_PROPERTY_PREFIX) ) {
- prefix = JAVA_SET_PROPERTY_PREFIX;
- } else if( propertyName.startsWith(JAVA_IS_PROPERTY_PREFIX) ) {
- prefix = JAVA_IS_PROPERTY_PREFIX;
- }
-
- if( (prefix != null) && (prefix.length() < propertyName.length()) ) {
- String remainder = propertyName.substring(prefix.length());
- if( (remainder.length() >= 2) &&
- Character.isUpperCase(remainder.charAt(0)) &&
- Character.isUpperCase(remainder.charAt(1)) ) {
- // don't set the first letter to lower-case if the
- // first two are upper-case
- attributeName = remainder;
- } else {
- attributeName = Character.toLowerCase(remainder.charAt(0)) +
- remainder.substring(1);
- }
- }
-
- return attributeName;
- }
-
- /**
- * Return IDL Type name for primitive types as defined in
- * Section 1.3.3 of Java2IDL spec or null if not a primitive type.
- */
- public IDLType getPrimitiveIDLTypeMapping(Class c) {
-
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- if( c.isPrimitive() ) {
- if( c == Void.TYPE ) {
- return new IDLType( c, "void" ) ;
- } else if( c == Boolean.TYPE ) {
- return new IDLType( c, "boolean" ) ;
- } else if( c == Character.TYPE ) {
- return new IDLType( c, "wchar" ) ;
- } else if( c == Byte.TYPE ) {
- return new IDLType( c, "octet" ) ;
- } else if( c == Short.TYPE ) {
- return new IDLType( c, "short" ) ;
- } else if( c == Integer.TYPE ) {
- return new IDLType( c, "long" ) ;
- } else if( c == Long.TYPE ) {
- return new IDLType( c, "long_long" ) ;
- } else if( c == Float.TYPE ) {
- return new IDLType( c, "float" ) ;
- } else if( c == Double.TYPE ) {
- return new IDLType( c, "double" ) ;
- }
- }
-
- return null;
- }
-
- /**
- * Return IDL Type name for special case type mappings as defined in
- * Table 1-1 of Java2IDL spec or null if given class is not a special
- * type.
- */
- public IDLType getSpecialCaseIDLTypeMapping(Class c) {
-
- if( c == null ) {
- throw new IllegalArgumentException();
- }
-
- if( c == java.lang.Object.class ) {
- return new IDLType( c, new String[] { "java", "lang" },
- "Object" ) ;
- } else if( c == java.lang.String.class ) {
- return new IDLType( c, new String[] { "CORBA" },
- "WStringValue" ) ;
- } else if( c == java.lang.Class.class ) {
- return new IDLType( c, new String[] { "javax", "rmi", "CORBA" },
- "ClassDesc" ) ;
- } else if( c == java.io.Serializable.class ) {
- return new IDLType( c, new String[] { "java", "io" },
- "Serializable" ) ;
- } else if( c == java.io.Externalizable.class ) {
- return new IDLType( c, new String[] { "java", "io" },
- "Externalizable" ) ;
- } else if( c == java.rmi.Remote.class ) {
- return new IDLType( c, new String[] { "java", "rmi" },
- "Remote" ) ;
- } else if( c == org.omg.CORBA.Object.class ) {
- return new IDLType( c, "Object" ) ;
- } else {
- return null;
- }
- }
-
- /**
- * Implements 1.2.3 #2 and #4
- */
- private void validateExceptions(Method method) throws IDLTypeException {
-
- Class[] exceptions = method.getExceptionTypes();
-
- boolean declaresRemoteExceptionOrSuperClass = false;
-
- // Section 1.2.3, #2
- for(int eIndex = 0; eIndex < exceptions.length; eIndex++) {
- Class exception = exceptions[eIndex];
- if( isRemoteExceptionOrSuperClass(exception) ) {
- declaresRemoteExceptionOrSuperClass = true;
- break;
- }
- }
-
- if( !declaresRemoteExceptionOrSuperClass ) {
- String msg = "Method '" + method + "' must throw at least one " +
- "exception of type java.rmi.RemoteException or one of its " +
- "super-classes";
- throw new IDLTypeException(msg);
- }
-
- // Section 1.2.3, #4
- // See also bug 4972402
- // For all exceptions E in exceptions,
- // (isCheckedException(E) => (isValue(E) || RemoteException.isAssignableFrom( E ) )
- for(int eIndex = 0; eIndex < exceptions.length; eIndex++) {
- Class exception = exceptions[eIndex];
-
- if (isCheckedException(exception) && !isValue(exception) &&
- !isRemoteException(exception))
- {
- String msg = "Exception '" + exception + "' on method '" +
- method + "' is not a allowed RMI/IIOP exception type";
- throw new IDLTypeException(msg);
- }
- }
-
- return;
- }
-
- /**
- * Returns true if the method's throw clause conforms to the exception
- * restrictions for properties as defined in Section 1.3.4.3 of
- * Java2IDL spec. This means that for all exceptions E declared on the
- * method, E isChecked => RemoteException.isAssignableFrom( E ).
- */
- private boolean validPropertyExceptions(Method method)
- {
- Class[] exceptions = method.getExceptionTypes();
-
- for(int eIndex = 0; eIndex < exceptions.length; eIndex++) {
- Class exception = exceptions[eIndex];
-
- if (isCheckedException(exception) && !isRemoteException(exception))
- return false ;
- }
-
- return true;
- }
-
- /**
- * Implements Section 1.2.3, #2.
- */
- private boolean isRemoteExceptionOrSuperClass(Class c) {
- return
- ((c == java.rmi.RemoteException.class) ||
- (c == java.io.IOException.class) ||
- (c == java.lang.Exception.class) ||
- (c == java.lang.Throwable.class));
- }
-
- /**
- * Implements Section 1.2.3, #5.
- */
- private void validateDirectInterfaces(Class c) throws IDLTypeException {
-
- Class[] directInterfaces = c.getInterfaces();
-
- if( directInterfaces.length < 2 ) {
- return;
- }
-
- Set allMethodNames = new HashSet();
- Set currentMethodNames = new HashSet();
-
- for(int i = 0; i < directInterfaces.length; i++) {
- Class next = directInterfaces[i];
- Method[] methods = next.getMethods();
-
- // Comparison is based on method names only. First collect
- // all methods from current interface, eliminating duplicate
- // names.
- currentMethodNames.clear();
- for(int m = 0; m < methods.length; m++) {
- currentMethodNames.add(methods[m].getName());
- }
-
- // Now check each method against list of all unique method
- // names processed so far.
- for(Iterator iter=currentMethodNames.iterator(); iter.hasNext();) {
- String methodName = (String) iter.next();
- if( allMethodNames.contains(methodName) ) {
- String msg = "Class " + c + " inherits method " +
- methodName + " from multiple direct interfaces.";
- throw new IDLTypeException(msg);
- } else {
- allMethodNames.add(methodName);
- }
- }
- }
-
- return;
- }
-
- /**
- * Implements 1.2.3 #6
- */
- private void validateConstants(final Class c)
- throws IDLTypeException {
-
- Field[] fields = null;
-
- try {
- fields = (Field[])
- java.security.AccessController.doPrivileged
- (new java.security.PrivilegedExceptionAction() {
- public java.lang.Object run() throws Exception {
- return c.getFields();
- }
- });
- } catch(java.security.PrivilegedActionException pae) {
- IDLTypeException ite = new IDLTypeException();
- ite.initCause(pae);
- throw ite;
- }
-
- for(int i = 0; i < fields.length; i++) {
- Field next = fields[i];
- Class fieldType = next.getType();
- if( (fieldType != java.lang.String.class) &&
- !isPrimitive(fieldType) ) {
- String msg = "Constant field '" + next.getName() +
- "' in class '" + next.getDeclaringClass().getName() +
- "' has invalid type' " + next.getType() + "'. Constants" +
- " in RMI/IIOP interfaces can only have primitive" +
- " types and java.lang.String types.";
- throw new IDLTypeException(msg);
- }
- }
-
-
- return;
- }
-
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/protocol/oldlocal/LocalClientRequestImpl.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.corba.se.impl.iiop;
-
-import com.sun.corba.se.impl.protocol.Request;
-import com.sun.corba.se.impl.core.ClientRequest;
-import com.sun.corba.se.impl.core.ServiceContext;
-import com.sun.corba.se.impl.core.ServiceContexts;
-import com.sun.corba.se.impl.core.ClientResponse;
-import com.sun.corba.se.impl.core.ServerRequest;
-import com.sun.corba.se.impl.core.ServerResponse;
-import com.sun.corba.se.impl.corba.IOR;
-import com.sun.corba.se.impl.corba.GIOPVersion;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.RequestMessage;
-import com.sun.corba.se.impl.orbutil.ORBConstants;
-import com.sun.corba.se.impl.core.ORBVersion;
-import com.sun.corba.se.impl.core.ORB;
-import com.sun.corba.se.impl.orbutil.ORBUtility;
-import com.sun.corba.se.impl.ior.ObjectKeyFactory ;
-import com.sun.corba.se.impl.ior.ObjectKey ;
-import com.sun.corba.se.impl.ior.ObjectKeyTemplate ;
-import com.sun.corba.se.impl.ior.IIOPProfile;
-
-public class LocalClientRequestImpl extends IIOPOutputStream
- implements ClientRequest
-{
- public LocalClientRequestImpl( GIOPVersion gv,
- ORB orb, IOR ior, short addrDisposition,
- String operationName, boolean oneway, ServiceContexts svc,
- int requestId, byte streamFormatVersion)
- {
- super(gv,
- orb,
- null,
- BufferManagerFactory.newBufferManagerWrite(BufferManagerFactory.GROW),
- streamFormatVersion);
-
- this.isOneway = oneway;
- boolean responseExpected = !isOneway;
-
- IIOPProfile iop = ior.getProfile();
- ObjectKey okey = iop.getObjectKey();
- ObjectKeyTemplate oktemp = okey.getTemplate() ;
- ORBVersion version = oktemp.getORBVersion() ;
- orb.setORBVersion( version ) ;
-
- this.request = MessageBase.createRequest(orb, gv, requestId,
- responseExpected, ior, addrDisposition, operationName, svc, null);
- setMessage(request);
- request.write(this);
-
- // mark beginning of msg body for possible later use
- bodyBegin = getSize();
- }
-
- public int getRequestId() {
- return request.getRequestId();
- }
-
- public boolean isOneWay() {
- return isOneway;
- }
-
- public ServiceContexts getServiceContexts() {
- return request.getServiceContexts();
- }
-
- public String getOperationName() {
- return request.getOperation();
- }
-
- public ObjectKey getObjectKey() {
- return request.getObjectKey();
- }
-
- public ServerRequest getServerRequest()
- {
- // Set the size of the marshalled data in the message header.
- getMessage().setSize( getByteBuffer(), getSize() ) ;
-
- // Construct a new ServerRequest out of the buffer in this ClientRequest
- LocalServerRequestImpl serverRequest = new LocalServerRequestImpl(
- (ORB)orb(), toByteArray(), request ) ;
-
- // Skip over all of the GIOP header information. This positions
- // the offset in the buffer so that the skeleton can correctly read
- // the marshalled arguments.
- serverRequest.setIndex( bodyBegin ) ;
-
- return serverRequest ;
- }
-
- public ClientResponse invoke()
- {
- ORB myORB = (ORB)orb() ;
-
- ServerResponse serverResponse = myORB.process( getServerRequest() ) ;
-
- LocalServerResponseImpl lsr = (LocalServerResponseImpl)serverResponse ;
-
- return lsr.getClientResponse() ;
- }
-
- /**
- * Check to see if the request is local.
- */
- public boolean isLocal(){
- return true;
- }
-
- private RequestMessage request;
- private int bodyBegin;
- private boolean isOneway;
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/protocol/oldlocal/LocalClientResponseImpl.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.corba.se.impl.iiop;
-
-import java.io.IOException;
-
-import org.omg.CORBA.SystemException;
-import org.omg.CORBA.CompletionStatus;
-
-import com.sun.corba.se.impl.core.Response;
-import com.sun.corba.se.impl.core.ClientResponse;
-import com.sun.corba.se.impl.corba.IOR;
-import com.sun.corba.se.impl.core.ORB;
-import com.sun.corba.se.impl.core.ServiceContext;
-import com.sun.corba.se.impl.core.ServiceContexts;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
-import com.sun.corba.se.impl.orbutil.MinorCodes;
-
-class LocalClientResponseImpl extends IIOPInputStream implements ClientResponse
-{
- LocalClientResponseImpl(ORB orb, byte[] buf, ReplyMessage header)
- {
- super(orb, buf, header.getSize(), header.isLittleEndian(), header, null);
-
- this.reply = header;
-
- // NOTE (Ram J) (06/02/2000) if we set result.setIndex(bodyBegin)
- // in LocalServerResponse.getClientResponse(), then we do not need
- // to read the headers (done below) anymore.
- // This will be an optimisation which is can be done to speed up the
- // local invocation by avoiding reading the headers in the local cases.
-
- // BUGFIX(Ram Jeyaraman) This has been moved from
- // LocalServerResponse.getClientResponse()
- // Skip over all of the GIOP header information. This positions
- // the offset in the buffer so that the skeleton can correctly read
- // the marshalled arguments.
- this.setIndex(Message.GIOPMessageHeaderLength);
-
- // BUGFIX(Ram Jeyaraman) For local invocations, the reply mesg fields
- // needs to be set, by reading the response buffer contents
- // to correctly set the exception type and other info.
- this.reply.read(this);
- }
-
- LocalClientResponseImpl(SystemException ex)
- {
- this.systemException = ex;
- }
-
- public boolean isSystemException() {
- if ( reply != null )
- return reply.getReplyStatus() == ReplyMessage.SYSTEM_EXCEPTION;
- else
- return (systemException != null);
- }
-
- public boolean isUserException() {
- if ( reply != null )
- return reply.getReplyStatus() == ReplyMessage.USER_EXCEPTION;
- else
- return false;
- }
-
- public boolean isLocationForward() {
- if ( reply != null ) {
- return ( (reply.getReplyStatus() == ReplyMessage.LOCATION_FORWARD) ||
- (reply.getReplyStatus() == ReplyMessage.LOCATION_FORWARD_PERM) );
- //return reply.getReplyStatus() == ReplyMessage.LOCATION_FORWARD;
- } else {
- return false;
- }
- }
-
- public boolean isDifferentAddrDispositionRequested() {
- if (reply != null) {
- return reply.getReplyStatus() == ReplyMessage.NEEDS_ADDRESSING_MODE;
- }
-
- return false;
- }
-
- public short getAddrDisposition() {
- if (reply != null) {
- return reply.getAddrDisposition();
- }
-
- throw new org.omg.CORBA.INTERNAL(
- "Null reply in getAddrDisposition",
- MinorCodes.NULL_REPLY_IN_GET_ADDR_DISPOSITION,
- CompletionStatus.COMPLETED_MAYBE);
- }
-
- public IOR getForwardedIOR() {
- if ( reply != null )
- return reply.getIOR();
- else
- return null;
- }
-
- public int getRequestId() {
- if ( reply != null )
- return reply.getRequestId();
- else
- throw new org.omg.CORBA.INTERNAL("Error in getRequestId");
- }
-
- public ServiceContexts getServiceContexts() {
- if ( reply != null )
- return reply.getServiceContexts();
- else
- return null;
- }
-
- public SystemException getSystemException() {
- if ( reply != null )
- return reply.getSystemException();
- else
- return systemException;
- }
-
- public java.lang.String peekUserExceptionId() {
- mark(Integer.MAX_VALUE);
- String result = read_string();
- reset();
- return result;
- }
-
- /**
- * Check to see if the response is local.
- */
- public boolean isLocal(){
- return true;
- }
-
- private ReplyMessage reply;
- private SystemException systemException;
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/protocol/oldlocal/LocalServerRequestImpl.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.corba.se.impl.iiop;
-
-import org.omg.CORBA.SystemException;
-
-import com.sun.corba.se.impl.core.ServerRequest;
-import com.sun.corba.se.impl.core.ServiceContext;
-import com.sun.corba.se.impl.core.DuplicateServiceContext;
-import com.sun.corba.se.impl.core.UEInfoServiceContext;
-import com.sun.corba.se.impl.core.ServiceContexts;
-import com.sun.corba.se.impl.core.ServerResponse;
-import com.sun.corba.se.impl.corba.IOR;
-import com.sun.corba.se.impl.core.ORB;
-import com.sun.corba.se.impl.orbutil.ORBUtility; //d11638
-import org.omg.CORBA.portable.UnknownException;
-import org.omg.CORBA.UNKNOWN;
-import org.omg.CORBA.CompletionStatus;
-import com.sun.corba.se.impl.ior.ObjectKey;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.RequestMessage;
-
-class LocalServerRequestImpl extends IIOPInputStream implements ServerRequest {
- org.omg.CORBA.portable.OutputStream replyStream;
- org.omg.CORBA.portable.OutputStream exceptionReplyStream;
-
- LocalServerRequestImpl(ORB orb, byte[] buf, RequestMessage header)
- {
- super(orb, buf, header.getSize(), header.isLittleEndian(), header, null );
-
- this.request = header;
- }
-
- public int getRequestId() {
- return request.getRequestId();
- }
-
- public boolean isOneWay() {
- return !request.isResponseExpected();
- }
-
- public ServiceContexts getServiceContexts() {
- return request.getServiceContexts();
- }
-
- public String getOperationName() {
- return request.getOperation();
- }
-
- public ObjectKey getObjectKey() {
- return request.getObjectKey();
- }
-
- public ServerResponse createResponse(ServiceContexts svc)
- {
- return new LocalServerResponseImpl(this, svc);
- }
-
- public org.omg.CORBA.portable.OutputStream createReply() {
- if (replyStream == null) {
- replyStream = (org.omg.CORBA.portable.OutputStream)
- createResponse(null);
- }
- return replyStream;
- }
-
- public org.omg.CORBA.portable.OutputStream createExceptionReply() {
- if (exceptionReplyStream == null) {
- exceptionReplyStream = (org.omg.CORBA.portable.OutputStream)
- createUserExceptionResponse(null);
- }
- return exceptionReplyStream;
- }
-
- public ServerResponse createUserExceptionResponse(
- ServiceContexts svc)
- {
- return new LocalServerResponseImpl(this, svc, true);
- }
-
- public ServerResponse createUnknownExceptionResponse(
- UnknownException ex) {
- ServiceContexts contexts = null;
- SystemException sys = new UNKNOWN( 0,
- CompletionStatus.COMPLETED_MAYBE);
-
- try {
- contexts = new ServiceContexts( (ORB)orb() );
- UEInfoServiceContext uei = new UEInfoServiceContext(sys);
- contexts.put(uei) ;
- } catch (DuplicateServiceContext d) {
- // can't happen
- }
-
- return createSystemExceptionResponse(sys,contexts);
- }
-
- public ServerResponse createSystemExceptionResponse(
- SystemException ex, ServiceContexts svc) {
-
- // Only do this if interceptors have been initialized on this request
- // and have not completed their lifecycle (otherwise the info stack
- // may be empty or have a different request's entry on top).
- if (executePIInResponseConstructor()) {
- // Inform Portable Interceptors of the SystemException. This is
- // required to be done here because the ending interception point
- // is called in the ServerResponseImpl constructor called below
- // but we do not currently write the SystemException into the
- // response until after the ending point is called.
- ORB orb = (ORB)orb();
- orb.getPIHandler().setServerPIInfo( ex );
- }
-
- if (orb() != null && ((ORB)orb()).subcontractDebugFlag && ex != null)
- ORBUtility.dprint(this, "Sending SystemException:", ex);
-
- LocalServerResponseImpl response =
- new LocalServerResponseImpl(this, svc, false);
- ORBUtility.writeSystemException(ex, response);
- return response;
- }
-
- public ServerResponse createLocationForward(
- IOR ior, ServiceContexts svc) {
- ReplyMessage reply = MessageBase.createReply( (ORB)orb(),
- request.getGIOPVersion(), request.getRequestId(),
- ReplyMessage.LOCATION_FORWARD, svc, ior);
- LocalServerResponseImpl response =
- new LocalServerResponseImpl(this, reply, ior);
-
- return response;
- }
-
- private RequestMessage request;
-
- /**
- * Check to see if the request is local.
- */
- public boolean isLocal(){
- return true;
- }
-
- private boolean _executeReturnServantInResponseConstructor = false;
-
- public boolean executeReturnServantInResponseConstructor()
- {
- return _executeReturnServantInResponseConstructor;
- }
-
- public void setExecuteReturnServantInResponseConstructor(boolean b)
- {
- _executeReturnServantInResponseConstructor = b;
- }
-
-
- private boolean _executeRemoveThreadInfoInResponseConstructor = false;
-
- public boolean executeRemoveThreadInfoInResponseConstructor()
- {
- return _executeRemoveThreadInfoInResponseConstructor;
- }
-
- public void setExecuteRemoveThreadInfoInResponseConstructor(boolean b)
- {
- _executeRemoveThreadInfoInResponseConstructor = b;
- }
-
-
- private boolean _executePIInResponseConstructor = false;
-
- public boolean executePIInResponseConstructor() {
- return _executePIInResponseConstructor;
- }
-
- public void setExecutePIInResponseConstructor( boolean b ) {
- _executePIInResponseConstructor = b;
- }
-
- // We know that we're talking to the same ValueHandler, so
- // use the maximum version it supports.
- public byte getStreamFormatVersionForReply() {
- return ORBUtility.getMaxStreamFormatVersion();
- }
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/protocol/oldlocal/LocalServerResponseImpl.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.corba.se.impl.iiop;
-
-import org.omg.CORBA.SystemException;
-
-import com.sun.corba.se.impl.core.ServerResponse;
-import com.sun.corba.se.impl.core.ORB;
-import com.sun.corba.se.impl.corba.IOR;
-import com.sun.corba.se.impl.core.ServiceContext;
-import com.sun.corba.se.impl.core.ServiceContexts;
-import com.sun.corba.se.impl.core.ClientResponse;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.ReplyMessage;
-
-class LocalServerResponseImpl
- extends IIOPOutputStream
- implements ServerResponse
-{
- LocalServerResponseImpl(LocalServerRequestImpl request, ServiceContexts svc)
- {
- this(request,
- MessageBase.createReply(
- (ORB)request.orb(),
- request.getGIOPVersion(),
- request.getRequestId(), ReplyMessage.NO_EXCEPTION,
- svc, null),
- null);
- }
-
- LocalServerResponseImpl(LocalServerRequestImpl request, ServiceContexts svc,
- boolean user)
- {
- this(request,
- MessageBase.createReply(
- (ORB)request.orb(),
- request.getGIOPVersion(), request.getRequestId(),
- user ? ReplyMessage.USER_EXCEPTION :
- ReplyMessage.SYSTEM_EXCEPTION,
- svc, null),
- null);
- }
-
- LocalServerResponseImpl( LocalServerRequestImpl request, ReplyMessage reply,
- IOR ior)
- {
- super(request.getGIOPVersion(),
- (ORB)request.orb(),
- null,
- BufferManagerFactory.newBufferManagerWrite(BufferManagerFactory.GROW),
- request.getStreamFormatVersionForReply());
-
- setMessage(reply);
-
- ORB orb = (ORB)request.orb();
-
- ServerResponseImpl.runServantPostInvoke(orb, request);
-
- if( request.executePIInResponseConstructor() ) {
- // Invoke server request ending interception points (send_*):
- // Note: this may end up with a SystemException or an internal
- // Runtime ForwardRequest.
- orb.getPIHandler().invokeServerPIEndingPoint( reply );
-
- // Note this will be executed even if a ForwardRequest or
- // SystemException is thrown by a Portable Interceptors ending
- // point since we end up in this constructor again anyway.
- orb.getPIHandler().cleanupServerPIRequest();
-
- // See (Local)ServerRequestImpl.createSystemExceptionResponse
- // for why this is necesary.
- request.setExecutePIInResponseConstructor(false);
- }
-
- // Once you get here then the final reply is available (i.e.,
- // postinvoke and interceptors have completed.
- if (request.executeRemoveThreadInfoInResponseConstructor()) {
- ServerResponseImpl.removeThreadInfo(orb, request);
- }
-
- reply.write(this);
- if (reply.getIOR() != null)
- reply.getIOR().write(this);
-
- this.reply = reply;
- this.ior = reply.getIOR();
- }
-
- public boolean isSystemException() {
- if (reply != null)
- return reply.getReplyStatus() == ReplyMessage.SYSTEM_EXCEPTION;
- return false;
- }
-
- public boolean isUserException() {
- if (reply != null)
- return reply.getReplyStatus() == ReplyMessage.USER_EXCEPTION;
- return false;
- }
-
- public boolean isLocationForward() {
- if (ior != null)
- return true;
- return false;
- }
-
- public IOR getForwardedIOR() {
- return ior;
- }
-
- public int getRequestId() {
- if (reply != null)
- return reply.getRequestId();
- return -1;
- }
-
- public ServiceContexts getServiceContexts() {
- if (reply != null)
- return reply.getServiceContexts();
- return null;
- }
-
- public SystemException getSystemException() {
- if (reply != null)
- return reply.getSystemException();
- return null;
- }
-
- public ReplyMessage getReply()
- {
- return reply ;
- }
-
- public ClientResponse getClientResponse()
- {
- // set the size of the marshalled data in the message header
- getMessage().setSize(getByteBuffer(), getSize());
-
- // Construct a new ClientResponse out of the buffer in this ClientRequest
- LocalClientResponseImpl result =
- new LocalClientResponseImpl( (ORB)orb(), toByteArray(), reply);
-
- // NOTE (Ram J) (06/02/2000) if we set result.setIndex(bodyBegin) here
- // then the LocalClientResponse does not need to read the headers anymore.
- // This will be an optimisation which is can be done to speed up the
- // local invocation by avoiding reading the headers in the local cases.
-
- // BUGFIX(Ram Jeyaraman) result.setOffset is now done in
- // LocalClientResponseImpl constructor.
- /*
- // Skip over all of the GIOP header information. This positions
- // the offset in the buffer so that the skeleton can correctly read
- // the marshalled arguments.
- result.setOffset( bodyBegin ) ;
- */
-
- return result ;
- }
-
- /**
- * Check to see if the response is local.
- */
- public boolean isLocal(){
- return true;
- }
-
- private ReplyMessage reply;
- private IOR ior; // forwarded IOR
-}
--- ./corba/src/share/classes/com/sun/corba/se/impl/transport/BufferConnectionImpl.sjava Tue Mar 18 12:29:47 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,710 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.corba.se.impl.transport;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.ByteBuffer;
-import java.nio.channels.SelectableChannel;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.SocketChannel;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.omg.CORBA.COMM_FAILURE;
-import org.omg.CORBA.CompletionStatus;
-import org.omg.CORBA.DATA_CONVERSION;
-import org.omg.CORBA.INTERNAL;
-import org.omg.CORBA.MARSHAL;
-import org.omg.CORBA.OBJECT_NOT_EXIST;
-import org.omg.CORBA.SystemException;
-
-import com.sun.org.omg.SendingContext.CodeBase;
-
-import com.sun.corba.se.pept.broker.Broker;
-import com.sun.corba.se.pept.encoding.InputObject;
-import com.sun.corba.se.pept.encoding.OutputObject;
-import com.sun.corba.se.pept.protocol.MessageMediator;
-import com.sun.corba.se.pept.transport.Acceptor;
-import com.sun.corba.se.pept.transport.Connection;
-import com.sun.corba.se.pept.transport.ConnectionCache;
-import com.sun.corba.se.pept.transport.ContactInfo;
-import com.sun.corba.se.pept.transport.EventHandler;
-import com.sun.corba.se.pept.transport.InboundConnectionCache;
-import com.sun.corba.se.pept.transport.OutboundConnectionCache;
-import com.sun.corba.se.pept.transport.ResponseWaitingRoom;
-import com.sun.corba.se.pept.transport.Selector;
-
-import com.sun.corba.se.spi.ior.IOR;
-import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
-import com.sun.corba.se.spi.logging.CORBALogDomains;
-import com.sun.corba.se.spi.orb.ORB ;
-import com.sun.corba.se.spi.orbutil.threadpool.Work;
-import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
-import com.sun.corba.se.spi.transport.CorbaContactInfo;
-import com.sun.corba.se.spi.transport.CorbaConnection;
-import com.sun.corba.se.spi.transport.CorbaResponseWaitingRoom;
-
-import com.sun.corba.se.impl.encoding.CachedCodeBase;
-import com.sun.corba.se.impl.encoding.CDRInputStream_1_0;
-import com.sun.corba.se.impl.encoding.CDROutputObject;
-import com.sun.corba.se.impl.encoding.CDROutputStream_1_0;
-import com.sun.corba.se.impl.encoding.CodeSetComponentInfo;
-import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
-import com.sun.corba.se.impl.logging.ORBUtilSystemException;
-import com.sun.corba.se.impl.orbutil.ORBConstants;
-import com.sun.corba.se.impl.orbutil.ORBUtility;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
-import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
-import com.sun.corba.se.impl.transport.CorbaResponseWaitingRoomImpl;
-
-/**
- * @author Ken Cavanaugh
- */
-public class BufferConnectionImpl
- extends
- EventHandlerBase
- implements
- CorbaConnection,
- Work
-{
- //
- // New transport.
- //
-
- protected long enqueueTime;
-
- public SocketChannel getSocketChannel()
- {
- return null;
- }
-
- // REVISIT:
- // protected for test: genericRPCMSGFramework.IIOPConnection constructor.
-
- //
- // From iiop.Connection.java
- //
-
- protected long timeStamp = 0;
- protected boolean isServer = false;
-
- // Start at some value other than zero since this is a magic
- // value in some protocols.
- protected int requestId = 5;
- protected CorbaResponseWaitingRoom responseWaitingRoom;
- protected int state;
- protected java.lang.Object stateEvent = new java.lang.Object();
- protected java.lang.Object writeEvent = new java.lang.Object();
- protected boolean writeLocked;
- protected int serverRequestCount = 0;
-
- // Server request map: used on the server side of Connection
- // Maps request ID to IIOPInputStream.
- Map serverRequestMap = new HashMap() ;
-
- // This is a flag associated per connection telling us if the
- // initial set of sending contexts were sent to the receiver
- // already...
- protected boolean postInitialContexts = false;
-
- // Remote reference to CodeBase server (supplies
- // FullValueDescription, among other things)
- protected IOR codeBaseServerIOR;
-
- // CodeBase cache for this connection. This will cache remote operations,
- // handle connecting, and ensure we don't do any remote operations until
- // necessary.
- protected CachedCodeBase cachedCodeBase = new CachedCodeBase(this);
-
- protected ORBUtilSystemException wrapper ;
-
- List buffers ;
-
- public BufferConnectionImpl(ORB orb, byte[][] data )
- {
- this.orb = orb;
- wrapper = ORBUtilSystemException.get( orb,
- CORBALogDomains.RPC_TRANSPORT ) ;
- buffers = new ArrayList() ;
- }
-
- ////////////////////////////////////////////////////
- //
- // framework.transport.Connection
- //
-
- public boolean shouldRegisterReadEvent()
- {
- return false;
- }
-
- public boolean shouldRegisterServerReadEvent()
- {
- return false;
- }
-
- public boolean read()
- {
- return true ;
- }
-
- protected CorbaMessageMediator readBits()
- {
- return null ;
- }
-
- protected boolean dispatch(CorbaMessageMediator messageMediator)
- {
- }
-
- public boolean shouldUseDirectByteBuffers()
- {
- return false ;
- }
-
- // Only called from readGIOPMessage with (12, 0, 12) as arguments
- // size is size of buffer to create
- // offset is offset from start of message in buffer
- // length is length to read
- public ByteBuffer read(int size, int offset, int length)
- throws IOException
- {
- byte[] buf = new byte[size];
- readFully( buf, offset, length);
- ByteBuffer byteBuffer = ByteBuffer.wrap(buf);
- byteBuffer.limit(size);
- return byteBuffer;
- }
-
- // Only called as read( buf, 12, msgsize-12 ) in readGIOPMessage
- // We can ignore the byteBuffer parameter
- // offset is the starting position to place data in the result
- // length is the length of the data to read
- public ByteBuffer read(ByteBuffer byteBuffer, int offset, int length)
- throws IOException
- {
- int size = offset + length;
- byte[] buf = new byte[size];
- readFully(buf, offset, length);
- return ByteBuffer.wrap(buf);
- }
-
- // Read size bytes from buffer list and place the data
- // starting at offset in buf.
- public void readFully(byte[] buf, int offset, int size)
- throws IOException
- {
- int remaining = size ;
- int position = offset ;
- while (remaining > 0) {
- ByteBuffer buff = (ByteBuffer)buffers.get(0) ;
- int dataSize = buff.remaining() ;
- int xferSize = dataSize ;
- if (dataSize >= remaining) :
- xferSize = remaining ;
- buffers.remove(0) ;
- }
-
- buff.get( buf, offset, xferSize ) ;
-
- offset += xferSize ;
- remaining -= xferSize ;
- }
- }
-
- public void write(ByteBuffer byteBuffer)
- throws IOException
- {
- buffers.add( byteBuffer ) ;
- }
-
- /**
- * Note:it is possible for this to be called more than once
- */
- public synchronized void close()
- {
- }
-
- public Acceptor getAcceptor()
- {
- return null;
- }
-
- public ContactInfo getContactInfo()
- {
- return null;
- }
-
- public EventHandler getEventHandler()
- {
- return this;
- }
-
- public OutputObject createOutputObject(MessageMediator messageMediator)
- {
- // REVISIT - remove this method from Connection and all it subclasses.
- throw new RuntimeException("*****SocketOrChannelConnectionImpl.createOutputObject - should not be called.");
- }
-
- // This is used by the GIOPOutputObject in order to
- // throw the correct error when handling code sets.
- // Can we determine if we are on the server side by
- // other means? XREVISIT
- public boolean isServer()
- {
- return isServer;
- }
-
- public boolean isBusy()
- {
- return false ;
- }
-
- public long getTimeStamp()
- {
- return timeStamp;
- }
-
- public void setTimeStamp(long time)
- {
- timeStamp = time;
- }
-
- public void setState(String stateString)
- {
- synchronized (stateEvent) {
- if (stateString.equals("ESTABLISHED")) {
- state = ESTABLISHED;
- stateEvent.notifyAll();
- } else {
- // REVISIT: ASSERT
- }
- }
- }
-
- public void writeLock()
- {
- }
-
- public void writeUnlock()
- {
- }
-
- public void sendWithoutLock(OutputObject outputObject)
- {
- }
-
- public void registerWaiter(MessageMediator messageMediator)
- {
- }
-
- public void unregisterWaiter(MessageMediator messageMediator)
- {
- }
-
- public InputObject waitForResponse(MessageMediator messageMediator)
- {
- return null ;
- }
-
- public void setConnectionCache(ConnectionCache connectionCache)
- {
- }
-
- public ConnectionCache getConnectionCache()
- {
- return null;
- }
-
- ////////////////////////////////////////////////////
- //
- // EventHandler methods
- //
-
- public SelectableChannel getChannel()
- {
- return null;
- }
-
- public int getInterestOps()
- {
- return null;
- }
-
- // public Acceptor getAcceptor() - already defined above.
-
- public Connection getConnection()
- {
- return this;
- }
-
- ////////////////////////////////////////////////////
- //
- // Work methods.
- //
-
- public String getName()
- {
- return this.toString();
- }
-
- public void doWork()
- {
- }
-
- public void setEnqueueTime(long timeInMillis)
- {
- enqueueTime = timeInMillis;
- }
-
- public long getEnqueueTime()
- {
- return enqueueTime;
- }
-
- ////////////////////////////////////////////////////
- //
- // spi.transport.CorbaConnection.
- //
-
- public ResponseWaitingRoom getResponseWaitingRoom()
- {
- return null ;
- }
-
- // REVISIT - inteface defines isServer but already defined in
- // higher interface.
-
-
- public void serverRequestMapPut(int requestId,
- CorbaMessageMediator messageMediator)
- {
- serverRequestMap.put(new Integer(requestId), messageMediator);
- }
-
- public CorbaMessageMediator serverRequestMapGet(int requestId)
- {
- return (CorbaMessageMediator)
- serverRequestMap.get(new Integer(requestId));
- }
-
- public void serverRequestMapRemove(int requestId)
- {
- serverRequestMap.remove(new Integer(requestId));
- }
-
-
- // REVISIT: this is also defined in:
- // com.sun.corba.se.spi.legacy.connection.Connection
- public java.net.Socket getSocket()
- {
- return null;
- }
-
- /** It is possible for a Close Connection to have been
- ** sent here, but we will not check for this. A "lazy"
- ** Exception will be thrown in the Worker thread after the
- ** incoming request has been processed even though the connection
- ** is closed before the request is processed. This is o.k because
- ** it is a boundary condition. To prevent it we would have to add
- ** more locks which would reduce performance in the normal case.
- **/
- public synchronized void serverRequestProcessingBegins()
- {
- serverRequestCount++;
- }
-
- public synchronized void serverRequestProcessingEnds()
- {
- serverRequestCount--;
- }
-
- //
- //
- //
-
- public synchronized int getNextRequestId()
- {
- return requestId++;
- }
-
- // Negotiated code sets for char and wchar data
- protected CodeSetComponentInfo.CodeSetContext codeSetContext = null;
-
- public ORB getBroker()
- {
- return orb;
- }
-
- public CodeSetComponentInfo.CodeSetContext getCodeSetContext()
- {
- // Needs to be synchronized for the following case when the client
- // doesn't send the code set context twice, and we have two threads
- // in ServerRequestDispatcher processCodeSetContext.
- //
- // Thread A checks to see if there is a context, there is none, so
- // it calls setCodeSetContext, getting the synch lock.
- // Thread B checks to see if there is a context. If we didn't synch,
- // it might decide to outlaw wchar/wstring.
- if (codeSetContext == null) {
- synchronized(this) {
- return codeSetContext;
- }
- }
-
- return codeSetContext;
- }
-
- public synchronized void setCodeSetContext(CodeSetComponentInfo.CodeSetContext csc) {
- // Double check whether or not we need to do this
- if (codeSetContext == null) {
-
- if (OSFCodeSetRegistry.lookupEntry(csc.getCharCodeSet()) == null ||
- OSFCodeSetRegistry.lookupEntry(csc.getWCharCodeSet()) == null) {
- // If the client says it's negotiated a code set that
- // isn't a fallback and we never said we support, then
- // it has a bug.
- throw wrapper.badCodesetsFromClient() ;
- }
-
- codeSetContext = csc;
- }
- }
-
- //
- // from iiop.IIOPConnection.java
- //
-
- // Map request ID to an InputObject.
- // This is so the client thread can start unmarshaling
- // the reply and remove it from the out_calls map while the
- // ReaderThread can still obtain the input stream to give
- // new fragments. Only the ReaderThread touches the clientReplyMap,
- // so it doesn't incur synchronization overhead.
-
- public MessageMediator clientRequestMapGet(int requestId)
- {
- return null ;
- }
-
- protected MessageMediator clientReply_1_1;
-
- public void clientReply_1_1_Put(MessageMediator x)
- {
- clientReply_1_1 = x;
- }
-
- public MessageMediator clientReply_1_1_Get()
- {
- return clientReply_1_1;
- }
-
- public void clientReply_1_1_Remove()
- {
- clientReply_1_1 = null;
- }
-
- protected MessageMediator serverRequest_1_1;
-
- public void serverRequest_1_1_Put(MessageMediator x)
- {
- serverRequest_1_1 = x;
- }
-
- public MessageMediator serverRequest_1_1_Get()
- {
- return serverRequest_1_1;
- }
-
- public void serverRequest_1_1_Remove()
- {
- serverRequest_1_1 = null;
- }
-
- protected String getStateString( int state )
- {
- synchronized ( stateEvent ){
- switch (state) {
- case OPENING : return "OPENING" ;
- case ESTABLISHED : return "ESTABLISHED" ;
- case CLOSE_SENT : return "CLOSE_SENT" ;
- case CLOSE_RECVD : return "CLOSE_RECVD" ;
- case ABORT : return "ABORT" ;
- default : return "???" ;
- }
- }
- }
-
- public synchronized boolean isPostInitialContexts() {
- return postInitialContexts;
- }
-
- // Can never be unset...
- public synchronized void setPostInitialContexts(){
- postInitialContexts = true;
- }
-
- /**
- * Wake up the outstanding requests on the connection, and hand them
- * COMM_FAILURE exception with a given minor code.
- *
- * Also, delete connection from connection table and
- * stop the reader thread.
-
- * Note that this should only ever be called by the Reader thread for
- * this connection.
- *
- * @param minor_code The minor code for the COMM_FAILURE major code.
- * @param die Kill the reader thread (this thread) before exiting.
- */
- public void purgeCalls(SystemException systemException,
- boolean die, boolean lockHeld)
- {
- }
-
- /*************************************************************************
- * The following methods are for dealing with Connection cleaning for
- * better scalability of servers in high network load conditions.
- **************************************************************************/
-
- public void sendCloseConnection(GIOPVersion giopVersion)
- throws IOException
- {
- Message msg = MessageBase.createCloseConnection(giopVersion);
- sendHelper(giopVersion, msg);
- }
-
- public void sendMessageError(GIOPVersion giopVersion)
- throws IOException
- {
- Message msg = MessageBase.createMessageError(giopVersion);
- sendHelper(giopVersion, msg);
- }
-
- /**
- * Send a CancelRequest message. This does not lock the connection, so the
- * caller needs to ensure this method is called appropriately.
- * @exception IOException - could be due to abortive connection closure.
- */
- public void sendCancelRequest(GIOPVersion giopVersion, int requestId)
- throws IOException
- {
-
- Message msg = MessageBase.createCancelRequest(giopVersion, requestId);
- sendHelper(giopVersion, msg);
- }
-
- protected void sendHelper(GIOPVersion giopVersion, Message msg)
- throws IOException
- {
- // REVISIT: See comments in CDROutputObject constructor.
- CDROutputObject outputObject =
- new CDROutputObject((ORB)orb, null, giopVersion, this, msg,
- ORBConstants.STREAM_FORMAT_VERSION_1);
- msg.write(outputObject);
-
- outputObject.writeTo(this);
- }
-
- public void sendCancelRequestWithLock(GIOPVersion giopVersion,
- int requestId)
- throws IOException
- {
- writeLock();
- try {
- sendCancelRequest(giopVersion, requestId);
- } finally {
- writeUnlock();
- }
- }
-
- // Begin Code Base methods ---------------------------------------
- //
- // Set this connection's code base IOR. The IOR comes from the
- // SendingContext. This is an optional service context, but all
- // JavaSoft ORBs send it.
- //
- // The set and get methods don't need to be synchronized since the
- // first possible get would occur during reading a valuetype, and
- // that would be after the set.
-
- // Sets this connection's code base IOR. This is done after
- // getting the IOR out of the SendingContext service context.
- // Our ORBs always send this, but it's optional in CORBA.
-
- public final void setCodeBaseIOR(IOR ior) {
- codeBaseServerIOR = ior;
- }
-
- public final IOR getCodeBaseIOR() {
- return codeBaseServerIOR;
- }
-
- // Get a CodeBase stub to use in unmarshaling. The CachedCodeBase
- // won't connect to the remote codebase unless it's necessary.
- public final CodeBase getCodeBase() {
- return cachedCodeBase;
- }
-
- // End Code Base methods -----------------------------------------
-
- // Can be overridden in subclass for different options.
- protected void setSocketOptions(Socket socket)
- {
- }
-
- public String toString()
- {
- synchronized ( stateEvent ){
- return
- "BufferConnectionImpl[" + " "
- + getStateString( state ) + " "
- + shouldUseSelectThreadToWait() + " "
- + shouldUseWorkerThreadForEvent()
- + "]" ;
- }
- }
-
- // Must be public - used in encoding.
- public void dprint(String msg)
- {
- ORBUtility.dprint("SocketOrChannelConnectionImpl", msg);
- }
-
- protected void dprint(String msg, Throwable t)
- {
- dprint(msg);
- t.printStackTrace(System.out);
- }
-}
-
-// End of file.
--- ./corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultSocketFactoryImpl.java Tue Mar 18 12:29:47 2014 -0700
+++ ./corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultSocketFactoryImpl.java Wed May 07 19:25:52 2014 -0700
@@ -32,6 +32,7 @@
import java.net.ServerSocket;
import java.nio.channels.SocketChannel;
import java.nio.channels.ServerSocketChannel;
+import java.security.PrivilegedAction;
import com.sun.corba.se.pept.transport.Acceptor;
@@ -44,6 +45,22 @@
implements ORBSocketFactory
{
private ORB orb;
+ private static final boolean keepAlive;
+
+ static {
+ keepAlive = java.security.AccessController.doPrivileged(
+ new PrivilegedAction() {
+ @Override
+ public Boolean run () {
+ String value =
+ System.getProperty("com.sun.CORBA.transport.enableTcpKeepAlive");
+ if (value != null)
+ return new Boolean(!"false".equalsIgnoreCase(value));
+
+ return Boolean.FALSE;
+ }
+ });
+ }
public void setORB(ORB orb)
{
@@ -85,6 +102,9 @@
// Disable Nagle's algorithm (i.e., always send immediately).
socket.setTcpNoDelay(true);
+ if (keepAlive)
+ socket.setKeepAlive(true);
+
return socket;
}
@@ -95,6 +115,8 @@
{
// Disable Nagle's algorithm (i.e., always send immediately).
socket.setTcpNoDelay(true);
+ if (keepAlive)
+ socket.setKeepAlive(true);
}
}
--- ./hotspot/.hgtags Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/.hgtags Wed May 07 19:26:16 2014 -0700
@@ -626,3 +626,35 @@
49cada8e39b9215b9fd8b9183743f92625587cfc jdk7u55-b11
aadc864abd1ced3049bf59ce32786a07997ba190 jdk7u55-b12
b021fd817a0177b31d1e3d65127a27458e85801e jdk7u55-b13
+d27b468d5f3be3329ff1ff342f3347e6b2e0303b jdk7u55-b30
+dff9147a781672f20bb0577a94233264ea4a95d1 jdk7u55-b14
+8175599864880938d68d0a515fa561043d7d5fd0 jdk7u55-b31
+ae4adc1492d1c90a70bd2d139a939fc0c8329be9 jdk7u60-b00
+af1fc2868a2b919727bfbb0858449bd991bbee4a jdk7u40-b60
+cc83359f5e5eb46dd9176b0a272390b1a0a51fdc hs24.60-b01
+b7d44793cd267b22352c688b0185466741bb7a89 hs24.60-b02
+90cfd4ad3c9263886d876792d72cb24ac0e03a85 hs24.60-b03
+8fd0e931efa57d1579fb1bc8a68ba3924244b99e jdk7u60-b01
+99e96aaac8afc14ce6f9f3d92ef7004cf505b35d hs24.60-b04
+0025a2a965c8f21376278245c2493d8861386fba jdk7u60-b02
+fa59add77d1a8f601a695f137248462fdc68cc2f hs24.60-b05
+a59134ccb1b704b2cd05e157970d425af43e5437 hs24.60-b06
+2c971ed884cec0a9293ccff3def696da81823225 jdk7u60-b03
+1afbeb8cb558429156d432f35e7582716053a9cb hs24.60-b07
+05fe7a87d14908eb3f21a0d29fc72cee2f996b7f jdk7u60-b04
+f52b5452d424545e3b101d808e6d7da763d6f0f3 hs24.60-b08
+462db155547e9bdd7ba26bead42808deb0b10d44 jdk7u60-b05
+0cc4550bd9c57ba3be343bfbfcaf46b9060d5e7d jdk7u60-b06
+2d053c4fd767155b2ac5e3e0a60b08a1bcc73cab jdk7u60-b07
+a198787e7b9bc7b831ad210b67732cdb2be9e46e jdk7u60-b08
+22cae361773d14b467328e8f90cf893550d1d610 jdk7u60-b09
+6f74afd8577eb4b6a0e6f7b25cfef7d6f7d92e5f jdk7u60-b10
+a2ac67a2c1cc867a8d6b525ab1df17204186e636 jdk7u60-b11
+cae50351dcece6e5bf215eabf958c5d669ffff1f jdk7u60-b12
+5853131ba4b448c5d89a3f0aa501fdf07f3b473c jdk7u60-b13
+b226be2040f971855626f5b88cb41a7d5299fea0 jdk7u60-b14
+2871f345b7e5585e20dc7aa91035967fe774cfba jdk7u60-b15
+ec76bacbb5b90efc7988dee5345c656126b97561 jdk7u60-b16
+617a6338e0c4f7699eed5061d7e8f576c3ace029 jdk7u60-b18
+617a6338e0c4f7699eed5061d7e8f576c3ace029 jdk7u60-b17
+361493c7cdb5f75b28efc63389d6cebaaaa43a2c jdk7u60-b19
--- ./hotspot/agent/src/os/linux/ps_core.c Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/agent/src/os/linux/ps_core.c Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -700,29 +700,61 @@
// read segments of a shared object
static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) {
- int i = 0;
- ELF_PHDR* phbuf;
- ELF_PHDR* lib_php = NULL;
+ int i = 0;
+ ELF_PHDR* phbuf;
+ ELF_PHDR* lib_php = NULL;
- if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL)
- return false;
+ int page_size = sysconf(_SC_PAGE_SIZE);
- // we want to process only PT_LOAD segments that are not writable.
- // i.e., text segments. The read/write/exec (data) segments would
- // have been already added from core file segments.
- for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) {
- if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) {
- if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL)
- goto err;
+ if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) {
+ return false;
+ }
+
+ // we want to process only PT_LOAD segments that are not writable.
+ // i.e., text segments. The read/write/exec (data) segments would
+ // have been already added from core file segments.
+ for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) {
+ if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) {
+
+ uintptr_t target_vaddr = lib_php->p_vaddr + lib_base;
+ map_info *existing_map = core_lookup(ph, target_vaddr);
+
+ if (existing_map == NULL){
+ if (add_map_info(ph, lib_fd, lib_php->p_offset,
+ target_vaddr, lib_php->p_memsz) == NULL) {
+ goto err;
+ }
+ } else {
+ // Coredump stores value of p_memsz elf field
+ // rounded up to page boundary.
+
+ if ((existing_map->memsz != page_size) &&
+ (existing_map->fd != lib_fd) &&
+ (ROUNDUP(existing_map->memsz, page_size) != ROUNDUP(lib_php->p_memsz, page_size))) {
+
+ print_debug("address conflict @ 0x%lx (existing map size = %ld, size = %ld, flags = %d)\n",
+ target_vaddr, existing_map->memsz, lib_php->p_memsz, lib_php->p_flags);
+ goto err;
+ }
+
+ /* replace PT_LOAD segment with library segment */
+ print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n",
+ existing_map->memsz, ROUNDUP(lib_php->p_memsz, page_size));
+
+ existing_map->fd = lib_fd;
+ existing_map->offset = lib_php->p_offset;
+ existing_map->memsz = ROUNDUP(lib_php->p_memsz, page_size);
}
- lib_php++;
- }
+ }
- free(phbuf);
- return true;
+ lib_php++;
+ }
+
+ free(phbuf);
+ return true;
err:
- free(phbuf);
- return false;
+ free(phbuf);
+ return false;
}
// process segments from interpreter (ld.so or ld-linux.so)
--- ./hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, 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
@@ -272,9 +272,10 @@
public static final int _fast_aldc = 229;
public static final int _fast_aldc_w = 230;
public static final int _return_register_finalizer = 231;
- public static final int _shouldnotreachhere = 232; // For debugging
+ public static final int _invokehandle = 232;
+ public static final int _shouldnotreachhere = 233; // For debugging
- public static final int number_of_codes = 233;
+ public static final int number_of_codes = 234;
// Flag bits derived from format strings, can_trap, can_rewrite, etc.:
// semantic flags:
@@ -798,6 +799,9 @@
def(_return_register_finalizer, "return_register_finalizer", "b" , null , BasicType.getTVoid() , 0, true, _return );
+ def(_invokehandle , "invokehandle" , "bJJ" , null , BasicType.getTIllegal(), -1, true, _invokevirtual );
+
+
def(_fast_aldc , "fast_aldc" , "bj" , null , BasicType.getTObject(), 1, true, _ldc );
def(_fast_aldc_w , "fast_aldc_w" , "bJJ" , null , BasicType.getTObject(), 1, true, _ldc_w );
--- ./hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/JVMTIThreadState.java Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/JVMTIThreadState.java Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2013 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
@@ -29,11 +29,10 @@
public static final int JVMTI_THREAD_STATE_ALIVE = 0x0001;
public static final int JVMTI_THREAD_STATE_TERMINATED = 0x0002;
public static final int JVMTI_THREAD_STATE_RUNNABLE = 0x0004;
- public static final int JVMTI_THREAD_STATE_WAITING = 0x0008;
+ public static final int JVMTI_THREAD_STATE_WAITING = 0x0080;
public static final int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
public static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
public static final int JVMTI_THREAD_STATE_SLEEPING = 0x0040;
- public static final int JVMTI_THREAD_STATE_WAITING_FOR_NOTIFICATION = 0x0080;
public static final int JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100;
public static final int JVMTI_THREAD_STATE_PARKED = 0x0200;
public static final int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400;
--- ./hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java Wed May 07 19:26:16 2014 -0700
@@ -32,7 +32,7 @@
// to the sys_thread_t structure of the classic JVM implementation.
public class OSThread extends VMObject {
private static JIntField interruptedField;
- private static JIntField threadIdField;
+ private static Field threadIdField;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@@ -44,7 +44,7 @@
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("OSThread");
interruptedField = type.getJIntField("_interrupted");
- threadIdField = type.getJIntField("_thread_id");
+ threadIdField = type.getField("_thread_id");
}
public OSThread(Address addr) {
@@ -56,7 +56,7 @@
}
public int threadId() {
- return (int)threadIdField.getValue(addr);
+ return threadIdField.getJInt(addr);
}
}
--- ./hotspot/make/bsd/makefiles/buildtree.make Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/make/bsd/makefiles/buildtree.make Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,6 @@
#
# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013 Red Hat, Inc.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -59,7 +60,7 @@
# needs to be set here since this Makefile doesn't include defs.make
OS_VENDOR:=$(shell uname -s)
--include $(SPEC)
+include $(GAMMADIR)/make/defs.make
include $(GAMMADIR)/make/scm.make
include $(GAMMADIR)/make/altsrc.make
@@ -215,6 +216,7 @@
echo "HOTSPOT_BUILD_USER = $(HOTSPOT_BUILD_USER)"; \
echo "HOTSPOT_VM_DISTRO = $(HOTSPOT_VM_DISTRO)"; \
echo "OPENJDK = $(OPENJDK)"; \
+ echo "ZERO_BUILD = $(ZERO_BUILD)"; \
echo; \
echo "# Used for platform dispatching"; \
echo "TARGET_DEFINES = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \
--- ./hotspot/make/bsd/makefiles/gcc.make Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/make/bsd/makefiles/gcc.make Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,6 @@
#
# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013 Red Hat, Inc.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -105,10 +106,10 @@
VM_PICFLAG/AOUT =
VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO))
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(TYPE),ZERO)
CFLAGS += $(LIBFFI_CFLAGS)
endif
-ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ifeq ($(TYPE),SHARK)
CFLAGS += $(LIBFFI_CFLAGS)
CFLAGS += $(LLVM_CFLAGS)
endif
--- ./hotspot/make/bsd/makefiles/vm.make Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/make/bsd/makefiles/vm.make Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,6 @@
#
# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013 Red Hat, Inc.
# 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,7 +43,9 @@
-include $(DEP_DIR)/*.d
# read machine-specific adjustments (%%% should do this via buildtree.make?)
-ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
+ifeq ($(TYPE),ZERO)
+ include $(MAKEFILES_DIR)/zeroshark.make
+else ifeq ($(TYPE),SHARK)
include $(MAKEFILES_DIR)/zeroshark.make
else
include $(MAKEFILES_DIR)/$(BUILDARCH).make
@@ -271,10 +274,10 @@
LIBS_VM += $(LIBS)
endif
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(TYPE),ZERO)
LIBS_VM += $(LIBFFI_LIBS)
endif
-ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ifeq ($(TYPE),SHARK)
LIBS_VM += $(LIBFFI_LIBS) $(LLVM_LIBS)
LFLAGS_VM += $(LLVM_LDFLAGS)
endif
--- ./hotspot/make/hotspot_version Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/make/hotspot_version Wed May 07 19:26:16 2014 -0700
@@ -34,8 +34,8 @@
HOTSPOT_VM_COPYRIGHT=Copyright 2014
HS_MAJOR_VER=24
-HS_MINOR_VER=55
-HS_BUILD_NUMBER=03
+HS_MINOR_VER=60
+HS_BUILD_NUMBER=09
JDK_MAJOR_VER=1
JDK_MINOR_VER=7
--- ./hotspot/make/linux/makefiles/buildtree.make Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/make/linux/makefiles/buildtree.make Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,6 @@
#
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013 Red Hat, Inc.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -56,7 +57,7 @@
# The makefiles are split this way so that "make foo" will run faster by not
# having to read the dependency files for the vm.
--include $(SPEC)
+include $(GAMMADIR)/make/defs.make
include $(GAMMADIR)/make/scm.make
include $(GAMMADIR)/make/altsrc.make
@@ -208,6 +209,7 @@
echo "HOTSPOT_BUILD_USER = $(HOTSPOT_BUILD_USER)"; \
echo "HOTSPOT_VM_DISTRO = $(HOTSPOT_VM_DISTRO)"; \
echo "OPENJDK = $(OPENJDK)"; \
+ echo "ZERO_BUILD = $(ZERO_BUILD)"; \
echo; \
echo "# Used for platform dispatching"; \
echo "TARGET_DEFINES = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \
--- ./hotspot/make/linux/makefiles/gcc.make Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/make/linux/makefiles/gcc.make Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,6 @@
#
# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013 Red Hat, Inc.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -72,10 +73,10 @@
VM_PICFLAG/AOUT =
VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO))
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(TYPE),ZERO)
CFLAGS += $(LIBFFI_CFLAGS)
endif
-ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ifeq ($(TYPE),SHARK)
CFLAGS += $(LIBFFI_CFLAGS)
CFLAGS += $(LLVM_CFLAGS)
endif
--- ./hotspot/make/linux/makefiles/vm.make Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/make/linux/makefiles/vm.make Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,6 @@
#
# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013 Red Hat, Inc.
# 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,7 +43,9 @@
-include $(DEP_DIR)/*.d
# read machine-specific adjustments (%%% should do this via buildtree.make?)
-ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
+ifeq ($(TYPE),ZERO)
+ include $(MAKEFILES_DIR)/zeroshark.make
+else ifeq ($(TYPE),SHARK)
include $(MAKEFILES_DIR)/zeroshark.make
else
include $(MAKEFILES_DIR)/$(BUILDARCH).make
@@ -244,7 +247,7 @@
vm.def: $(Res_Files) $(Obj_Files)
sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
-ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ifeq ($(TYPE),SHARK)
STATIC_CXX = false
else
ifeq ($(ZERO_LIBARCH), ppc64)
@@ -276,10 +279,10 @@
LIBS_VM += $(LIBS)
endif
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(TYPE),ZERO)
LIBS_VM += $(LIBFFI_LIBS)
endif
-ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ifeq ($(TYPE),SHARK)
LIBS_VM += $(LIBFFI_LIBS) $(LLVM_LIBS)
LFLAGS_VM += $(LLVM_LDFLAGS)
endif
--- ./hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Wed May 07 19:26:16 2014 -0700
@@ -4512,7 +4512,7 @@
#define __ masm.
address start = __ pc();
- Label not_already_dirty, restart, refill;
+ Label not_already_dirty, restart, refill, young_card;
#ifdef _LP64
__ srlx(O0, CardTableModRefBS::card_shift, O0);
@@ -4523,9 +4523,15 @@
__ set(addrlit, O1); // O1 :=
__ ldub(O0, O1, O2); // O2 := [O0 + O1]
+ __ cmp_and_br_short(O2, G1SATBCardTableModRefBS::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
+
+ __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+ __ ldub(O0, O1, O2); // O2 := [O0 + O1]
+
assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
__ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
+ __ bind(young_card);
// We didn't take the branch, so we're already dirty: return.
// Use return-from-leaf
__ retl();
--- ./hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed May 07 19:26:16 2014 -0700
@@ -36,6 +36,9 @@
#include "runtime/signature.hpp"
#include "runtime/vframeArray.hpp"
#include "vmreg_sparc.inline.hpp"
+#ifndef SERIALGC
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#endif
// Implementation of StubAssembler
@@ -898,7 +901,7 @@
Register tmp2 = G3_scratch;
jbyte* byte_map_base = ((CardTableModRefBS*)bs)->byte_map_base;
- Label not_already_dirty, restart, refill;
+ Label not_already_dirty, restart, refill, young_card;
#ifdef _LP64
__ srlx(addr, CardTableModRefBS::card_shift, addr);
@@ -910,9 +913,15 @@
__ set(rs, cardtable); // cardtable :=
__ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
+ __ cmp_and_br_short(tmp, G1SATBCardTableModRefBS::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
+
+ __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+ __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
+
assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
__ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
+ __ bind(young_card);
// We didn't take the branch, so we're already dirty: return.
// Use return-from-leaf
__ retl();
--- ./hotspot/src/cpu/sparc/vm/sparc.ad Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/sparc/vm/sparc.ad Wed May 07 19:26:16 2014 -0700
@@ -3399,8 +3399,8 @@
interface(CONST_INTER);
%}
-// Unsigned (positive) Integer Immediate: 13-bit
-operand immU13() %{
+// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
+operand immU12() %{
predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
match(ConI);
op_cost(0);
@@ -3436,6 +3436,17 @@
interface(CONST_INTER);
%}
+// Int Immediate non-negative
+operand immU31()
+%{
+ predicate(n->get_int() >= 0);
+ match(ConI);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Integer Immediate: 0-bit
operand immI0() %{
predicate(n->get_int() == 0);
@@ -5732,7 +5743,6 @@
effect(TEMP dst, TEMP tmp);
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
- size((3+1)*4); // set may use two instructions.
format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
"SET $mask,$tmp\n\t"
"AND $dst,$tmp,$dst" %}
@@ -5854,13 +5864,13 @@
ins_pipe(iload_mem);
%}
-// Load Integer with a 13-bit mask into a Long Register
-instruct loadI2L_immI13(iRegL dst, memory mem, immI13 mask) %{
+// Load Integer with a 12-bit mask into a Long Register
+instruct loadI2L_immU12(iRegL dst, memory mem, immU12 mask) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
ins_cost(MEMORY_REF_COST + DEFAULT_COST);
size(2*4);
- format %{ "LDUW $mem,$dst\t! int & 13-bit mask -> long\n\t"
+ format %{ "LDUW $mem,$dst\t! int & 12-bit mask -> long\n\t"
"AND $dst,$mask,$dst" %}
ins_encode %{
Register Rdst = $dst$$Register;
@@ -5870,14 +5880,13 @@
ins_pipe(iload_mem);
%}
-// Load Integer with a 32-bit mask into a Long Register
-instruct loadI2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
+// Load Integer with a 31-bit mask into a Long Register
+instruct loadI2L_immU31(iRegL dst, memory mem, immU31 mask, iRegL tmp) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
effect(TEMP dst, TEMP tmp);
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
- size((3+1)*4); // set may use two instructions.
- format %{ "LDUW $mem,$dst\t! int & 32-bit mask -> long\n\t"
+ format %{ "LDUW $mem,$dst\t! int & 31-bit mask -> long\n\t"
"SET $mask,$tmp\n\t"
"AND $dst,$tmp,$dst" %}
ins_encode %{
@@ -8919,7 +8928,7 @@
ins_pipe(ialu_cconly_reg_reg);
%}
-instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU13 op2 ) %{
+instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU12 op2 ) %{
match(Set icc (CmpU op1 op2));
size(4);
--- ./hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -1873,6 +1873,25 @@
if (ProfileInterpreter) {
__ set_method_data_pointer_for_bcp();
}
+
+ if (EnableInvokeDynamic) {
+ Label L_done;
+
+ __ ldub(Address(Lbcp, 0), G1_scratch); // Load current bytecode
+ __ cmp_and_br_short(G1_scratch, Bytecodes::_invokestatic, Assembler::notEqual, Assembler::pn, L_done);
+
+ // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call.
+ // Detect such a case in the InterpreterRuntime function and return the member name argument, or NULL.
+
+ __ call_VM(G1_scratch, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), I0, Lmethod, Lbcp);
+
+ __ br_null(G1_scratch, false, Assembler::pn, L_done);
+ __ delayed()->nop();
+
+ __ st_ptr(G1_scratch, Lesp, wordSize);
+ __ bind(L_done);
+ }
+
// Resume bytecode interpretation at the current bcp
__ dispatch_next(vtos);
// end of JVMTI PopFrame support
--- ./hotspot/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed May 07 19:26:16 2014 -0700
@@ -8754,13 +8754,18 @@
const Register card_addr = tmp;
lea(card_addr, as_Address(ArrayAddress(cardtable, index)));
#endif
- cmpb(Address(card_addr, 0), 0);
+ cmpb(Address(card_addr, 0), (int)G1SATBCardTableModRefBS::g1_young_card_val());
jcc(Assembler::equal, done);
+ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+ cmpb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
+ jcc(Assembler::equal, done);
+
+
// storing a region crossing, non-NULL oop, card is clean.
// dirty card and log.
- movb(Address(card_addr, 0), 0);
+ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
cmpl(queue_index, 0);
jcc(Assembler::equal, runtime);
--- ./hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed May 07 19:26:16 2014 -0700
@@ -1686,14 +1686,6 @@
}
assert_different_registers(obj, k_RInfo, klass_RInfo);
- if (!k->is_loaded()) {
- jobject2reg_with_patching(k_RInfo, op->info_for_patch());
- } else {
-#ifdef _LP64
- __ movoop(k_RInfo, k->constant_encoding());
-#endif // _LP64
- }
- assert(obj != k_RInfo, "must be different");
__ cmpptr(obj, (int32_t)NULL_WORD);
if (op->should_profile()) {
@@ -1710,6 +1702,14 @@
} else {
__ jcc(Assembler::equal, *obj_is_null);
}
+
+ if (!k->is_loaded()) {
+ jobject2reg_with_patching(k_RInfo, op->info_for_patch());
+ } else {
+#ifdef _LP64
+ __ movoop(k_RInfo, k->constant_encoding());
+#endif // _LP64
+ }
__ verify_oop(obj);
if (op->fast_check()) {
--- ./hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed May 07 19:26:16 2014 -0700
@@ -1395,19 +1395,18 @@
addr = new LIR_Address(src.result(), offset, type);
}
- if (data != dst) {
- __ move(data, dst);
- data = dst;
- }
+ // Because we want a 2-arg form of xchg and xadd
+ __ move(data, dst);
+
if (x->is_add()) {
- __ xadd(LIR_OprFact::address(addr), data, dst, LIR_OprFact::illegalOpr);
+ __ xadd(LIR_OprFact::address(addr), dst, dst, LIR_OprFact::illegalOpr);
} else {
if (is_obj) {
// Do the pre-write barrier, if any.
pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
true /* do_load */, false /* patch */, NULL);
}
- __ xchg(LIR_OprFact::address(addr), data, dst, LIR_OprFact::illegalOpr);
+ __ xchg(LIR_OprFact::address(addr), dst, dst, LIR_OprFact::illegalOpr);
if (is_obj) {
// Seems to be a precise address
post_barrier(LIR_OprFact::address(addr), data);
--- ./hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed May 07 19:26:16 2014 -0700
@@ -37,6 +37,9 @@
#include "runtime/signature.hpp"
#include "runtime/vframeArray.hpp"
#include "vmreg_x86.inline.hpp"
+#ifndef SERIALGC
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#endif
// Implementation of StubAssembler
@@ -1743,13 +1746,17 @@
__ leal(card_addr, __ as_Address(ArrayAddress(cardtable, index)));
#endif
- __ cmpb(Address(card_addr, 0), 0);
+ __ cmpb(Address(card_addr, 0), (int)G1SATBCardTableModRefBS::g1_young_card_val());
+ __ jcc(Assembler::equal, done);
+
+ __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+ __ cmpb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
__ jcc(Assembler::equal, done);
// storing region crossing non-NULL, card is clean.
// dirty card and log.
- __ movb(Address(card_addr, 0), 0);
+ __ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
__ cmpl(queue_index, 0);
__ jcc(Assembler::equal, runtime);
--- ./hotspot/src/cpu/x86/vm/frame_x86.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/frame_x86.cpp Wed May 07 19:26:16 2014 -0700
@@ -94,12 +94,6 @@
// other generic buffer blobs are more problematic so we just assume they are
// ok. adapter blobs never have a frame complete and are never ok.
- // check for a valid frame_size, otherwise we are unlikely to get a valid sender_pc
-
- if (!Interpreter::contains(_pc) && _cb->frame_size() <= 0) {
- return false;
- }
-
if (!_cb->is_frame_complete_at(_pc)) {
if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) {
return false;
@@ -139,6 +133,11 @@
// must be some sort of compiled/runtime frame
// fp does not have to be safe (although it could be check for c1?)
+ // check for a valid frame_size, otherwise we are unlikely to get a valid sender_pc
+ if (_cb->frame_size() <= 0) {
+ return false;
+ }
+
sender_sp = _unextended_sp + _cb->frame_size();
// On Intel the return_address is always the word on the stack
sender_pc = (address) *(sender_sp-1);
--- ./hotspot/src/cpu/x86/vm/globals_x86.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/globals_x86.hpp Wed May 07 19:26:16 2014 -0700
@@ -62,7 +62,7 @@
// due to lack of optimization caused by C++ compiler bugs
define_pd_global(intx, StackShadowPages, NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2));
#else
-define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
+define_pd_global(intx, StackShadowPages, 6 DEBUG_ONLY(+5));
#endif // AMD64
define_pd_global(intx, PreInflateSpin, 10);
--- ./hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -1789,6 +1789,27 @@
__ get_thread(thread);
__ movl(Address(thread, JavaThread::popframe_condition_offset()), JavaThread::popframe_inactive);
+ if (EnableInvokeDynamic) {
+ Label L_done;
+ const Register local0 = rdi;
+
+ __ cmpb(Address(rsi, 0), Bytecodes::_invokestatic);
+ __ jcc(Assembler::notEqual, L_done);
+
+ // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call.
+ // Detect such a case in the InterpreterRuntime function and return the member name argument, or NULL.
+
+ __ get_method(rdx);
+ __ movptr(rax, Address(local0, 0));
+ __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), rax, rdx, rsi);
+
+ __ testptr(rax, rax);
+ __ jcc(Assembler::zero, L_done);
+
+ __ movptr(Address(rbx, 0), rax);
+ __ bind(L_done);
+ }
+
__ dispatch_next(vtos);
// end of PopFrame support
--- ./hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -1815,6 +1815,27 @@
__ movl(Address(r15_thread, JavaThread::popframe_condition_offset()),
JavaThread::popframe_inactive);
+ if (EnableInvokeDynamic) {
+ Label L_done;
+ const Register local0 = r14;
+
+ __ cmpb(Address(r13, 0), Bytecodes::_invokestatic);
+ __ jcc(Assembler::notEqual, L_done);
+
+ // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call.
+ // Detect such a case in the InterpreterRuntime function and return the member name argument, or NULL.
+
+ __ get_method(rdx);
+ __ movptr(rax, Address(local0, 0));
+ __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), rax, rdx, r13);
+
+ __ testptr(rax, rax);
+ __ jcc(Assembler::zero, L_done);
+
+ __ movptr(Address(rbx, 0), rax);
+ __ bind(L_done);
+ }
+
__ dispatch_next(vtos);
// end of PopFrame support
--- ./hotspot/src/cpu/x86/vm/x86_32.ad Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/x86_32.ad Wed May 07 19:26:16 2014 -0700
@@ -3919,6 +3919,17 @@
interface(CONST_INTER);
%}
+// Int Immediate non-negative
+operand immU31()
+%{
+ predicate(n->get_int() >= 0);
+ match(ConI);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Constant for long shifts
operand immI_32() %{
predicate( n->get_int() == 32 );
@@ -6135,12 +6146,12 @@
ins_pipe(ialu_reg_mem);
%}
-// Load Integer with 32-bit mask into Long Register
-instruct loadI2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
+// Load Integer with 31-bit mask into Long Register
+instruct loadI2L_immU31(eRegL dst, memory mem, immU31 mask, eFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
effect(KILL cr);
- format %{ "MOV $dst.lo,$mem\t# int & 32-bit mask -> long\n\t"
+ format %{ "MOV $dst.lo,$mem\t# int & 31-bit mask -> long\n\t"
"XOR $dst.hi,$dst.hi\n\t"
"AND $dst.lo,$mask" %}
ins_encode %{
--- ./hotspot/src/cpu/x86/vm/x86_64.ad Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/x86/vm/x86_64.ad Wed May 07 19:26:16 2014 -0700
@@ -3142,6 +3142,17 @@
interface(CONST_INTER);
%}
+// Int Immediate non-negative
+operand immU31()
+%{
+ predicate(n->get_int() >= 0);
+ match(ConI);
+
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Constant for long shifts
operand immI_32()
%{
@@ -5083,12 +5094,12 @@
ins_pipe(ialu_reg_mem);
%}
-// Load Integer with a 32-bit mask into Long Register
-instruct loadI2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
+// Load Integer with a 31-bit mask into Long Register
+instruct loadI2L_immU31(rRegL dst, memory mem, immU31 mask, rFlagsReg cr) %{
match(Set dst (ConvI2L (AndI (LoadI mem) mask)));
effect(KILL cr);
- format %{ "movl $dst, $mem\t# int & 32-bit mask -> long\n\t"
+ format %{ "movl $dst, $mem\t# int & 31-bit mask -> long\n\t"
"andl $dst, $mask" %}
ins_encode %{
Register Rdst = $dst$$Register;
--- ./hotspot/src/cpu/zero/vm/entryFrame_zero.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/zero/vm/entryFrame_zero.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2008, 2010 Red Hat, Inc.
+ * Copyright (c) 2013 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,8 @@
JavaCallWrapper* call_wrapper,
TRAPS);
public:
- JavaCallWrapper *call_wrapper() const {
- return (JavaCallWrapper *) value_of_word(call_wrapper_off);
+ JavaCallWrapper **call_wrapper() const {
+ return (JavaCallWrapper **) addr_of_word(call_wrapper_off);
}
public:
--- ./hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2007, 2013, Red Hat, Inc.
+ * Copyright (c) 2013 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -132,7 +132,7 @@
return fp();
}
-inline JavaCallWrapper* frame::entry_frame_call_wrapper() const {
+inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const {
return zero_entryframe()->call_wrapper();
}
--- ./hotspot/src/os/bsd/vm/attachListener_bsd.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/bsd/vm/attachListener_bsd.cpp Wed May 07 19:26:16 2014 -0700
@@ -460,14 +460,14 @@
void AttachListener::vm_start() {
char fn[UNIX_PATH_MAX];
- struct stat64 st;
+ struct stat st;
int ret;
int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow");
- RESTARTABLE(::stat64(fn, &st), ret);
+ RESTARTABLE(::stat(fn, &st), ret);
if (ret == 0) {
ret = ::unlink(fn);
if (ret == -1) {
--- ./hotspot/src/os/bsd/vm/os_bsd.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/bsd/vm/os_bsd.cpp Wed May 07 19:26:16 2014 -0700
@@ -1582,10 +1582,10 @@
return (1000 * 1000);
}
-// XXX: For now, code this as if BSD does not support vtime.
-bool os::supports_vtime() { return false; }
+bool os::supports_vtime() { return true; }
bool os::enable_vtime() { return false; }
bool os::vtime_enabled() { return false; }
+
double os::elapsedVTime() {
// better than nothing, but not much
return elapsedTime();
@@ -3434,7 +3434,9 @@
#endif
#endif
-char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) {
+char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr, bool exec) {
+ fatal("This code is not used or maintained.");
+
// "exec" is passed in but not used. Creating the shared image for
// the code cache doesn't have an SHM_X executable permission to check.
assert(UseLargePages && UseSHM, "only for SHM large pages");
@@ -6105,3 +6107,9 @@
return n;
}
+#ifndef PRODUCT
+void TestReserveMemorySpecial_test() {
+ // No tests available for this platform
+}
+#endif
+
--- ./hotspot/src/os/linux/vm/globals_linux.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/linux/vm/globals_linux.hpp Wed May 07 19:26:16 2014 -0700
@@ -40,6 +40,9 @@
product(bool, UseHugeTLBFS, false, \
"Use MAP_HUGETLB for large pages") \
\
+ product(bool, UseTransparentHugePages, false, \
+ "Use MADV_HUGEPAGE for large pages") \
+ \
product(bool, LoadExecStackDllInVMThread, true, \
"Load DLLs with executable-stack attribute in the VM Thread") \
\
@@ -50,7 +53,7 @@
// Defines Linux-specific default values. The flags are available on all
// platforms, but they may have different default values on other platforms.
//
-define_pd_global(bool, UseLargePages, true);
+define_pd_global(bool, UseLargePages, false);
define_pd_global(bool, UseLargePagesIndividualAllocation, false);
define_pd_global(bool, UseOSErrorReporting, false);
define_pd_global(bool, UseThreadPriorities, true) ;
--- ./hotspot/src/os/linux/vm/jsig.c Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/linux/vm/jsig.c Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, 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,7 +107,7 @@
signal_lock();
- sigused = (MASK(sig) & jvmsigs) != 0;
+ sigused = (sig < MAXSIGNUM) && ((MASK(sig) & jvmsigs) != 0);
if (jvm_signal_installed && sigused) {
/* jvm has installed its signal handler for this signal. */
/* Save the handler. Don't really install it. */
@@ -116,7 +116,7 @@
signal_unlock();
return oldhandler;
- } else if (jvm_signal_installing) {
+ } else if (sig < MAXSIGNUM && jvm_signal_installing) {
/* jvm is installing its signal handlers. Install the new
* handlers and save the old ones. jvm uses sigaction().
* Leave the piece here just in case. */
@@ -165,7 +165,7 @@
signal_lock();
- sigused = (MASK(sig) & jvmsigs) != 0;
+ sigused = (sig < MAXSIGNUM) && ((MASK(sig) & jvmsigs) != 0);
if (jvm_signal_installed && sigused) {
/* jvm has installed its signal handler for this signal. */
/* Save the handler. Don't really install it. */
@@ -178,7 +178,7 @@
signal_unlock();
return 0;
- } else if (jvm_signal_installing) {
+ } else if (sig < MAXSIGNUM && jvm_signal_installing) {
/* jvm is installing its signal handlers. Install the new
* handlers and save the old ones. */
res = call_os_sigaction(sig, act, &oldAct);
--- ./hotspot/src/os/linux/vm/os_linux.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/linux/vm/os_linux.cpp Wed May 07 19:26:16 2014 -0700
@@ -120,8 +120,16 @@
# include
# include
+// if RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling
+// getrusage() is prepared to handle the associated failure.
+#ifndef RUSAGE_THREAD
+#define RUSAGE_THREAD (1) /* only the calling thread */
+#endif
+
#define MAX_PATH (2 * K)
+#define MAX_SECS 100000000
+
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
@@ -144,6 +152,7 @@
bool os::Linux::_supports_fast_thread_cpu_time = false;
const char * os::Linux::_glibc_version = NULL;
const char * os::Linux::_libpthread_version = NULL;
+pthread_condattr_t os::Linux::_condattr[1];
static jlong initial_time_count=0;
@@ -1377,15 +1386,19 @@
return (1000 * 1000);
}
-// For now, we say that linux does not support vtime. I have no idea
-// whether it can actually be made to (DLD, 9/13/05).
-
-bool os::supports_vtime() { return false; }
+bool os::supports_vtime() { return true; }
bool os::enable_vtime() { return false; }
bool os::vtime_enabled() { return false; }
+
double os::elapsedVTime() {
- // better than nothing, but not much
- return elapsedTime();
+ struct rusage usage;
+ int retval = getrusage(RUSAGE_THREAD, &usage);
+ if (retval == 0) {
+ return (double) (usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) + (double) (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec) / (1000 * 1000);
+ } else {
+ // better than nothing, but not much
+ return elapsedTime();
+ }
}
jlong os::javaTimeMillis() {
@@ -1427,12 +1440,15 @@
clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) {
// yes, monotonic clock is supported
_clock_gettime = clock_gettime_func;
+ return;
} else {
// close librt if there is no monotonic clock
dlclose(handle);
}
}
}
+ warning("No monotonic clock was available - timed services may " \
+ "be adversely affected if the time-of-day clock changes");
}
#ifndef SYS_clock_getres
@@ -2468,7 +2484,6 @@
sem_t _semaphore;
};
-
Semaphore::Semaphore() {
sem_init(&_semaphore, 0, 0);
}
@@ -2490,8 +2505,22 @@
}
bool Semaphore::timedwait(unsigned int sec, int nsec) {
+
struct timespec ts;
- unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
+ // Semaphore's are always associated with CLOCK_REALTIME
+ os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
+ // see unpackTime for discussion on overflow checking
+ if (sec >= MAX_SECS) {
+ ts.tv_sec += MAX_SECS;
+ ts.tv_nsec = 0;
+ } else {
+ ts.tv_sec += sec;
+ ts.tv_nsec += nsec;
+ if (ts.tv_nsec >= NANOSECS_PER_SEC) {
+ ts.tv_nsec -= NANOSECS_PER_SEC;
+ ++ts.tv_sec; // note: this must be <= max_secs
+ }
+ }
while (1) {
int result = sem_timedwait(&_semaphore, &ts);
@@ -2696,14 +2725,6 @@
alignment_hint, exec, strerror(err), err);
}
-static void warn_fail_commit_memory(char* addr, size_t size,
- size_t alignment_hint, bool exec,
- int err, const char* msg) {
- warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT
- ", " SIZE_FORMAT ", %d) failed; error='%s' (errno=%d); %s", addr, size,
- alignment_hint, exec, strerror(err), err, msg);
-}
-
// NOTE: Linux kernel does not really reserve the pages for us.
// All it does is to check if there are enough free pages
// left at the time of mmap(). This could be a potential
@@ -2754,41 +2775,9 @@
#define MADV_HUGEPAGE 14
#endif
-volatile jint os::Linux::num_largepage_commit_fails = 0;
-
int os::Linux::commit_memory_impl(char* addr, size_t size,
size_t alignment_hint, bool exec) {
- int err;
- if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
- int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
- uintptr_t res =
- (uintptr_t) ::mmap(addr, size, prot,
- MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB,
- -1, 0);
- if (res != (uintptr_t) MAP_FAILED) {
- if (UseNUMAInterleaving) {
- numa_make_global(addr, size);
- }
- return 0;
- }
-
- err = errno; // save errno from mmap() call above
-
- if (!recoverable_mmap_error(err)) {
- // However, it is not clear that this loss of our reserved mapping
- // happens with large pages on Linux or that we cannot recover
- // from the loss. For now, we just issue a warning and we don't
- // call vm_exit_out_of_memory(). This issue is being tracked by
- // JBS-8007074.
- Atomic::inc(&os::Linux::num_largepage_commit_fails);
- warn_fail_commit_memory(addr, size, alignment_hint, exec, err,
- "Cannot allocate large pages, falling back to regular pages");
-// vm_exit_out_of_memory(size, "committing reserved memory.");
- }
- // Fall through and try to use small pages
- }
-
- err = os::Linux::commit_memory_impl(addr, size, exec);
+ int err = os::Linux::commit_memory_impl(addr, size, exec);
if (err == 0) {
realign_memory(addr, size, alignment_hint);
}
@@ -2813,7 +2802,7 @@
}
void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
- if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
+ if (UseTransparentHugePages && alignment_hint > (size_t)vm_page_size()) {
// We don't check the return value: madvise(MADV_HUGEPAGE) may not
// be supported or the memory may already be backed by huge pages.
::madvise(addr, bytes, MADV_HUGEPAGE);
@@ -2826,7 +2815,7 @@
// uncommitted at all. We don't do anything in this case to avoid creating a segment with
// small pages on top of the SHM segment. This method always works for small pages, so we
// allow that in any case.
- if (alignment_hint <= (size_t)os::vm_page_size() || !UseSHM) {
+ if (alignment_hint <= (size_t)os::vm_page_size() || can_commit_large_page_memory()) {
commit_memory(addr, bytes, alignment_hint, !ExecMem);
}
}
@@ -3195,11 +3184,31 @@
return linux_mprotect(addr, size, PROT_READ|PROT_WRITE);
}
+bool os::Linux::transparent_huge_pages_sanity_check(bool warn, size_t page_size) {
+ bool result = false;
+ void *p = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE,
+ -1, 0);
+ if (p != MAP_FAILED) {
+ void *aligned_p = align_ptr_up(p, page_size);
+
+ result = madvise(aligned_p, page_size, MADV_HUGEPAGE) == 0;
+
+ munmap(p, page_size * 2);
+ }
+
+ if (warn && !result) {
+ warning("TransparentHugePages is not supported by the operating system.");
+ }
+
+ return result;
+}
+
bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) {
bool result = false;
- void *p = mmap (NULL, page_size, PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB,
- -1, 0);
+ void *p = mmap(NULL, page_size, PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB,
+ -1, 0);
if (p != MAP_FAILED) {
// We don't know if this really is a huge page or not.
@@ -3220,12 +3229,10 @@
}
fclose(fp);
}
- munmap (p, page_size);
- if (result)
- return true;
- }
-
- if (warn) {
+ munmap(p, page_size);
+ }
+
+ if (warn && !result) {
warning("HugeTLBFS is not supported by the operating system.");
}
@@ -3273,82 +3280,126 @@
static size_t _large_page_size = 0;
-void os::large_page_init() {
- if (!UseLargePages) {
- UseHugeTLBFS = false;
- UseSHM = false;
- return;
- }
-
- if (FLAG_IS_DEFAULT(UseHugeTLBFS) && FLAG_IS_DEFAULT(UseSHM)) {
- // If UseLargePages is specified on the command line try both methods,
- // if it's default, then try only HugeTLBFS.
- if (FLAG_IS_DEFAULT(UseLargePages)) {
- UseHugeTLBFS = true;
- } else {
- UseHugeTLBFS = UseSHM = true;
- }
- }
-
- if (LargePageSizeInBytes) {
- _large_page_size = LargePageSizeInBytes;
- } else {
- // large_page_size on Linux is used to round up heap size. x86 uses either
- // 2M or 4M page, depending on whether PAE (Physical Address Extensions)
- // mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use
- // page as large as 256M.
- //
- // Here we try to figure out page size by parsing /proc/meminfo and looking
- // for a line with the following format:
- // Hugepagesize: 2048 kB
- //
- // If we can't determine the value (e.g. /proc is not mounted, or the text
- // format has been changed), we'll use the largest page size supported by
- // the processor.
+size_t os::Linux::find_large_page_size() {
+ size_t large_page_size = 0;
+
+ // large_page_size on Linux is used to round up heap size. x86 uses either
+ // 2M or 4M page, depending on whether PAE (Physical Address Extensions)
+ // mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use
+ // page as large as 256M.
+ //
+ // Here we try to figure out page size by parsing /proc/meminfo and looking
+ // for a line with the following format:
+ // Hugepagesize: 2048 kB
+ //
+ // If we can't determine the value (e.g. /proc is not mounted, or the text
+ // format has been changed), we'll use the largest page size supported by
+ // the processor.
#ifndef ZERO
- _large_page_size = IA32_ONLY(4 * M) AMD64_ONLY(2 * M) IA64_ONLY(256 * M) SPARC_ONLY(4 * M)
- ARM_ONLY(2 * M) PPC_ONLY(4 * M);
+ large_page_size = IA32_ONLY(4 * M) AMD64_ONLY(2 * M) IA64_ONLY(256 * M) SPARC_ONLY(4 * M)
+ ARM_ONLY(2 * M) PPC_ONLY(4 * M);
#endif // ZERO
- FILE *fp = fopen("/proc/meminfo", "r");
- if (fp) {
- while (!feof(fp)) {
- int x = 0;
- char buf[16];
- if (fscanf(fp, "Hugepagesize: %d", &x) == 1) {
- if (x && fgets(buf, sizeof(buf), fp) && strcmp(buf, " kB\n") == 0) {
- _large_page_size = x * K;
- break;
- }
- } else {
- // skip to next line
- for (;;) {
- int ch = fgetc(fp);
- if (ch == EOF || ch == (int)'\n') break;
- }
+ FILE *fp = fopen("/proc/meminfo", "r");
+ if (fp) {
+ while (!feof(fp)) {
+ int x = 0;
+ char buf[16];
+ if (fscanf(fp, "Hugepagesize: %d", &x) == 1) {
+ if (x && fgets(buf, sizeof(buf), fp) && strcmp(buf, " kB\n") == 0) {
+ large_page_size = x * K;
+ break;
+ }
+ } else {
+ // skip to next line
+ for (;;) {
+ int ch = fgetc(fp);
+ if (ch == EOF || ch == (int)'\n') break;
}
}
- fclose(fp);
}
- }
-
- // print a warning if any large page related flag is specified on command line
- bool warn_on_failure = !FLAG_IS_DEFAULT(UseHugeTLBFS);
-
+ fclose(fp);
+ }
+
+ if (!FLAG_IS_DEFAULT(LargePageSizeInBytes) && LargePageSizeInBytes != large_page_size) {
+ warning("Setting LargePageSizeInBytes has no effect on this OS. Large page size is "
+ SIZE_FORMAT "%s.", byte_size_in_proper_unit(large_page_size),
+ proper_unit_for_byte_size(large_page_size));
+ }
+
+ return large_page_size;
+}
+
+size_t os::Linux::setup_large_page_size() {
+ _large_page_size = Linux::find_large_page_size();
const size_t default_page_size = (size_t)Linux::page_size();
if (_large_page_size > default_page_size) {
_page_sizes[0] = _large_page_size;
_page_sizes[1] = default_page_size;
_page_sizes[2] = 0;
}
- UseHugeTLBFS = UseHugeTLBFS &&
- Linux::hugetlbfs_sanity_check(warn_on_failure, _large_page_size);
-
- if (UseHugeTLBFS)
+
+ return _large_page_size;
+}
+
+bool os::Linux::setup_large_page_type(size_t page_size) {
+ if (FLAG_IS_DEFAULT(UseHugeTLBFS) &&
+ FLAG_IS_DEFAULT(UseSHM) &&
+ FLAG_IS_DEFAULT(UseTransparentHugePages)) {
+
+ // The type of large pages has not been specified by the user.
+
+ // Try UseHugeTLBFS and then UseSHM.
+ UseHugeTLBFS = UseSHM = true;
+
+ // Don't try UseTransparentHugePages since there are known
+ // performance issues with it turned on. This might change in the future.
+ UseTransparentHugePages = false;
+ }
+
+ if (UseTransparentHugePages) {
+ bool warn_on_failure = !FLAG_IS_DEFAULT(UseTransparentHugePages);
+ if (transparent_huge_pages_sanity_check(warn_on_failure, page_size)) {
+ UseHugeTLBFS = false;
+ UseSHM = false;
+ return true;
+ }
+ UseTransparentHugePages = false;
+ }
+
+ if (UseHugeTLBFS) {
+ bool warn_on_failure = !FLAG_IS_DEFAULT(UseHugeTLBFS);
+ if (hugetlbfs_sanity_check(warn_on_failure, page_size)) {
+ UseSHM = false;
+ return true;
+ }
+ UseHugeTLBFS = false;
+ }
+
+ return UseSHM;
+}
+
+void os::large_page_init() {
+ if (!UseLargePages &&
+ !UseTransparentHugePages &&
+ !UseHugeTLBFS &&
+ !UseSHM) {
+ // Not using large pages.
+ return;
+ }
+
+ if (!FLAG_IS_DEFAULT(UseLargePages) && !UseLargePages) {
+ // The user explicitly turned off large pages.
+ // Ignore the rest of the large pages flags.
+ UseTransparentHugePages = false;
+ UseHugeTLBFS = false;
UseSHM = false;
-
- UseLargePages = UseHugeTLBFS || UseSHM;
+ return;
+ }
+
+ size_t large_page_size = Linux::setup_large_page_size();
+ UseLargePages = Linux::setup_large_page_type(large_page_size);
set_coredump_filter();
}
@@ -3357,16 +3408,22 @@
#define SHM_HUGETLB 04000
#endif
-char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) {
+char* os::Linux::reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec) {
// "exec" is passed in but not used. Creating the shared image for
// the code cache doesn't have an SHM_X executable permission to check.
assert(UseLargePages && UseSHM, "only for SHM large pages");
+ assert(is_ptr_aligned(req_addr, os::large_page_size()), "Unaligned address");
+
+ if (!is_size_aligned(bytes, os::large_page_size()) || alignment > os::large_page_size()) {
+ return NULL; // Fallback to small pages.
+ }
key_t key = IPC_PRIVATE;
char *addr;
bool warn_on_failure = UseLargePages &&
(!FLAG_IS_DEFAULT(UseLargePages) ||
+ !FLAG_IS_DEFAULT(UseSHM) ||
!FLAG_IS_DEFAULT(LargePageSizeInBytes)
);
char msg[128];
@@ -3414,42 +3471,220 @@
return NULL;
}
- if ((addr != NULL) && UseNUMAInterleaving) {
- numa_make_global(addr, bytes);
- }
-
- // The memory is committed
- MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC);
-
return addr;
}
+static void warn_on_large_pages_failure(char* req_addr, size_t bytes, int error) {
+ assert(error == ENOMEM, "Only expect to fail if no memory is available");
+
+ bool warn_on_failure = UseLargePages &&
+ (!FLAG_IS_DEFAULT(UseLargePages) ||
+ !FLAG_IS_DEFAULT(UseHugeTLBFS) ||
+ !FLAG_IS_DEFAULT(LargePageSizeInBytes));
+
+ if (warn_on_failure) {
+ char msg[128];
+ jio_snprintf(msg, sizeof(msg), "Failed to reserve large pages memory req_addr: "
+ PTR_FORMAT " bytes: " SIZE_FORMAT " (errno = %d).", req_addr, bytes, error);
+ warning(msg);
+ }
+}
+
+char* os::Linux::reserve_memory_special_huge_tlbfs_only(size_t bytes, char* req_addr, bool exec) {
+ assert(UseLargePages && UseHugeTLBFS, "only for Huge TLBFS large pages");
+ assert(is_size_aligned(bytes, os::large_page_size()), "Unaligned size");
+ assert(is_ptr_aligned(req_addr, os::large_page_size()), "Unaligned address");
+
+ int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
+ char* addr = (char*)::mmap(req_addr, bytes, prot,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB,
+ -1, 0);
+
+ if (addr == MAP_FAILED) {
+ warn_on_large_pages_failure(req_addr, bytes, errno);
+ return NULL;
+ }
+
+ assert(is_ptr_aligned(addr, os::large_page_size()), "Must be");
+
+ return addr;
+}
+
+char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t alignment, char* req_addr, bool exec) {
+ size_t large_page_size = os::large_page_size();
+
+ assert(bytes >= large_page_size, "Shouldn't allocate large pages for small sizes");
+
+ // Allocate small pages.
+
+ char* start;
+ if (req_addr != NULL) {
+ assert(is_ptr_aligned(req_addr, alignment), "Must be");
+ assert(is_size_aligned(bytes, alignment), "Must be");
+ start = os::reserve_memory(bytes, req_addr);
+ assert(start == NULL || start == req_addr, "Must be");
+ } else {
+ start = os::reserve_memory_aligned(bytes, alignment);
+ }
+
+ if (start == NULL) {
+ return NULL;
+ }
+
+ assert(is_ptr_aligned(start, alignment), "Must be");
+
+ // os::reserve_memory_special will record this memory area.
+ // Need to release it here to prevent overlapping reservations.
+ MemTracker::record_virtual_memory_release((address)start, bytes);
+
+ char* end = start + bytes;
+
+ // Find the regions of the allocated chunk that can be promoted to large pages.
+ char* lp_start = (char*)align_ptr_up(start, large_page_size);
+ char* lp_end = (char*)align_ptr_down(end, large_page_size);
+
+ size_t lp_bytes = lp_end - lp_start;
+
+ assert(is_size_aligned(lp_bytes, large_page_size), "Must be");
+
+ if (lp_bytes == 0) {
+ // The mapped region doesn't even span the start and the end of a large page.
+ // Fall back to allocate a non-special area.
+ ::munmap(start, end - start);
+ return NULL;
+ }
+
+ int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
+
+
+ void* result;
+
+ if (start != lp_start) {
+ result = ::mmap(start, lp_start - start, prot,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
+ -1, 0);
+ if (result == MAP_FAILED) {
+ ::munmap(lp_start, end - lp_start);
+ return NULL;
+ }
+ }
+
+ result = ::mmap(lp_start, lp_bytes, prot,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|MAP_HUGETLB,
+ -1, 0);
+ if (result == MAP_FAILED) {
+ warn_on_large_pages_failure(req_addr, bytes, errno);
+ // If the mmap above fails, the large pages region will be unmapped and we
+ // have regions before and after with small pages. Release these regions.
+ //
+ // | mapped | unmapped | mapped |
+ // ^ ^ ^ ^
+ // start lp_start lp_end end
+ //
+ ::munmap(start, lp_start - start);
+ ::munmap(lp_end, end - lp_end);
+ return NULL;
+ }
+
+ if (lp_end != end) {
+ result = ::mmap(lp_end, end - lp_end, prot,
+ MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
+ -1, 0);
+ if (result == MAP_FAILED) {
+ ::munmap(start, lp_end - start);
+ return NULL;
+ }
+ }
+
+ return start;
+}
+
+char* os::Linux::reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, char* req_addr, bool exec) {
+ assert(UseLargePages && UseHugeTLBFS, "only for Huge TLBFS large pages");
+ assert(is_ptr_aligned(req_addr, alignment), "Must be");
+ assert(is_power_of_2(alignment), "Must be");
+ assert(is_power_of_2(os::large_page_size()), "Must be");
+ assert(bytes >= os::large_page_size(), "Shouldn't allocate large pages for small sizes");
+
+ if (is_size_aligned(bytes, os::large_page_size()) && alignment <= os::large_page_size()) {
+ return reserve_memory_special_huge_tlbfs_only(bytes, req_addr, exec);
+ } else {
+ return reserve_memory_special_huge_tlbfs_mixed(bytes, alignment, req_addr, exec);
+ }
+}
+
+char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr, bool exec) {
+ assert(UseLargePages, "only for large pages");
+
+ char* addr;
+ if (UseSHM) {
+ addr = os::Linux::reserve_memory_special_shm(bytes, alignment, req_addr, exec);
+ } else {
+ assert(UseHugeTLBFS, "must be");
+ addr = os::Linux::reserve_memory_special_huge_tlbfs(bytes, alignment, req_addr, exec);
+ }
+
+ if (addr != NULL) {
+ if (UseNUMAInterleaving) {
+ numa_make_global(addr, bytes);
+ }
+
+ // The memory is committed
+ MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC);
+ }
+
+ return addr;
+}
+
+bool os::Linux::release_memory_special_shm(char* base, size_t bytes) {
+ // detaching the SHM segment will also delete it, see reserve_memory_special_shm()
+ return shmdt(base) == 0;
+}
+
+bool os::Linux::release_memory_special_huge_tlbfs(char* base, size_t bytes) {
+ return pd_release_memory(base, bytes);
+}
+
bool os::release_memory_special(char* base, size_t bytes) {
+ assert(UseLargePages, "only for large pages");
+
MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
- // detaching the SHM segment will also delete it, see reserve_memory_special()
- int rslt = shmdt(base);
- if (rslt == 0) {
+
+ bool res;
+ if (UseSHM) {
+ res = os::Linux::release_memory_special_shm(base, bytes);
+ } else {
+ assert(UseHugeTLBFS, "must be");
+ res = os::Linux::release_memory_special_huge_tlbfs(base, bytes);
+ }
+
+ if (res) {
tkr.record((address)base, bytes);
- return true;
} else {
tkr.discard();
- return false;
- }
-}
+ }
+
+ return res;
+}
+
size_t os::large_page_size() {
return _large_page_size;
}
-// HugeTLBFS allows application to commit large page memory on demand;
-// with SysV SHM the entire memory region must be allocated as shared
+// With SysV SHM the entire memory region must be allocated as shared
// memory.
+// HugeTLBFS allows application to commit large page memory on demand.
+// However, when committing memory with HugeTLBFS fails, the region
+// that was supposed to be committed will lose the old reservation
+// and allow other threads to steal that memory region. Because of this
+// behavior we can't commit HugeTLBFS memory.
bool os::can_commit_large_page_memory() {
- return UseHugeTLBFS;
+ return UseTransparentHugePages;
}
bool os::can_execute_large_page_memory() {
- return UseHugeTLBFS;
+ return UseTransparentHugePages || UseHugeTLBFS;
}
// Reserve memory at an arbitrary address, only if that area is
@@ -4505,6 +4740,26 @@
Linux::clock_init();
initial_time_count = os::elapsed_counter();
+
+ // pthread_condattr initialization for monotonic clock
+ int status;
+ pthread_condattr_t* _condattr = os::Linux::condAttr();
+ if ((status = pthread_condattr_init(_condattr)) != 0) {
+ fatal(err_msg("pthread_condattr_init: %s", strerror(status)));
+ }
+ // Only set the clock if CLOCK_MONOTONIC is available
+ if (Linux::supports_monotonic_clock()) {
+ if ((status = pthread_condattr_setclock(_condattr, CLOCK_MONOTONIC)) != 0) {
+ if (status == EINVAL) {
+ warning("Unable to use monotonic clock with relative timed-waits" \
+ " - changes to the time-of-day clock may have adverse affects");
+ } else {
+ fatal(err_msg("pthread_condattr_setclock: %s", strerror(status)));
+ }
+ }
+ }
+ // else it defaults to CLOCK_REALTIME
+
pthread_mutex_init(&dl_mutex, NULL);
// If the pagesize of the VM is greater than 8K determine the appropriate
@@ -4587,6 +4842,10 @@
Linux::capture_initial_stack(JavaThread::stack_size_at_create());
+#if defined(IA32)
+ workaround_expand_exec_shield_cs_limit();
+#endif
+
Linux::libpthread_init();
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("[HotSpot is running with %s, %s(%s)]\n",
@@ -4603,21 +4862,23 @@
UseNUMA = false;
}
}
- // With SHM large pages we cannot uncommit a page, so there's not way
+ // With SHM and HugeTLBFS large pages we cannot uncommit a page, so there's no way
// we can make the adaptive lgrp chunk resizing work. If the user specified
- // both UseNUMA and UseLargePages (or UseSHM) on the command line - warn and
+ // both UseNUMA and UseLargePages (or UseSHM/UseHugeTLBFS) on the command line - warn and
// disable adaptive resizing.
- if (UseNUMA && UseLargePages && UseSHM) {
- if (!FLAG_IS_DEFAULT(UseNUMA)) {
- if (FLAG_IS_DEFAULT(UseLargePages) && FLAG_IS_DEFAULT(UseSHM)) {
+ if (UseNUMA && UseLargePages && !can_commit_large_page_memory()) {
+ if (FLAG_IS_DEFAULT(UseNUMA)) {
+ UseNUMA = false;
+ } else {
+ if (FLAG_IS_DEFAULT(UseLargePages) &&
+ FLAG_IS_DEFAULT(UseSHM) &&
+ FLAG_IS_DEFAULT(UseHugeTLBFS)) {
UseLargePages = false;
} else {
- warning("UseNUMA is not fully compatible with SHM large pages, disabling adaptive resizing");
+ warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, disabling adaptive resizing");
UseAdaptiveSizePolicy = false;
UseAdaptiveNUMAChunkSizing = false;
}
- } else {
- UseNUMA = false;
}
}
if (!UseNUMA && ForceNUMA) {
@@ -5351,21 +5612,36 @@
static struct timespec* compute_abstime(timespec* abstime, jlong millis) {
if (millis < 0) millis = 0;
- struct timeval now;
- int status = gettimeofday(&now, NULL);
- assert(status == 0, "gettimeofday");
+
jlong seconds = millis / 1000;
millis %= 1000;
if (seconds > 50000000) { // see man cond_timedwait(3T)
seconds = 50000000;
}
- abstime->tv_sec = now.tv_sec + seconds;
- long usec = now.tv_usec + millis * 1000;
- if (usec >= 1000000) {
- abstime->tv_sec += 1;
- usec -= 1000000;
- }
- abstime->tv_nsec = usec * 1000;
+
+ if (os::Linux::supports_monotonic_clock()) {
+ struct timespec now;
+ int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now);
+ assert_status(status == 0, status, "clock_gettime");
+ abstime->tv_sec = now.tv_sec + seconds;
+ long nanos = now.tv_nsec + millis * NANOSECS_PER_MILLISEC;
+ if (nanos >= NANOSECS_PER_SEC) {
+ abstime->tv_sec += 1;
+ nanos -= NANOSECS_PER_SEC;
+ }
+ abstime->tv_nsec = nanos;
+ } else {
+ struct timeval now;
+ int status = gettimeofday(&now, NULL);
+ assert(status == 0, "gettimeofday");
+ abstime->tv_sec = now.tv_sec + seconds;
+ long usec = now.tv_usec + millis * 1000;
+ if (usec >= 1000000) {
+ abstime->tv_sec += 1;
+ usec -= 1000000;
+ }
+ abstime->tv_nsec = usec * 1000;
+ }
return abstime;
}
@@ -5457,7 +5733,7 @@
status = os::Linux::safe_cond_timedwait(_cond, _mutex, &abst);
if (status != 0 && WorkAroundNPTLTimedWaitHang) {
pthread_cond_destroy (_cond);
- pthread_cond_init (_cond, NULL) ;
+ pthread_cond_init (_cond, os::Linux::condAttr()) ;
}
assert_status(status == 0 || status == EINTR ||
status == ETIME || status == ETIMEDOUT,
@@ -5536,7 +5812,6 @@
* is no need to track notifications.
*/
-#define MAX_SECS 100000000
/*
* This code is common to linux and solaris and will be moved to a
* common place in dolphin.
@@ -5558,32 +5833,50 @@
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
assert (time > 0, "convertTime");
-
- struct timeval now;
- int status = gettimeofday(&now, NULL);
- assert(status == 0, "gettimeofday");
-
- time_t max_secs = now.tv_sec + MAX_SECS;
-
- if (isAbsolute) {
- jlong secs = time / 1000;
- if (secs > max_secs) {
- absTime->tv_sec = max_secs;
+ time_t max_secs = 0;
+
+ if (!os::Linux::supports_monotonic_clock() || isAbsolute) {
+ struct timeval now;
+ int status = gettimeofday(&now, NULL);
+ assert(status == 0, "gettimeofday");
+
+ max_secs = now.tv_sec + MAX_SECS;
+
+ if (isAbsolute) {
+ jlong secs = time / 1000;
+ if (secs > max_secs) {
+ absTime->tv_sec = max_secs;
+ } else {
+ absTime->tv_sec = secs;
+ }
+ absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC;
+ } else {
+ jlong secs = time / NANOSECS_PER_SEC;
+ if (secs >= MAX_SECS) {
+ absTime->tv_sec = max_secs;
+ absTime->tv_nsec = 0;
+ } else {
+ absTime->tv_sec = now.tv_sec + secs;
+ absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000;
+ if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
+ absTime->tv_nsec -= NANOSECS_PER_SEC;
+ ++absTime->tv_sec; // note: this must be <= max_secs
+ }
+ }
}
- else {
- absTime->tv_sec = secs;
- }
- absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC;
- }
- else {
+ } else {
+ // must be relative using monotonic clock
+ struct timespec now;
+ int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now);
+ assert_status(status == 0, status, "clock_gettime");
+ max_secs = now.tv_sec + MAX_SECS;
jlong secs = time / NANOSECS_PER_SEC;
if (secs >= MAX_SECS) {
absTime->tv_sec = max_secs;
absTime->tv_nsec = 0;
- }
- else {
+ } else {
absTime->tv_sec = now.tv_sec + secs;
- absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000;
+ absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_nsec;
if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
absTime->tv_nsec -= NANOSECS_PER_SEC;
++absTime->tv_sec; // note: this must be <= max_secs
@@ -5662,16 +5955,20 @@
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
jt->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
-
+ assert(_cur_index == -1, "invariant");
if (time == 0) {
- status = pthread_cond_wait (_cond, _mutex) ;
+ _cur_index = REL_INDEX; // arbitrary choice when not timed
+ status = pthread_cond_wait (&_cond[_cur_index], _mutex) ;
} else {
- status = os::Linux::safe_cond_timedwait (_cond, _mutex, &absTime) ;
+ _cur_index = isAbsolute ? ABS_INDEX : REL_INDEX;
+ status = os::Linux::safe_cond_timedwait (&_cond[_cur_index], _mutex, &absTime) ;
if (status != 0 && WorkAroundNPTLTimedWaitHang) {
- pthread_cond_destroy (_cond) ;
- pthread_cond_init (_cond, NULL);
+ pthread_cond_destroy (&_cond[_cur_index]) ;
+ pthread_cond_init (&_cond[_cur_index], isAbsolute ? NULL : os::Linux::condAttr());
}
}
+ _cur_index = -1;
+
assert_status(status == 0 || status == EINTR ||
status == ETIME || status == ETIMEDOUT,
status, "cond_timedwait");
@@ -5700,17 +5997,24 @@
s = _counter;
_counter = 1;
if (s < 1) {
- if (WorkAroundNPTLTimedWaitHang) {
- status = pthread_cond_signal (_cond) ;
- assert (status == 0, "invariant") ;
+ // thread might be parked
+ if (_cur_index != -1) {
+ // thread is definitely parked
+ if (WorkAroundNPTLTimedWaitHang) {
+ status = pthread_cond_signal (&_cond[_cur_index]);
+ assert (status == 0, "invariant");
status = pthread_mutex_unlock(_mutex);
- assert (status == 0, "invariant") ;
- } else {
+ assert (status == 0, "invariant");
+ } else {
status = pthread_mutex_unlock(_mutex);
- assert (status == 0, "invariant") ;
- status = pthread_cond_signal (_cond) ;
- assert (status == 0, "invariant") ;
- }
+ assert (status == 0, "invariant");
+ status = pthread_cond_signal (&_cond[_cur_index]);
+ assert (status == 0, "invariant");
+ }
+ } else {
+ pthread_mutex_unlock(_mutex);
+ assert (status == 0, "invariant") ;
+ }
} else {
pthread_mutex_unlock(_mutex);
assert (status == 0, "invariant") ;
@@ -5926,3 +6230,149 @@
}
#endif // JAVASE_EMBEDDED
+
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+#define test_log(...) \
+ do {\
+ if (VerboseInternalVMTests) { \
+ tty->print_cr(__VA_ARGS__); \
+ tty->flush(); \
+ }\
+ } while (false)
+
+class TestReserveMemorySpecial : AllStatic {
+ public:
+ static void small_page_write(void* addr, size_t size) {
+ size_t page_size = os::vm_page_size();
+
+ char* end = (char*)addr + size;
+ for (char* p = (char*)addr; p < end; p += page_size) {
+ *p = 1;
+ }
+ }
+
+ static void test_reserve_memory_special_huge_tlbfs_only(size_t size) {
+ if (!UseHugeTLBFS) {
+ return;
+ }
+
+ test_log("test_reserve_memory_special_huge_tlbfs_only(" SIZE_FORMAT ")", size);
+
+ char* addr = os::Linux::reserve_memory_special_huge_tlbfs_only(size, NULL, false);
+
+ if (addr != NULL) {
+ small_page_write(addr, size);
+
+ os::Linux::release_memory_special_huge_tlbfs(addr, size);
+ }
+ }
+
+ static void test_reserve_memory_special_huge_tlbfs_only() {
+ if (!UseHugeTLBFS) {
+ return;
+ }
+
+ size_t lp = os::large_page_size();
+
+ for (size_t size = lp; size <= lp * 10; size += lp) {
+ test_reserve_memory_special_huge_tlbfs_only(size);
+ }
+ }
+
+ static void test_reserve_memory_special_huge_tlbfs_mixed(size_t size, size_t alignment) {
+ if (!UseHugeTLBFS) {
+ return;
+ }
+
+ test_log("test_reserve_memory_special_huge_tlbfs_mixed(" SIZE_FORMAT ", " SIZE_FORMAT ")",
+ size, alignment);
+
+ assert(size >= os::large_page_size(), "Incorrect input to test");
+
+ char* addr = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, NULL, false);
+
+ if (addr != NULL) {
+ small_page_write(addr, size);
+
+ os::Linux::release_memory_special_huge_tlbfs(addr, size);
+ }
+ }
+
+ static void test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(size_t size) {
+ size_t lp = os::large_page_size();
+ size_t ag = os::vm_allocation_granularity();
+
+ for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) {
+ test_reserve_memory_special_huge_tlbfs_mixed(size, alignment);
+ }
+ }
+
+ static void test_reserve_memory_special_huge_tlbfs_mixed() {
+ size_t lp = os::large_page_size();
+ size_t ag = os::vm_allocation_granularity();
+
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp + ag);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp + lp / 2);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 + ag);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 - ag);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 + lp / 2);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 10);
+ test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 10 + lp / 2);
+ }
+
+ static void test_reserve_memory_special_huge_tlbfs() {
+ if (!UseHugeTLBFS) {
+ return;
+ }
+
+ test_reserve_memory_special_huge_tlbfs_only();
+ test_reserve_memory_special_huge_tlbfs_mixed();
+ }
+
+ static void test_reserve_memory_special_shm(size_t size, size_t alignment) {
+ if (!UseSHM) {
+ return;
+ }
+
+ test_log("test_reserve_memory_special_shm(" SIZE_FORMAT ", " SIZE_FORMAT ")", size, alignment);
+
+ char* addr = os::Linux::reserve_memory_special_shm(size, alignment, NULL, false);
+
+ if (addr != NULL) {
+ assert(is_ptr_aligned(addr, alignment), "Check");
+ assert(is_ptr_aligned(addr, os::large_page_size()), "Check");
+
+ small_page_write(addr, size);
+
+ os::Linux::release_memory_special_shm(addr, size);
+ }
+ }
+
+ static void test_reserve_memory_special_shm() {
+ size_t lp = os::large_page_size();
+ size_t ag = os::vm_allocation_granularity();
+
+ for (size_t size = ag; size < lp * 3; size += ag) {
+ for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) {
+ test_reserve_memory_special_shm(size, alignment);
+ }
+ }
+ }
+
+ static void test() {
+ test_reserve_memory_special_huge_tlbfs();
+ test_reserve_memory_special_shm();
+ }
+};
+
+void TestReserveMemorySpecial_test() {
+ TestReserveMemorySpecial::test();
+}
+
+#endif
--- ./hotspot/src/os/linux/vm/os_linux.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/linux/vm/os_linux.hpp Wed May 07 19:26:16 2014 -0700
@@ -32,6 +32,7 @@
class Linux {
friend class os;
+ friend class TestReserveMemorySpecial;
// For signal-chaining
#define MAXSIGNUM 32
@@ -92,15 +93,27 @@
static void rebuild_cpu_to_node_map();
static GrowableArray* cpu_to_node() { return _cpu_to_node; }
+ static size_t find_large_page_size();
+ static size_t setup_large_page_size();
+
+ static bool setup_large_page_type(size_t page_size);
+ static bool transparent_huge_pages_sanity_check(bool warn, size_t pages_size);
static bool hugetlbfs_sanity_check(bool warn, size_t page_size);
+ static char* reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec);
+ static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, char* req_addr, bool exec);
+ static char* reserve_memory_special_huge_tlbfs_only(size_t bytes, char* req_addr, bool exec);
+ static char* reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t alignment, char* req_addr, bool exec);
+
+ static bool release_memory_special_shm(char* base, size_t bytes);
+ static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);
+
static void print_full_memory_info(outputStream* st);
static void print_distro_info(outputStream* st);
static void print_libversion_info(outputStream* st);
public:
static bool _stack_is_executable;
- static volatile jint num_largepage_commit_fails;
static void *dlopen_helper(const char *name, char *ebuf, int ebuflen);
static void *dll_load_in_vmthread(const char *name, char *ebuf, int ebuflen);
@@ -208,6 +221,13 @@
static jlong fast_thread_cpu_time(clockid_t clockid);
+ // pthread_cond clock suppport
+ private:
+ static pthread_condattr_t _condattr[1];
+
+ public:
+ static pthread_condattr_t* condAttr() { return _condattr; }
+
// Stack repair handling
// none present
@@ -274,7 +294,7 @@
public:
PlatformEvent() {
int status;
- status = pthread_cond_init (_cond, NULL);
+ status = pthread_cond_init (_cond, os::Linux::condAttr());
assert_status(status == 0, status, "cond_init");
status = pthread_mutex_init (_mutex, NULL);
assert_status(status == 0, status, "mutex_init");
@@ -289,14 +309,19 @@
void park () ;
void unpark () ;
int TryPark () ;
- int park (jlong millis) ;
+ int park (jlong millis) ; // relative timed-wait only
void SetAssociation (Thread * a) { _Assoc = a ; }
} ;
class PlatformParker : public CHeapObj {
protected:
+ enum {
+ REL_INDEX = 0,
+ ABS_INDEX = 1
+ };
+ int _cur_index; // which cond is in use: -1, 0, 1
pthread_mutex_t _mutex [1] ;
- pthread_cond_t _cond [1] ;
+ pthread_cond_t _cond [2] ; // one for relative times and one for abs.
public: // TODO-FIXME: make dtor private
~PlatformParker() { guarantee (0, "invariant") ; }
@@ -304,10 +329,13 @@
public:
PlatformParker() {
int status;
- status = pthread_cond_init (_cond, NULL);
- assert_status(status == 0, status, "cond_init");
+ status = pthread_cond_init (&_cond[REL_INDEX], os::Linux::condAttr());
+ assert_status(status == 0, status, "cond_init rel");
+ status = pthread_cond_init (&_cond[ABS_INDEX], NULL);
+ assert_status(status == 0, status, "cond_init abs");
status = pthread_mutex_init (_mutex, NULL);
assert_status(status == 0, status, "mutex_init");
+ _cur_index = -1; // mark as unused
}
};
--- ./hotspot/src/os/posix/vm/os_posix.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/posix/vm/os_posix.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 1999, 2013, 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
@@ -30,6 +30,8 @@
#include
#include
#include
+#include
+#include
// Check core dump limit and report possible place where core can be found
@@ -203,11 +205,17 @@
* The callback is supposed to provide the method that should be protected.
*/
bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) {
+ sigset_t saved_sig_mask;
+
assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread");
assert(!WatcherThread::watcher_thread()->has_crash_protection(),
"crash_protection already set?");
- if (sigsetjmp(_jmpbuf, 1) == 0) {
+ // we cannot rely on sigsetjmp/siglongjmp to save/restore the signal mask
+ // since on at least some systems (OS X) siglongjmp will restore the mask
+ // for the process, not the thread
+ pthread_sigmask(0, NULL, &saved_sig_mask);
+ if (sigsetjmp(_jmpbuf, 0) == 0) {
// make sure we can see in the signal handler that we have crash protection
// installed
WatcherThread::watcher_thread()->set_crash_protection(this);
@@ -217,6 +225,7 @@
return true;
}
// this happens when we siglongjmp() back
+ pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
WatcherThread::watcher_thread()->set_crash_protection(NULL);
return false;
}
--- ./hotspot/src/os/solaris/vm/os_solaris.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/solaris/vm/os_solaris.cpp Wed May 07 19:26:16 2014 -0700
@@ -3530,11 +3530,15 @@
return true;
}
-char* os::reserve_memory_special(size_t size, char* addr, bool exec) {
+char* os::reserve_memory_special(size_t size, size_t alignment, char* addr, bool exec) {
// "exec" is passed in but not used. Creating the shared image for
// the code cache doesn't have an SHM_X executable permission to check.
assert(UseLargePages && UseISM, "only for ISM large pages");
+ if (!is_size_aligned(size, os::large_page_size()) || alignment > os::large_page_size()) {
+ return NULL; // Fallback to small pages.
+ }
+
char* retAddr = NULL;
int shmid;
key_t ismKey;
@@ -6862,3 +6866,9 @@
return strlen(buffer);
}
+
+#ifndef PRODUCT
+void TestReserveMemorySpecial_test() {
+ // No tests available for this platform
+}
+#endif
--- ./hotspot/src/os/windows/vm/os_windows.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os/windows/vm/os_windows.cpp Wed May 07 19:26:16 2014 -0700
@@ -800,15 +800,21 @@
return result;
}
-// For now, we say that Windows does not support vtime. I have no idea
-// whether it can actually be made to (DLD, 9/13/05).
-
-bool os::supports_vtime() { return false; }
+bool os::supports_vtime() { return true; }
bool os::enable_vtime() { return false; }
bool os::vtime_enabled() { return false; }
+
double os::elapsedVTime() {
- // better than nothing, but not much
- return elapsedTime();
+ FILETIME created;
+ FILETIME exited;
+ FILETIME kernel;
+ FILETIME user;
+ if (GetThreadTimes(GetCurrentThread(), &created, &exited, &kernel, &user) != 0) {
+ // the resolution of windows_to_java_time() should be sufficient (ms)
+ return (double) (windows_to_java_time(kernel) + windows_to_java_time(user)) / MILLIUNITS;
+ } else {
+ return elapsedTime();
+ }
}
jlong os::javaTimeMillis() {
@@ -3088,7 +3094,12 @@
return true;
}
-char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) {
+char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, bool exec) {
+ assert(UseLargePages, "only for large pages");
+
+ if (!is_size_aligned(bytes, os::large_page_size()) || alignment > os::large_page_size()) {
+ return NULL; // Fallback to small pages.
+ }
const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
@@ -5593,3 +5604,9 @@
}
#endif
+
+#ifndef PRODUCT
+void TestReserveMemorySpecial_test() {
+ // No tests available for this platform
+}
+#endif
--- ./hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed May 07 19:26:16 2014 -0700
@@ -873,3 +873,46 @@
#endif
}
#endif
+
+
+/*
+ * IA32 only: execute code at a high address in case buggy NX emulation is present. I.e. avoid CS limit
+ * updates (JDK-8023956).
+ */
+void os::workaround_expand_exec_shield_cs_limit() {
+#if defined(IA32)
+ size_t page_size = os::vm_page_size();
+ /*
+ * Take the highest VA the OS will give us and exec
+ *
+ * Although using -(pagesz) as mmap hint works on newer kernel as you would
+ * think, older variants affected by this work-around don't (search forward only).
+ *
+ * On the affected distributions, we understand the memory layout to be:
+ *
+ * TASK_LIMIT= 3G, main stack base close to TASK_LIMT.
+ *
+ * A few pages south main stack will do it.
+ *
+ * If we are embedded in an app other than launcher (initial != main stack),
+ * we don't have much control or understanding of the address space, just let it slide.
+ */
+ char* hint = (char*) (Linux::initial_thread_stack_bottom() -
+ ((StackYellowPages + StackRedPages + 1) * page_size));
+ char* codebuf = os::reserve_memory(page_size, hint);
+ if ( (codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true)) ) {
+ return; // No matter, we tried, best effort.
+ }
+ if (PrintMiscellaneous && (Verbose || WizardMode)) {
+ tty->print_cr("[CS limit NX emulation work-around, exec code at: %p]", codebuf);
+ }
+
+ // Some code to exec: the 'ret' instruction
+ codebuf[0] = 0xC3;
+
+ // Call the code in the codebuf
+ __asm__ volatile("call *%0" : : "r"(codebuf));
+
+ // keep the page mapped so CS limit isn't reduced.
+#endif
+}
--- ./hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.hpp Wed May 07 19:26:16 2014 -0700
@@ -36,4 +36,17 @@
// Note: Currently only used in 64 bit Windows implementations
static bool register_code_area(char *low, char *high) { return true; }
+ /*
+ * Work-around for broken NX emulation using CS limit, Red Hat patch "Exec-Shield"
+ * (IA32 only).
+ *
+ * Map and execute at a high VA to prevent CS lazy updates race with SMP MM
+ * invalidation.Further code generation by the JVM will no longer cause CS limit
+ * updates.
+ *
+ * Affects IA32: RHEL 5 & 6, Ubuntu 10.04 (LTS), 10.10, 11.04, 11.10, 12.04.
+ * @see JDK-8023956
+ */
+ static void workaround_expand_exec_shield_cs_limit();
+
#endif // OS_CPU_LINUX_X86_VM_OS_LINUX_X86_HPP
--- ./hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed May 07 19:26:16 2014 -0700
@@ -4178,7 +4178,9 @@
}
}
- if (!PrintInlining) return;
+ if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
+ return;
+ }
CompileTask::print_inlining(callee, scope()->level(), bci(), msg);
if (success && CIPrintMethodCodes) {
callee->print_codes();
--- ./hotspot/src/share/vm/c1/c1_LIR.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/c1/c1_LIR.hpp Wed May 07 19:26:16 2014 -0700
@@ -2221,7 +2221,7 @@
typedef enum { inputMode, firstMode = inputMode, tempMode, outputMode, numModes, invalidMode = -1 } OprMode;
enum {
- maxNumberOfOperands = 16,
+ maxNumberOfOperands = 20,
maxNumberOfInfos = 4
};
--- ./hotspot/src/share/vm/c1/c1_LinearScan.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed May 07 19:26:16 2014 -0700
@@ -1138,8 +1138,10 @@
}
}
}
-
- } else if (opr_type != T_LONG) {
+ // We want to sometimes use logical operations on pointers, in particular in GC barriers.
+ // Since 64bit logical operations do not current support operands on stack, we have to make sure
+ // T_OBJECT doesn't get spilled along with T_LONG.
+ } else if (opr_type != T_LONG LP64_ONLY(&& opr_type != T_OBJECT)) {
// integer instruction (note: long operands must always be in register)
switch (op->code()) {
case lir_cmp:
--- ./hotspot/src/share/vm/c1/c1_Runtime1.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed May 07 19:26:16 2014 -0700
@@ -911,16 +911,6 @@
// Return to the now deoptimized frame.
}
- // If we are patching in a non-perm oop, make sure the nmethod
- // is on the right list.
- if (ScavengeRootsInCode && load_klass.not_null() && load_klass->is_scavengable()) {
- MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
- nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
- guarantee(nm != NULL, "only nmethods can contain non-perm oops");
- if (!nm->on_scavenge_root_list())
- CodeCache::add_scavenge_root_nmethod(nm);
- }
-
// Now copy code back
{
@@ -1096,6 +1086,22 @@
}
}
}
+
+
+ // If we are patching in a non-perm oop, make sure the nmethod
+ // is on the right list.
+ if (ScavengeRootsInCode && load_klass.not_null() && load_klass->is_scavengable()) {
+ MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
+ guarantee(nm != NULL, "only nmethods can contain non-perm oops");
+ if (!nm->on_scavenge_root_list()) {
+ CodeCache::add_scavenge_root_nmethod(nm);
+ }
+
+ // Since we've patched some oops in the nmethod,
+ // (re)register it with the heap.
+ Universe::heap()->register_nmethod(nm);
+ }
JRT_END
//
--- ./hotspot/src/share/vm/classfile/classFileParser.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/classFileParser.cpp Wed May 07 19:26:16 2014 -0700
@@ -4056,8 +4056,8 @@
for (int index = 0; index < num_methods; index++) {
methodOop m = (methodOop)methods->obj_at(index);
- // skip static and methods
- if ((!m->is_static()) &&
+ // skip private, static, and methods
+ if ((!m->is_private() && !m->is_static()) &&
(m->name() != vmSymbols::object_initializer_name())) {
Symbol* name = m->name();
--- ./hotspot/src/share/vm/classfile/javaClasses.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/javaClasses.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -2388,6 +2388,26 @@
*offset = value;
}
+// Support for java_lang_invoke_DirectMethodHandle
+
+int java_lang_invoke_DirectMethodHandle::_member_offset;
+
+oop java_lang_invoke_DirectMethodHandle::member(oop dmh) {
+ oop member_name = NULL;
+ bool is_dmh = dmh->is_oop() && java_lang_invoke_DirectMethodHandle::is_instance(dmh);
+ assert(is_dmh, "a DirectMethodHandle oop is expected");
+ if (is_dmh) {
+ member_name = dmh->obj_field(member_offset_in_bytes());
+ }
+ return member_name;
+}
+
+void java_lang_invoke_DirectMethodHandle::compute_offsets() {
+ klassOop klass_oop = SystemDictionary::DirectMethodHandle_klass();
+ if (klass_oop != NULL && EnableInvokeDynamic) {
+ compute_offset(_member_offset, klass_oop, vmSymbols::member_name(), vmSymbols::java_lang_invoke_MemberName_signature());
+ }
+}
// Support for java_lang_invoke_MethodHandle
@@ -2497,6 +2517,13 @@
return mname->obj_field(_vmtarget_offset);
}
+// Can be executed on VM thread only
+void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, oop ref) {
+ assert((is_instance(mname) && (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0), "wrong type");
+ assert(Thread::current()->is_VM_thread(), "not VM thread");
+ mname->address_field_put(_vmtarget_offset, (address)ref);
+}
+
void java_lang_invoke_MemberName::set_vmtarget(oop mname, oop ref) {
assert(is_instance(mname), "wrong type");
#ifdef ASSERT
@@ -3000,6 +3027,7 @@
java_lang_ThreadGroup::compute_offsets();
if (EnableInvokeDynamic) {
java_lang_invoke_MethodHandle::compute_offsets();
+ java_lang_invoke_DirectMethodHandle::compute_offsets();
java_lang_invoke_MemberName::compute_offsets();
java_lang_invoke_LambdaForm::compute_offsets();
java_lang_invoke_MethodType::compute_offsets();
--- ./hotspot/src/share/vm/classfile/javaClasses.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/javaClasses.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -915,6 +915,32 @@
static int form_offset_in_bytes() { return _form_offset; }
};
+// Interface to java.lang.invoke.DirectMethodHandle objects
+
+class java_lang_invoke_DirectMethodHandle: AllStatic {
+ friend class JavaClasses;
+
+ private:
+ static int _member_offset; // the MemberName of this DMH
+
+ static void compute_offsets();
+
+ public:
+ // Accessors
+ static oop member(oop mh);
+
+ // Testers
+ static bool is_subclass(klassOop klass) {
+ return Klass::cast(klass)->is_subclass_of(SystemDictionary::DirectMethodHandle_klass());
+ }
+ static bool is_instance(oop obj) {
+ return obj != NULL && is_subclass(obj->klass());
+ }
+
+ // Accessors for code generation:
+ static int member_offset_in_bytes() { return _member_offset; }
+};
+
// Interface to java.lang.invoke.LambdaForm objects
// (These are a private interface for managing adapter code generation.)
@@ -988,6 +1014,7 @@
static oop vmtarget(oop mname);
static void set_vmtarget(oop mname, oop target);
+ static void adjust_vmtarget(oop mname, oop target);
static intptr_t vmindex(oop mname);
static void set_vmindex(oop mname, intptr_t index);
--- ./hotspot/src/share/vm/classfile/symbolTable.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/symbolTable.cpp Wed May 07 19:26:16 2014 -0700
@@ -39,6 +39,9 @@
// --------------------------------------------------------------------------
+// the number of buckets a thread claims
+const int ClaimChunkSize = 32;
+
SymbolTable* SymbolTable::_the_table = NULL;
// Static arena for symbols that are not deallocated
Arena* SymbolTable::_arena = NULL;
@@ -81,16 +84,12 @@
}
}
-int SymbolTable::symbols_removed = 0;
-int SymbolTable::symbols_counted = 0;
+int SymbolTable::_symbols_removed = 0;
+int SymbolTable::_symbols_counted = 0;
+volatile int SymbolTable::_parallel_claimed_idx = 0;
-// Remove unreferenced symbols from the symbol table
-// This is done late during GC.
-void SymbolTable::unlink() {
- int removed = 0;
- int total = 0;
- size_t memory_total = 0;
- for (int i = 0; i < the_table()->table_size(); ++i) {
+void SymbolTable::buckets_unlink(int start_idx, int end_idx, int* processed, int* removed, size_t* memory_total) {
+ for (int i = start_idx; i < end_idx; ++i) {
HashtableEntry** p = the_table()->bucket_addr(i);
HashtableEntry* entry = the_table()->bucket(i);
while (entry != NULL) {
@@ -102,14 +101,14 @@
break;
}
Symbol* s = entry->literal();
- memory_total += s->object_size();
- total++;
+ (*memory_total) += s->object_size();
+ (*processed)++;
assert(s != NULL, "just checking");
// If reference count is zero, remove.
if (s->refcount() == 0) {
assert(!entry->is_shared(), "shared entries should be kept live");
delete s;
- removed++;
+ (*removed)++;
*p = entry->next();
the_table()->free_entry(entry);
} else {
@@ -119,12 +118,45 @@
entry = (HashtableEntry*)HashtableEntry::make_ptr(*p);
}
}
- symbols_removed += removed;
- symbols_counted += total;
+}
+
+// Remove unreferenced symbols from the symbol table
+// This is done late during GC.
+void SymbolTable::unlink(int* processed, int* removed) {
+ size_t memory_total = 0;
+ buckets_unlink(0, the_table()->table_size(), processed, removed, &memory_total);
+ _symbols_removed += *removed;
+ _symbols_counted += *processed;
// Exclude printing for normal PrintGCDetails because people parse
// this output.
if (PrintGCDetails && Verbose && WizardMode) {
- gclog_or_tty->print(" [Symbols=%d size=" SIZE_FORMAT "K] ", total,
+ gclog_or_tty->print(" [Symbols=%d size=" SIZE_FORMAT "K] ", *processed,
+ (memory_total*HeapWordSize)/1024);
+ }
+}
+
+void SymbolTable::possibly_parallel_unlink(int* processed, int* removed) {
+ const int limit = the_table()->table_size();
+
+ size_t memory_total = 0;
+
+ for (;;) {
+ // Grab next set of buckets to scan
+ int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
+ if (start_idx >= limit) {
+ // End of table
+ break;
+ }
+
+ int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
+ buckets_unlink(start_idx, end_idx, processed, removed, &memory_total);
+ }
+ Atomic::add(*processed, &_symbols_counted);
+ Atomic::add(*removed, &_symbols_removed);
+ // Exclude printing for normal PrintGCDetails because people parse
+ // this output.
+ if (PrintGCDetails && Verbose && WizardMode) {
+ gclog_or_tty->print(" [Symbols: scanned=%d removed=%d size=" SIZE_FORMAT "K] ", *processed, *removed,
(memory_total*HeapWordSize)/1024);
}
}
@@ -503,21 +535,21 @@
}
}
tty->print_cr("Symbol Table:");
- tty->print_cr("Total number of symbols %5d", count);
- tty->print_cr("Total size in memory %5dK",
+ tty->print_cr("Total number of symbols "INT32_FORMAT, count);
+ tty->print_cr("Total size in memory "INT32_FORMAT"K",
(memory_total*HeapWordSize)/1024);
- tty->print_cr("Total counted %5d", symbols_counted);
- tty->print_cr("Total removed %5d", symbols_removed);
- if (symbols_counted > 0) {
+ tty->print_cr("Total counted "INT32_FORMAT, _symbols_counted);
+ tty->print_cr("Total removed "INT32_FORMAT, _symbols_removed);
+ if (_symbols_counted > 0) {
tty->print_cr("Percent removed %3.2f",
- ((float)symbols_removed/(float)symbols_counted)* 100);
+ ((float)_symbols_removed/(float)_symbols_counted)* 100);
}
- tty->print_cr("Reference counts %5d", Symbol::_total_count);
- tty->print_cr("Symbol arena size %5d used %5d",
+ tty->print_cr("Reference counts "INT32_FORMAT, Symbol::_total_count);
+ tty->print_cr("Symbol arena size "SIZE_FORMAT" used "SIZE_FORMAT,
arena()->size_in_bytes(), arena()->used());
tty->print_cr("Histogram of symbol length:");
- tty->print_cr("%8s %5d", "Total ", total);
- tty->print_cr("%8s %5d", "Maximum", max_symbols);
+ tty->print_cr("%8s "INT32_FORMAT, "Total ", total);
+ tty->print_cr("%8s "INT32_FORMAT, "Maximum", max_symbols);
tty->print_cr("%8s %3.2f", "Average",
((float) total / (float) the_table()->table_size()));
tty->print_cr("%s", "Histogram:");
@@ -746,11 +778,41 @@
return result;
}
-void StringTable::unlink(BoolObjectClosure* is_alive) {
+void StringTable::unlink(BoolObjectClosure* is_alive, int* processed, int* removed) {
+ buckets_unlink(is_alive, 0, the_table()->table_size(), processed, removed);
+}
+
+void StringTable::possibly_parallel_unlink(BoolObjectClosure* is_alive, int* processed, int* removed) {
// Readers of the table are unlocked, so we should only be removing
// entries at a safepoint.
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- for (int i = 0; i < the_table()->table_size(); ++i) {
+ const int limit = the_table()->table_size();
+
+ for (;;) {
+ // Grab next set of buckets to scan
+ int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
+ if (start_idx >= limit) {
+ // End of table
+ break;
+ }
+
+ int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
+ buckets_unlink(is_alive, start_idx, end_idx, processed, removed);
+ }
+}
+
+void StringTable::buckets_unlink(BoolObjectClosure* is_alive, int start_idx, int end_idx, int* processed, int* removed) {
+ const int limit = the_table()->table_size();
+
+ assert(0 <= start_idx && start_idx <= limit,
+ err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx));
+ assert(0 <= end_idx && end_idx <= limit,
+ err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx));
+ assert(start_idx <= end_idx,
+ err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
+ start_idx, end_idx));
+
+ for (int i = start_idx; i < end_idx; ++i) {
HashtableEntry** p = the_table()->bucket_addr(i);
HashtableEntry* entry = the_table()->bucket(i);
while (entry != NULL) {
@@ -767,24 +829,26 @@
} else {
*p = entry->next();
the_table()->free_entry(entry);
+ (*removed)++;
}
+ (*processed)++;
entry = (HashtableEntry*)HashtableEntry::make_ptr(*p);
}
}
}
-void StringTable::buckets_do(OopClosure* f, int start_idx, int end_idx) {
+void StringTable::buckets_oops_do(OopClosure* f, int start_idx, int end_idx) {
const int limit = the_table()->table_size();
assert(0 <= start_idx && start_idx <= limit,
- err_msg("start_idx (" INT32_FORMAT ") oob?", start_idx));
+ err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx));
assert(0 <= end_idx && end_idx <= limit,
- err_msg("end_idx (" INT32_FORMAT ") oob?", end_idx));
+ err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx));
assert(start_idx <= end_idx,
- err_msg("Ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
+ err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
start_idx, end_idx));
- for (int i = start_idx; i < end_idx; i += 1) {
+ for (int i = start_idx; i < end_idx; i++) {
HashtableEntry** p = the_table()->bucket_addr(i);
HashtableEntry* entry = the_table()->bucket(i);
while (entry != NULL) {
@@ -804,11 +868,10 @@
}
void StringTable::oops_do(OopClosure* f) {
- buckets_do(f, 0, the_table()->table_size());
+ buckets_oops_do(f, 0, the_table()->table_size());
}
void StringTable::possibly_parallel_oops_do(OopClosure* f) {
- const int ClaimChunkSize = 32;
const int limit = the_table()->table_size();
for (;;) {
@@ -820,7 +883,7 @@
}
int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
- buckets_do(f, start_idx, end_idx);
+ buckets_oops_do(f, start_idx, end_idx);
}
}
--- ./hotspot/src/share/vm/classfile/symbolTable.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/symbolTable.hpp Wed May 07 19:26:16 2014 -0700
@@ -86,8 +86,8 @@
static bool _needs_rehashing;
// For statistics
- static int symbols_removed;
- static int symbols_counted;
+ static int _symbols_removed;
+ static int _symbols_counted;
Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
@@ -126,6 +126,11 @@
static Arena* arena() { return _arena; } // called for statistics
static void initialize_symbols(int arena_alloc_size = 0);
+
+ static volatile int _parallel_claimed_idx;
+
+ // Release any dead symbols
+ static void buckets_unlink(int start_idx, int end_idx, int* processed, int* removed, size_t* memory_total);
public:
enum {
symbol_alloc_batch_size = 8,
@@ -175,7 +180,19 @@
unsigned int* hashValues, TRAPS);
// Release any dead symbols
- static void unlink();
+ static void unlink() {
+ int processed = 0;
+ int removed = 0;
+ unlink(&processed, &removed);
+ }
+ static void unlink(int* processed, int* removed);
+ // Release any dead symbols, possibly parallel version
+ static void possibly_parallel_unlink() {
+ int processed = 0;
+ int removed = 0;
+ possibly_parallel_unlink(&processed, &removed);
+ }
+ static void possibly_parallel_unlink(int* processed, int* removed);
// iterate over symbols
static void symbols_do(SymbolClosure *cl);
@@ -233,6 +250,9 @@
// Rehash the symbol table if it gets out of balance
static void rehash_table();
static bool needs_rehashing() { return _needs_rehashing; }
+ // Parallel chunked scanning
+ static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
+ static int parallel_claimed_index() { return _parallel_claimed_idx; }
};
class StringTable : public Hashtable {
@@ -256,7 +276,9 @@
// Apply the give oop closure to the entries to the buckets
// in the range [start_idx, end_idx).
- static void buckets_do(OopClosure* f, int start_idx, int end_idx);
+ static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx);
+ // Unlink the entries to the buckets in the range [start_idx, end_idx).
+ static void buckets_unlink(BoolObjectClosure* is_alive, int start_idx, int end_idx, int* processed, int* removed);
StringTable() : Hashtable((int)StringTableSize,
sizeof (HashtableEntry)) {}
@@ -283,7 +305,13 @@
// GC support
// Delete pointers to otherwise-unreachable objects.
- static void unlink(BoolObjectClosure* cl);
+ static void unlink(BoolObjectClosure* cl) {
+ int processed = 0;
+ int removed = 0;
+ unlink(cl, &processed, &removed);
+ }
+
+ static void unlink(BoolObjectClosure* cl, int* processed, int* removed);
// Serially invoke "f->do_oop" on the locations of all oops in the table.
static void oops_do(OopClosure* f);
@@ -291,6 +319,8 @@
// Possibly parallel version of the above
static void possibly_parallel_oops_do(OopClosure* f);
+ static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed);
+
// Hashing algorithm, used as the hash value used by the
// StringTable for bucket selection and comparison (stored in the
// HashtableEntry structures). This is used in the String.intern() method.
@@ -328,5 +358,6 @@
// Parallel chunked scanning
static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
+ static int parallel_claimed_index() { return _parallel_claimed_idx; }
};
#endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
--- ./hotspot/src/share/vm/classfile/systemDictionary.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/systemDictionary.cpp Wed May 07 19:26:16 2014 -0700
@@ -585,7 +585,7 @@
assert(name != NULL && !FieldType::is_array(name) &&
!FieldType::is_obj(name), "invalid class name");
- TracingTime class_load_start_time = Tracing::time();
+ const Ticks class_load_start_time = Ticks::now();
// UseNewReflection
// Fix for 4474172; see evaluation for more details
@@ -946,7 +946,7 @@
TRAPS) {
TempNewSymbol parsed_name = NULL;
- TracingTime class_load_start_time = Tracing::time();
+ const Ticks class_load_start_time = Ticks::now();
// Parse the stream. Note that we do this even though this klass might
// already be present in the SystemDictionary, otherwise we would not
@@ -1572,9 +1572,10 @@
// Used for assertions and verification only
klassOop SystemDictionary::find_class(Symbol* class_name, Handle class_loader) {
#ifndef ASSERT
- guarantee(VerifyBeforeGC ||
- VerifyDuringGC ||
- VerifyBeforeExit ||
+ guarantee(VerifyBeforeGC ||
+ VerifyDuringGC ||
+ VerifyBeforeExit ||
+ VerifyDuringStartup ||
VerifyAfterGC, "too expensive");
#endif
assert_locked_or_safepoint(SystemDictionary_lock);
@@ -2314,6 +2315,11 @@
objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
assert(appendix_box->obj_at(0) == NULL, "");
+ // This should not happen. JDK code should take care of that.
+ if (accessing_klass.is_null() || method_type.is_null()) {
+ THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokehandle", empty);
+ }
+
// call java.lang.invoke.MethodHandleNatives::linkMethod(... String, MethodType) -> MemberName
JavaCallArguments args;
args.push_oop(accessing_klass()->java_mirror());
@@ -2439,6 +2445,9 @@
Handle type;
if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
type = find_method_handle_type(signature, caller, CHECK_(empty));
+ } else if (caller.is_null()) {
+ // This should not happen. JDK code should take care of that.
+ THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad MH constant", empty);
} else {
ResourceMark rm(THREAD);
SignatureStream ss(signature, false);
@@ -2502,6 +2511,11 @@
Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
Handle method_type = find_method_handle_type(type, caller, CHECK_(empty));
+ // This should not happen. JDK code should take care of that.
+ if (caller.is_null() || method_type.is_null()) {
+ THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty);
+ }
+
objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
assert(appendix_box->obj_at(0) == NULL, "");
@@ -2607,13 +2621,12 @@
}
// utility function for posting class load event
-void SystemDictionary::post_class_load_event(TracingTime start_time,
+void SystemDictionary::post_class_load_event(const Ticks& start_time,
instanceKlassHandle k,
Handle initiating_loader) {
#if INCLUDE_TRACE
EventClassLoad event(UNTIMED);
if (event.should_commit()) {
- event.set_endtime(Tracing::time());
event.set_starttime(start_time);
event.set_loadedClass(k());
oop defining_class_loader = k->class_loader();
@@ -2632,7 +2645,7 @@
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
if (Tracing::enabled()) {
_should_write_unload_events = Tracing::is_event_enabled(TraceClassUnloadEvent);
- _class_unload_time = Tracing::time();
+ _class_unload_time = Ticks::now();
_is_alive = is_alive;
classes_do(&class_unload_event);
@@ -2648,7 +2661,7 @@
#if INCLUDE_TRACE
-TracingTime SystemDictionary::_class_unload_time;
+Ticks SystemDictionary::_class_unload_time;
BoolObjectClosure* SystemDictionary::_is_alive = NULL;
int SystemDictionary::_no_of_classes_unloading = 0;
bool SystemDictionary::_should_write_unload_events = false;
--- ./hotspot/src/share/vm/classfile/systemDictionary.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/systemDictionary.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -33,7 +33,7 @@
#include "runtime/reflectionUtils.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/hashtable.inline.hpp"
-#include "trace/traceTime.hpp"
+#include "utilities/ticks.hpp"
// The system dictionary stores all loaded classes and maps:
//
@@ -151,6 +151,7 @@
do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292 ) \
do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292 ) \
do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt ) \
+ do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle, Opt ) \
do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292 ) \
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292 ) \
do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292 ) \
@@ -616,7 +617,7 @@
static void add_to_hierarchy(instanceKlassHandle k, TRAPS);
// event based tracing
- static void post_class_load_event(TracingTime start_time, instanceKlassHandle k,
+ static void post_class_load_event(const Ticks& start_time, instanceKlassHandle k,
Handle initiating_loader);
static void post_class_unload_events(BoolObjectClosure* is_alive);
@@ -678,7 +679,7 @@
static bool _has_checkPackageAccess;
#if INCLUDE_TRACE
- static TracingTime _class_unload_time;
+ static Ticks _class_unload_time;
static BoolObjectClosure* _is_alive;
static int _no_of_classes_unloading;
static bool _should_write_unload_events;
--- ./hotspot/src/share/vm/classfile/vmSymbols.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/classfile/vmSymbols.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -243,6 +243,7 @@
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \
template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \
+ template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \
template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \
template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \
template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \
@@ -338,6 +339,7 @@
template(thread_id_name, "tid") \
template(newInstance0_name, "newInstance0") \
template(limit_name, "limit") \
+ template(member_name, "member") \
template(forName_name, "forName") \
template(forName0_name, "forName0") \
template(isJavaIdentifierStart_name, "isJavaIdentifierStart") \
--- ./hotspot/src/share/vm/code/nmethod.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/code/nmethod.cpp Wed May 07 19:26:16 2014 -0700
@@ -676,6 +676,7 @@
code_buffer->copy_oops_to(this);
if (ScavengeRootsInCode && detect_scavenge_root_oops()) {
CodeCache::add_scavenge_root_nmethod(this);
+ Universe::heap()->register_nmethod(this);
}
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
@@ -869,6 +870,7 @@
dependencies->copy_to(this);
if (ScavengeRootsInCode && detect_scavenge_root_oops()) {
CodeCache::add_scavenge_root_nmethod(this);
+ Universe::heap()->register_nmethod(this);
}
debug_only(verify_scavenge_root_oops());
@@ -1282,6 +1284,13 @@
methodHandle the_method(method());
No_Safepoint_Verifier nsv;
+ // during patching, depending on the nmethod state we must notify the GC that
+ // code has been unloaded, unregistering it. We cannot do this right while
+ // holding the Patching_lock because we need to use the CodeCache_lock. This
+ // would be prone to deadlocks.
+ // This flag is used to remember whether we need to later lock and unregister.
+ bool nmethod_needs_unregister = false;
+
{
// invalidate osr nmethod before acquiring the patching lock since
// they both acquire leaf locks and we don't want a deadlock.
@@ -1314,6 +1323,13 @@
inc_decompile_count();
}
+ // If the state is becoming a zombie, signal to unregister the nmethod with
+ // the heap.
+ // This nmethod may have already been unloaded during a full GC.
+ if ((state == zombie) && !is_unloaded()) {
+ nmethod_needs_unregister = true;
+ }
+
// Change state
_state = state;
@@ -1349,6 +1365,9 @@
// safepoint can sneak in, otherwise the oops used by the
// dependency logic could have become stale.
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ if (nmethod_needs_unregister) {
+ Universe::heap()->unregister_nmethod(this);
+ }
flush_dependencies(NULL);
}
@@ -1696,20 +1715,10 @@
#endif // !PRODUCT
}
-// This method is called twice during GC -- once while
-// tracing the "active" nmethods on thread stacks during
-// the (strong) marking phase, and then again when walking
-// the code cache contents during the weak roots processing
-// phase. The two uses are distinguished by means of the
-// 'do_strong_roots_only' flag, which is true in the first
-// case. We want to walk the weak roots in the nmethod
-// only in the second case. The weak roots in the nmethod
-// are the oops in the ExceptionCache and the InlineCache
-// oops.
-void nmethod::oops_do(OopClosure* f, bool do_strong_roots_only) {
- // make sure the oops ready to receive visitors
- assert(!is_zombie() && !is_unloaded(),
- "should not call follow on zombie or unloaded nmethod");
+void nmethod::oops_do(OopClosure* f, bool do_strong_roots_only, bool allow_zombie) {
+ // make sure the oops ready to receive visitors
+ assert(allow_zombie || !is_zombie(), "should not call follow on zombie nmethod");
+ assert(!is_unloaded(), "should not call follow on unloaded nmethod");
// If the method is not entrant or zombie then a JMP is plastered over the
// first few bytes. If an oop in the old code was there, that oop
--- ./hotspot/src/share/vm/code/nmethod.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/code/nmethod.hpp Wed May 07 19:26:16 2014 -0700
@@ -548,8 +548,8 @@
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map,
OopClosure* f);
- void oops_do(OopClosure* f) { oops_do(f, false); }
- void oops_do(OopClosure* f, bool do_strong_roots_only);
+ void oops_do(OopClosure* f) { oops_do(f, false, false); }
+ void oops_do(OopClosure* f, bool do_strong_roots_only, bool allow_zombie);
bool detect_scavenge_root_oops();
void verify_scavenge_root_oops() PRODUCT_RETURN;
--- ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Wed May 07 19:26:16 2014 -0700
@@ -58,8 +58,22 @@
MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop_work(p); }
- inline void do_oop_nv(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); }
+
+ Prefetch::style prefetch_style() {
+ return Prefetch::do_read;
+ }
+};
+
+class Par_MarkRefsIntoClosure: public OopsInGenClosure {
+ private:
+ const MemRegion _span;
+ CMSBitMap* _bitMap;
+ protected:
+ DO_OOP_WORK_DEFN
+ public:
+ Par_MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
+ virtual void do_oop(oop* p);
+ virtual void do_oop(narrowOop* p);
bool do_header() { return true; }
Prefetch::style prefetch_style() {
return Prefetch::do_read;
--- ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed May 07 19:26:16 2014 -0700
@@ -575,6 +575,7 @@
_restart_addr(NULL),
_overflow_list(NULL),
_stats(cmsGen),
+ _eden_chunk_lock(new Mutex(Mutex::leaf + 1, "CMS_eden_chunk_lock", true)),
_eden_chunk_array(NULL), // may be set in ctor body
_eden_chunk_capacity(0), // -- ditto --
_eden_chunk_index(0), // -- ditto --
@@ -754,7 +755,7 @@
assert(_eden_chunk_array != NULL || _eden_chunk_capacity == 0, "Error");
// Support for parallelizing survivor space rescan
- if (CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) {
+ if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
const size_t max_plab_samples =
((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize;
@@ -1997,7 +1998,7 @@
GenCollectedHeap* gch = GenCollectedHeap::heap();
STWGCTimer* gc_timer = GenMarkSweep::gc_timer();
- gc_timer->register_gc_start(os::elapsed_counter());
+ gc_timer->register_gc_start();
SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
@@ -2094,7 +2095,7 @@
size_policy()->msc_collection_end(gch->gc_cause());
}
- gc_timer->register_gc_end(os::elapsed_counter());
+ gc_timer->register_gc_end();
gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions());
@@ -2136,6 +2137,39 @@
}
+void CMSCollector::print_eden_and_survivor_chunk_arrays() {
+ DefNewGeneration* dng = _young_gen->as_DefNewGeneration();
+ EdenSpace* eden_space = dng->eden();
+ ContiguousSpace* from_space = dng->from();
+ ContiguousSpace* to_space = dng->to();
+ // Eden
+ if (_eden_chunk_array != NULL) {
+ gclog_or_tty->print_cr("eden " PTR_FORMAT "-" PTR_FORMAT "-" PTR_FORMAT "(" SIZE_FORMAT ")",
+ eden_space->bottom(), eden_space->top(),
+ eden_space->end(), eden_space->capacity());
+ gclog_or_tty->print_cr("_eden_chunk_index=" SIZE_FORMAT ", "
+ "_eden_chunk_capacity=" SIZE_FORMAT,
+ _eden_chunk_index, _eden_chunk_capacity);
+ for (size_t i = 0; i < _eden_chunk_index; i++) {
+ gclog_or_tty->print_cr("_eden_chunk_array[" SIZE_FORMAT "]=" PTR_FORMAT,
+ i, _eden_chunk_array[i]);
+ }
+ }
+ // Survivor
+ if (_survivor_chunk_array != NULL) {
+ gclog_or_tty->print_cr("survivor " PTR_FORMAT "-" PTR_FORMAT "-" PTR_FORMAT "(" SIZE_FORMAT ")",
+ from_space->bottom(), from_space->top(),
+ from_space->end(), from_space->capacity());
+ gclog_or_tty->print_cr("_survivor_chunk_index=" SIZE_FORMAT ", "
+ "_survivor_chunk_capacity=" SIZE_FORMAT,
+ _survivor_chunk_index, _survivor_chunk_capacity);
+ for (size_t i = 0; i < _survivor_chunk_index; i++) {
+ gclog_or_tty->print_cr("_survivor_chunk_array[" SIZE_FORMAT "]=" PTR_FORMAT,
+ i, _survivor_chunk_array[i]);
+ }
+ }
+}
+
void CMSCollector::getFreelistLocks() const {
// Get locks for all free lists in all generations that this
// collector is responsible for
@@ -2443,7 +2477,7 @@
void CMSCollector::register_gc_start(GCCause::Cause cause) {
_cms_start_registered = true;
- _gc_timer_cm->register_gc_start(os::elapsed_counter());
+ _gc_timer_cm->register_gc_start();
_gc_tracer_cm->report_gc_start(cause, _gc_timer_cm->gc_start());
}
@@ -2451,7 +2485,7 @@
if (_cms_start_registered) {
report_heap_summary(GCWhen::AfterGC);
- _gc_timer_cm->register_gc_end(os::elapsed_counter());
+ _gc_timer_cm->register_gc_end();
_gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions());
_cms_start_registered = false;
}
@@ -2510,8 +2544,7 @@
// initial marking in checkpointRootsInitialWork has been completed
if (VerifyDuringGC &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
- gclog_or_tty->print("Verify before initial mark: ");
- Universe::verify();
+ Universe::verify("Verify before initial mark: ");
}
{
bool res = markFromRoots(false);
@@ -2522,8 +2555,7 @@
case FinalMarking:
if (VerifyDuringGC &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
- gclog_or_tty->print("Verify before re-mark: ");
- Universe::verify();
+ Universe::verify("Verify before re-mark: ");
}
checkpointRootsFinal(false, clear_all_soft_refs,
init_mark_was_synchronous);
@@ -2534,8 +2566,7 @@
// final marking in checkpointRootsFinal has been completed
if (VerifyDuringGC &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
- gclog_or_tty->print("Verify before sweep: ");
- Universe::verify();
+ Universe::verify("Verify before sweep: ");
}
sweep(false);
assert(_collectorState == Resizing, "Incorrect state");
@@ -2550,8 +2581,7 @@
// The heap has been resized.
if (VerifyDuringGC &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
- gclog_or_tty->print("Verify before reset: ");
- Universe::verify();
+ Universe::verify("Verify before reset: ");
}
save_heap_summary();
reset(false);
@@ -2890,8 +2920,8 @@
bool failed() { return _failed; }
};
-bool CMSCollector::verify_after_remark() {
- gclog_or_tty->print(" [Verifying CMS Marking... ");
+bool CMSCollector::verify_after_remark(bool silent) {
+ if (!silent) gclog_or_tty->print(" [Verifying CMS Marking... ");
MutexLockerEx ml(verification_mark_bm()->lock(), Mutex::_no_safepoint_check_flag);
static bool init = false;
@@ -2952,7 +2982,7 @@
warning("Unrecognized value %d for CMSRemarkVerifyVariant",
CMSRemarkVerifyVariant);
}
- gclog_or_tty->print(" done] ");
+ if (!silent) gclog_or_tty->print(" done] ");
return true;
}
@@ -3530,6 +3560,31 @@
// CMS work
+// The common parts of CMSParInitialMarkTask and CMSParRemarkTask.
+class CMSParMarkTask : public AbstractGangTask {
+ protected:
+ CMSCollector* _collector;
+ int _n_workers;
+ CMSParMarkTask(const char* name, CMSCollector* collector, int n_workers) :
+ AbstractGangTask(name),
+ _collector(collector),
+ _n_workers(n_workers) {}
+ // Work method in support of parallel rescan ... of young gen spaces
+ void do_young_space_rescan(uint worker_id, OopsInGenClosure* cl,
+ ContiguousSpace* space,
+ HeapWord** chunk_array, size_t chunk_top);
+ void work_on_young_gen_roots(uint worker_id, OopsInGenClosure* cl);
+};
+
+// Parallel initial mark task
+class CMSParInitialMarkTask: public CMSParMarkTask {
+ public:
+ CMSParInitialMarkTask(CMSCollector* collector, int n_workers) :
+ CMSParMarkTask("Scan roots and young gen for initial mark in parallel",
+ collector, n_workers) {}
+ void work(uint worker_id);
+};
+
// Checkpoint the roots into this generation from outside
// this generation. [Note this initial checkpoint need only
// be approximate -- we'll do a catch up phase subsequently.]
@@ -3619,20 +3674,42 @@
// weak reference processing has not started yet.
ref_processor()->set_enqueuing_is_done(false);
+ if (CMSPrintEdenSurvivorChunks) {
+ print_eden_and_survivor_chunk_arrays();
+ }
+
{
// This is not needed. DEBUG_ONLY(RememberKlassesChecker imx(true);)
COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
- gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
- gch->gen_process_strong_roots(_cmsGen->level(),
- true, // younger gens are roots
- true, // activate StrongRootsScope
- true, // collecting perm gen
- SharedHeap::ScanningOption(roots_scanning_options()),
- ¬Older,
- true, // walk all of code cache if (so & SO_CodeCache)
- NULL);
- }
-
+ if (CMSParallelInitialMarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
+ // The parallel version.
+ FlexibleWorkGang* workers = gch->workers();
+ assert(workers != NULL, "Need parallel worker threads.");
+ int n_workers = workers->active_workers();
+ CMSParInitialMarkTask tsk(this, n_workers);
+ gch->set_par_threads(n_workers);
+ initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
+ if (n_workers > 1) {
+ GenCollectedHeap::StrongRootsScope srs(gch);
+ workers->run_task(&tsk);
+ } else {
+ GenCollectedHeap::StrongRootsScope srs(gch);
+ tsk.work(0);
+ }
+ gch->set_par_threads(0);
+ } else {
+ // The serial version.
+ gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
+ gch->gen_process_strong_roots(_cmsGen->level(),
+ true, // younger gens are roots
+ true, // activate StrongRootsScope
+ true, // collecting perm gen
+ SharedHeap::ScanningOption(roots_scanning_options()),
+ ¬Older,
+ true, // walk all of code cache if (so & SO_CodeCache)
+ NULL);
+ }
+ }
// Clear mod-union table; it will be dirtied in the prologue of
// CMS generation per each younger generation collection.
@@ -4414,7 +4491,9 @@
verify_overflow_empty();
_abort_preclean = false;
if (CMSPrecleaningEnabled) {
- _eden_chunk_index = 0;
+ if (!CMSEdenChunksRecordAlways) {
+ _eden_chunk_index = 0;
+ }
size_t used = get_eden_used();
size_t capacity = get_eden_capacity();
// Don't start sampling unless we will get sufficiently
@@ -4523,7 +4602,9 @@
if (!_start_sampling) {
return;
}
- if (_eden_chunk_array) {
+ // When CMSEdenChunksRecordAlways is true, the eden chunk array
+ // is populated by the young generation.
+ if (_eden_chunk_array != NULL && !CMSEdenChunksRecordAlways) {
if (_eden_chunk_index < _eden_chunk_capacity) {
_eden_chunk_array[_eden_chunk_index] = *_top_addr; // take sample
assert(_eden_chunk_array[_eden_chunk_index] <= *_end_addr,
@@ -5000,6 +5081,10 @@
// Update the saved marks which may affect the root scans.
gch->save_marks();
+ if (CMSPrintEdenSurvivorChunks) {
+ print_eden_and_survivor_chunk_arrays();
+ }
+
{
COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
@@ -5107,10 +5192,51 @@
}
}
+void CMSParInitialMarkTask::work(uint worker_id) {
+ elapsedTimer _timer;
+ ResourceMark rm;
+ HandleMark hm;
+
+ // ---------- scan from roots --------------
+ _timer.start();
+ GenCollectedHeap* gch = GenCollectedHeap::heap();
+ Par_MarkRefsIntoClosure par_mri_cl(_collector->_span, &(_collector->_markBitMap));
+
+ // ---------- young gen roots --------------
+ {
+ work_on_young_gen_roots(worker_id, &par_mri_cl);
+ _timer.stop();
+ if (PrintCMSStatistics != 0) {
+ gclog_or_tty->print_cr(
+ "Finished young gen initial mark scan work in %dth thread: %3.3f sec",
+ worker_id, _timer.seconds());
+ }
+ }
+
+ // ---------- remaining roots --------------
+ _timer.reset();
+ _timer.start();
+ gch->gen_process_strong_roots(_collector->_cmsGen->level(),
+ false, // yg was scanned above
+ false, // this is parallel code
+ true, // collecting perm gen
+ SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
+ &par_mri_cl,
+ true, // walk all of code cache if (so & SO_CodeCache)
+ NULL);
+ assert(_collector->should_unload_classes()
+ || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache),
+ "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
+ _timer.stop();
+ if (PrintCMSStatistics != 0) {
+ gclog_or_tty->print_cr(
+ "Finished remaining root initial mark scan work in %dth thread: %3.3f sec",
+ worker_id, _timer.seconds());
+ }
+}
+
// Parallel remark task
-class CMSParRemarkTask: public AbstractGangTask {
- CMSCollector* _collector;
- int _n_workers;
+class CMSParRemarkTask: public CMSParMarkTask {
CompactibleFreeListSpace* _cms_space;
CompactibleFreeListSpace* _perm_space;
@@ -5126,10 +5252,9 @@
CompactibleFreeListSpace* perm_space,
int n_workers, FlexibleWorkGang* workers,
OopTaskQueueSet* task_queues):
- AbstractGangTask("Rescan roots and grey objects in parallel"),
- _collector(collector),
+ CMSParMarkTask("Rescan roots and grey objects in parallel",
+ collector, n_workers),
_cms_space(cms_space), _perm_space(perm_space),
- _n_workers(n_workers),
_task_queues(task_queues),
_term(n_workers, task_queues) { }
@@ -5143,11 +5268,6 @@
void work(uint worker_id);
private:
- // Work method in support of parallel rescan ... of young gen spaces
- void do_young_space_rescan(int i, Par_MarkRefsIntoAndScanClosure* cl,
- ContiguousSpace* space,
- HeapWord** chunk_array, size_t chunk_top);
-
// ... of dirty cards in old space
void do_dirty_card_rescan_tasks(CompactibleFreeListSpace* sp, int i,
Par_MarkRefsIntoAndScanClosure* cl);
@@ -5156,6 +5276,25 @@
void do_work_steal(int i, Par_MarkRefsIntoAndScanClosure* cl, int* seed);
};
+void CMSParMarkTask::work_on_young_gen_roots(uint worker_id, OopsInGenClosure* cl) {
+ DefNewGeneration* dng = _collector->_young_gen->as_DefNewGeneration();
+ EdenSpace* eden_space = dng->eden();
+ ContiguousSpace* from_space = dng->from();
+ ContiguousSpace* to_space = dng->to();
+
+ HeapWord** eca = _collector->_eden_chunk_array;
+ size_t ect = _collector->_eden_chunk_index;
+ HeapWord** sca = _collector->_survivor_chunk_array;
+ size_t sct = _collector->_survivor_chunk_index;
+
+ assert(ect <= _collector->_eden_chunk_capacity, "out of bounds");
+ assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds");
+
+ do_young_space_rescan(worker_id, cl, to_space, NULL, 0);
+ do_young_space_rescan(worker_id, cl, from_space, sca, sct);
+ do_young_space_rescan(worker_id, cl, eden_space, eca, ect);
+}
+
// work_queue(i) is passed to the closure
// Par_MarkRefsIntoAndScanClosure. The "i" parameter
// also is passed to do_dirty_card_rescan_tasks() and to
@@ -5180,23 +5319,7 @@
// work first.
// ---------- young gen roots --------------
{
- DefNewGeneration* dng = _collector->_young_gen->as_DefNewGeneration();
- EdenSpace* eden_space = dng->eden();
- ContiguousSpace* from_space = dng->from();
- ContiguousSpace* to_space = dng->to();
-
- HeapWord** eca = _collector->_eden_chunk_array;
- size_t ect = _collector->_eden_chunk_index;
- HeapWord** sca = _collector->_survivor_chunk_array;
- size_t sct = _collector->_survivor_chunk_index;
-
- assert(ect <= _collector->_eden_chunk_capacity, "out of bounds");
- assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds");
-
- do_young_space_rescan(worker_id, &par_mrias_cl, to_space, NULL, 0);
- do_young_space_rescan(worker_id, &par_mrias_cl, from_space, sca, sct);
- do_young_space_rescan(worker_id, &par_mrias_cl, eden_space, eca, ect);
-
+ work_on_young_gen_roots(worker_id, &par_mrias_cl);
_timer.stop();
if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr(
@@ -5257,8 +5380,8 @@
// Note that parameter "i" is not used.
void
-CMSParRemarkTask::do_young_space_rescan(int i,
- Par_MarkRefsIntoAndScanClosure* cl, ContiguousSpace* space,
+CMSParMarkTask::do_young_space_rescan(uint worker_id,
+ OopsInGenClosure* cl, ContiguousSpace* space,
HeapWord** chunk_array, size_t chunk_top) {
// Until all tasks completed:
// . claim an unclaimed task
@@ -5454,6 +5577,32 @@
"Else our work is not yet done");
}
+// Record object boundaries in _eden_chunk_array by sampling the eden
+// top in the slow-path eden object allocation code path and record
+// the boundaries, if CMSEdenChunksRecordAlways is true. If
+// CMSEdenChunksRecordAlways is false, we use the other asynchronous
+// sampling in sample_eden() that activates during the part of the
+// preclean phase.
+void CMSCollector::sample_eden_chunk() {
+ if (CMSEdenChunksRecordAlways && _eden_chunk_array != NULL) {
+ if (_eden_chunk_lock->try_lock()) {
+ // Record a sample. This is the critical section. The contents
+ // of the _eden_chunk_array have to be non-decreasing in the
+ // address order.
+ _eden_chunk_array[_eden_chunk_index] = *_top_addr;
+ assert(_eden_chunk_array[_eden_chunk_index] <= *_end_addr,
+ "Unexpected state of Eden");
+ if (_eden_chunk_index == 0 ||
+ ((_eden_chunk_array[_eden_chunk_index] > _eden_chunk_array[_eden_chunk_index-1]) &&
+ (pointer_delta(_eden_chunk_array[_eden_chunk_index],
+ _eden_chunk_array[_eden_chunk_index-1]) >= CMSSamplingGrain))) {
+ _eden_chunk_index++; // commit sample
+ }
+ _eden_chunk_lock->unlock();
+ }
+ }
+}
+
// Return a thread-local PLAB recording array, as appropriate.
void* CMSCollector::get_data_recorder(int thr_num) {
if (_survivor_plab_array != NULL &&
@@ -5477,12 +5626,13 @@
// Merge the per-thread plab arrays into the global survivor chunk
// array which will provide the partitioning of the survivor space
-// for CMS rescan.
+// for CMS initial scan and rescan.
void CMSCollector::merge_survivor_plab_arrays(ContiguousSpace* surv,
int no_of_gc_threads) {
assert(_survivor_plab_array != NULL, "Error");
assert(_survivor_chunk_array != NULL, "Error");
- assert(_collectorState == FinalMarking, "Error");
+ assert(_collectorState == FinalMarking ||
+ (CMSParallelInitialMarkEnabled && _collectorState == InitialMarking), "Error");
for (int j = 0; j < no_of_gc_threads; j++) {
_cursor[j] = 0;
}
@@ -5545,7 +5695,7 @@
}
// Set up the space's par_seq_tasks structure for work claiming
-// for parallel rescan of young gen.
+// for parallel initial scan and rescan of young gen.
// See ParRescanTask where this is currently used.
void
CMSCollector::
@@ -6695,6 +6845,28 @@
void MarkRefsIntoClosure::do_oop(oop* p) { MarkRefsIntoClosure::do_oop_work(p); }
void MarkRefsIntoClosure::do_oop(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); }
+Par_MarkRefsIntoClosure::Par_MarkRefsIntoClosure(
+ MemRegion span, CMSBitMap* bitMap):
+ _span(span),
+ _bitMap(bitMap)
+{
+ assert(_ref_processor == NULL, "deliberately left NULL");
+ assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
+}
+
+void Par_MarkRefsIntoClosure::do_oop(oop obj) {
+ // if p points into _span, then mark corresponding bit in _markBitMap
+ assert(obj->is_oop(), "expected an oop");
+ HeapWord* addr = (HeapWord*)obj;
+ if (_span.contains(addr)) {
+ // this should be made more efficient
+ _bitMap->par_mark(addr);
+ }
+}
+
+void Par_MarkRefsIntoClosure::do_oop(oop* p) { Par_MarkRefsIntoClosure::do_oop_work(p); }
+void Par_MarkRefsIntoClosure::do_oop(narrowOop* p) { Par_MarkRefsIntoClosure::do_oop_work(p); }
+
// A variant of the above, used for CMS marking verification.
MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure(
MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm):
@@ -9360,7 +9532,6 @@
return;
}
}
-
// Transfer some number of overflown objects to usual marking
// stack. Return true if some objects were transferred.
bool MarkRefsIntoAndScanClosure::take_from_overflow_list() {
@@ -9432,4 +9603,3 @@
ShouldNotReachHere();
}
}
-
--- ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed May 07 19:26:16 2014 -0700
@@ -516,6 +516,8 @@
friend class ConcurrentMarkSweepThread;
friend class ConcurrentMarkSweepGeneration;
friend class CompactibleFreeListSpace;
+ friend class CMSParMarkTask;
+ friend class CMSParInitialMarkTask;
friend class CMSParRemarkTask;
friend class CMSConcMarkingTask;
friend class CMSRefProcTaskProxy;
@@ -752,6 +754,7 @@
Generation* _young_gen; // the younger gen
HeapWord** _top_addr; // ... Top of Eden
HeapWord** _end_addr; // ... End of Eden
+ Mutex* _eden_chunk_lock;
HeapWord** _eden_chunk_array; // ... Eden partitioning array
size_t _eden_chunk_index; // ... top (exclusive) of array
size_t _eden_chunk_capacity; // ... max entries in array
@@ -953,6 +956,7 @@
// Support for parallel remark of survivor space
void* get_data_recorder(int thr_num);
+ void sample_eden_chunk();
CMSBitMap* markBitMap() { return &_markBitMap; }
void directAllocated(HeapWord* start, size_t size);
@@ -1013,7 +1017,7 @@
// debugging
void verify();
- bool verify_after_remark();
+ bool verify_after_remark(bool silent = VerifySilently);
void verify_ok_to_terminate() const PRODUCT_RETURN;
void verify_work_stacks_empty() const PRODUCT_RETURN;
void verify_overflow_empty() const PRODUCT_RETURN;
@@ -1031,6 +1035,8 @@
// Initialization errors
bool completed_initialization() { return _completed_initialization; }
+
+ void print_eden_and_survivor_chunk_arrays();
};
class CMSExpansionCause : public AllStatic {
@@ -1317,6 +1323,10 @@
//Delegate to collector
return collector()->get_data_recorder(thr_num);
}
+ void sample_eden_chunk() {
+ //Delegate to collector
+ return collector()->sample_eden_chunk();
+ }
// Printing
const char* name() const;
--- ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -145,7 +145,7 @@
);
#endif /* USDT2 */
- _collector->_gc_timer_cm->register_gc_pause_start("Initial Mark", os::elapsed_counter());
+ _collector->_gc_timer_cm->register_gc_pause_start("Initial Mark");
GenCollectedHeap* gch = GenCollectedHeap::heap();
GCCauseSetter gccs(gch, GCCause::_cms_initial_mark);
@@ -157,7 +157,7 @@
VM_CMS_Operation::verify_after_gc();
- _collector->_gc_timer_cm->register_gc_pause_end(os::elapsed_counter());
+ _collector->_gc_timer_cm->register_gc_pause_end();
#ifndef USDT2
HS_DTRACE_PROBE(hs_private, cms__initmark__end);
@@ -182,7 +182,7 @@
);
#endif /* USDT2 */
- _collector->_gc_timer_cm->register_gc_pause_start("Final Mark", os::elapsed_counter());
+ _collector->_gc_timer_cm->register_gc_pause_start("Final Mark");
GenCollectedHeap* gch = GenCollectedHeap::heap();
GCCauseSetter gccs(gch, GCCause::_cms_final_remark);
@@ -195,7 +195,7 @@
VM_CMS_Operation::verify_after_gc();
_collector->save_heap_summary();
- _collector->_gc_timer_cm->register_gc_pause_end(os::elapsed_counter());
+ _collector->_gc_timer_cm->register_gc_pause_end();
#ifndef USDT2
HS_DTRACE_PROBE(hs_private, cms__remark__end);
--- ./hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Wed May 07 19:26:16 2014 -0700
@@ -114,6 +114,14 @@
}
}
+void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) {
+ if (_threads != NULL) {
+ for (int i = 0; i < worker_thread_num(); i++) {
+ tc->do_thread(_threads[i]);
+ }
+ }
+}
+
int ConcurrentG1Refine::thread_num() {
int n_threads = (G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads
: ParallelGCThreads;
@@ -126,3 +134,7 @@
st->cr();
}
}
+
+ConcurrentG1RefineThread * ConcurrentG1Refine::sampling_thread() const {
+ return _threads[worker_thread_num()];
+}
--- ./hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Wed May 07 19:26:16 2014 -0700
@@ -35,6 +35,7 @@
class G1CollectedHeap;
class G1HotCardCache;
class G1RemSet;
+class DirtyCardQueue;
class ConcurrentG1Refine: public CHeapObj {
ConcurrentG1RefineThread** _threads;
@@ -78,9 +79,15 @@
void reinitialize_threads();
- // Iterate over the conc refine threads
+ // Iterate over all concurrent refinement threads
void threads_do(ThreadClosure *tc);
+ // Iterate over all worker refinement threads
+ void worker_threads_do(ThreadClosure * tc);
+
+ // The RS sampling thread
+ ConcurrentG1RefineThread * sampling_thread() const;
+
static int thread_num();
void print_worker_threads_on(outputStream* st) const;
--- ./hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed May 07 19:26:16 2014 -0700
@@ -1154,10 +1154,9 @@
if (VerifyDuringGC) {
HandleMark hm; // handle scope
- gclog_or_tty->print(" VerifyDuringGC:(before)");
Universe::heap()->prepare_for_verify();
- Universe::verify(/* silent */ false,
- /* option */ VerifyOption_G1UsePrevMarking);
+ Universe::verify(VerifyOption_G1UsePrevMarking,
+ " VerifyDuringGC:(before)");
}
G1CollectorPolicy* g1p = g1h->g1_policy();
@@ -1181,10 +1180,9 @@
// Verify the heap w.r.t. the previous marking bitmap.
if (VerifyDuringGC) {
HandleMark hm; // handle scope
- gclog_or_tty->print(" VerifyDuringGC:(overflow)");
Universe::heap()->prepare_for_verify();
- Universe::verify(/* silent */ false,
- /* option */ VerifyOption_G1UsePrevMarking);
+ Universe::verify(VerifyOption_G1UsePrevMarking,
+ " VerifyDuringGC:(overflow)");
}
// Clear the marking state because we will be restarting
@@ -1204,10 +1202,9 @@
if (VerifyDuringGC) {
HandleMark hm; // handle scope
- gclog_or_tty->print(" VerifyDuringGC:(after)");
Universe::heap()->prepare_for_verify();
- Universe::verify(/* silent */ false,
- /* option */ VerifyOption_G1UseNextMarking);
+ Universe::verify(VerifyOption_G1UseNextMarking,
+ " VerifyDuringGC:(after)");
}
assert(!restart_for_overflow(), "sanity");
// Completely reset the marking state since marking completed
@@ -1498,7 +1495,6 @@
}
};
-
class G1ParVerifyFinalCountTask: public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
@@ -1856,10 +1852,9 @@
if (VerifyDuringGC) {
HandleMark hm; // handle scope
- gclog_or_tty->print(" VerifyDuringGC:(before)");
Universe::heap()->prepare_for_verify();
- Universe::verify(/* silent */ false,
- /* option */ VerifyOption_G1UsePrevMarking);
+ Universe::verify(VerifyOption_G1UsePrevMarking,
+ " VerifyDuringGC:(before)");
}
G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
@@ -2011,10 +2006,9 @@
if (VerifyDuringGC) {
HandleMark hm; // handle scope
- gclog_or_tty->print(" VerifyDuringGC:(after)");
Universe::heap()->prepare_for_verify();
- Universe::verify(/* silent */ false,
- /* option */ VerifyOption_G1UsePrevMarking);
+ Universe::verify(VerifyOption_G1UsePrevMarking,
+ " VerifyDuringGC:(after)");
}
g1h->verify_region_sets_optional();
@@ -2412,10 +2406,9 @@
assert(!rp->discovery_enabled(), "Post condition");
}
- // Now clean up stale oops in StringTable
- StringTable::unlink(&g1_is_alive);
- // Clean up unreferenced symbols in symbol table.
- SymbolTable::unlink();
+ g1h->unlink_string_and_symbol_table(&g1_is_alive,
+ /* process_strings */ false, // currently strings are always roots
+ /* process_symbols */ true);
}
void ConcurrentMark::swapMarkBitMaps() {
@@ -4396,7 +4389,8 @@
_total_used_bytes(0), _total_capacity_bytes(0),
_total_prev_live_bytes(0), _total_next_live_bytes(0),
_hum_used_bytes(0), _hum_capacity_bytes(0),
- _hum_prev_live_bytes(0), _hum_next_live_bytes(0) {
+ _hum_prev_live_bytes(0), _hum_next_live_bytes(0),
+ _total_remset_bytes(0), _total_strong_code_roots_bytes(0) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
MemRegion g1_committed = g1h->g1_committed();
MemRegion g1_reserved = g1h->g1_reserved();
@@ -4414,23 +4408,29 @@
HeapRegion::GrainBytes);
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
- G1PPRL_TYPE_H_FORMAT
- G1PPRL_ADDR_BASE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_DOUBLE_H_FORMAT,
- "type", "address-range",
- "used", "prev-live", "next-live", "gc-eff");
+ G1PPRL_TYPE_H_FORMAT
+ G1PPRL_ADDR_BASE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_DOUBLE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT,
+ "type", "address-range",
+ "used", "prev-live", "next-live", "gc-eff",
+ "remset", "code-roots");
_out->print_cr(G1PPRL_LINE_PREFIX
- G1PPRL_TYPE_H_FORMAT
- G1PPRL_ADDR_BASE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_BYTE_H_FORMAT
- G1PPRL_DOUBLE_H_FORMAT,
- "", "",
- "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)");
+ G1PPRL_TYPE_H_FORMAT
+ G1PPRL_ADDR_BASE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_DOUBLE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT
+ G1PPRL_BYTE_H_FORMAT,
+ "", "",
+ "(bytes)", "(bytes)", "(bytes)", "(bytes/ms)",
+ "(bytes)", "(bytes)");
}
// It takes as a parameter a reference to one of the _hum_* fields, it
@@ -4472,6 +4472,9 @@
size_t prev_live_bytes = r->live_bytes();
size_t next_live_bytes = r->next_live_bytes();
double gc_eff = r->gc_efficiency();
+ size_t remset_bytes = r->rem_set()->mem_size();
+ size_t strong_code_roots_bytes = r->rem_set()->strong_code_roots_mem_size();
+
if (r->used() == 0) {
type = "FREE";
} else if (r->is_survivor()) {
@@ -4505,6 +4508,8 @@
_total_capacity_bytes += capacity_bytes;
_total_prev_live_bytes += prev_live_bytes;
_total_next_live_bytes += next_live_bytes;
+ _total_remset_bytes += remset_bytes;
+ _total_strong_code_roots_bytes += strong_code_roots_bytes;
// Print a line for this particular region.
_out->print_cr(G1PPRL_LINE_PREFIX
@@ -4513,14 +4518,19 @@
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
- G1PPRL_DOUBLE_FORMAT,
+ G1PPRL_DOUBLE_FORMAT
+ G1PPRL_BYTE_FORMAT
+ G1PPRL_BYTE_FORMAT,
type, bottom, end,
- used_bytes, prev_live_bytes, next_live_bytes, gc_eff);
+ used_bytes, prev_live_bytes, next_live_bytes, gc_eff,
+ remset_bytes, strong_code_roots_bytes);
return false;
}
G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() {
+ // add static memory usages to remembered set sizes
+ _total_remset_bytes += HeapRegionRemSet::fl_mem_size() + HeapRegionRemSet::static_mem_size();
// Print the footer of the output.
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
@@ -4528,13 +4538,17 @@
G1PPRL_SUM_MB_FORMAT("capacity")
G1PPRL_SUM_MB_PERC_FORMAT("used")
G1PPRL_SUM_MB_PERC_FORMAT("prev-live")
- G1PPRL_SUM_MB_PERC_FORMAT("next-live"),
+ G1PPRL_SUM_MB_PERC_FORMAT("next-live")
+ G1PPRL_SUM_MB_FORMAT("remset")
+ G1PPRL_SUM_MB_FORMAT("code-roots"),
bytes_to_mb(_total_capacity_bytes),
bytes_to_mb(_total_used_bytes),
perc(_total_used_bytes, _total_capacity_bytes),
bytes_to_mb(_total_prev_live_bytes),
perc(_total_prev_live_bytes, _total_capacity_bytes),
bytes_to_mb(_total_next_live_bytes),
- perc(_total_next_live_bytes, _total_capacity_bytes));
+ perc(_total_next_live_bytes, _total_capacity_bytes),
+ bytes_to_mb(_total_remset_bytes),
+ bytes_to_mb(_total_strong_code_roots_bytes));
_out->cr();
}
--- ./hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed May 07 19:26:16 2014 -0700
@@ -1224,6 +1224,12 @@
size_t _hum_prev_live_bytes;
size_t _hum_next_live_bytes;
+ // Accumulator for the remembered set size
+ size_t _total_remset_bytes;
+
+ // Accumulator for strong code roots memory size
+ size_t _total_strong_code_roots_bytes;
+
static double perc(size_t val, size_t total) {
if (total == 0) {
return 0.0;
--- ./hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Wed May 07 19:26:16 2014 -0700
@@ -81,7 +81,7 @@
size_t* marked_bytes_array,
BitMap* task_card_bm) {
G1CollectedHeap* g1h = _g1h;
- CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set());
+ CardTableModRefBS* ct_bs = g1h->g1_barrier_set();
HeapWord* start = mr.start();
HeapWord* end = mr.end();
--- ./hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Wed May 07 19:26:16 2014 -0700
@@ -65,9 +65,7 @@
// threshold limit is no more than this.
guarantee(G1ConcRSHotCardLimit <= max_jubyte, "sanity");
- ModRefBarrierSet* bs = _g1h->mr_bs();
- guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition");
- _ct_bs = (CardTableModRefBS*)bs;
+ _ct_bs = _g1h->g1_barrier_set();
_ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start());
// Allocate/Reserve the counts table
--- ./hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed May 07 19:26:16 2014 -0700
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
#include "gc_implementation/g1/bufferingOopClosure.hpp"
#include "gc_implementation/g1/concurrentG1Refine.hpp"
@@ -56,6 +57,7 @@
#include "oops/oop.pcgc.inline.hpp"
#include "runtime/aprofiler.hpp"
#include "runtime/vmThread.hpp"
+#include "utilities/ticks.hpp"
size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
@@ -125,10 +127,8 @@
int _histo[256];
public:
ClearLoggedCardTableEntryClosure() :
- _calls(0)
+ _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set())
{
- _g1h = G1CollectedHeap::heap();
- _ctbs = (CardTableModRefBS*)_g1h->barrier_set();
for (int i = 0; i < 256; i++) _histo[i] = 0;
}
bool do_card_ptr(jbyte* card_ptr, int worker_i) {
@@ -158,11 +158,8 @@
CardTableModRefBS* _ctbs;
public:
RedirtyLoggedCardTableEntryClosure() :
- _calls(0)
- {
- _g1h = G1CollectedHeap::heap();
- _ctbs = (CardTableModRefBS*)_g1h->barrier_set();
- }
+ _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {}
+
bool do_card_ptr(jbyte* card_ptr, int worker_i) {
if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
_calls++;
@@ -477,7 +474,7 @@
void G1CollectedHeap::check_ct_logs_at_safepoint() {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
- CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set();
+ CardTableModRefBS* ct_bs = g1_barrier_set();
// Count the dirty cards at the start.
CountNonCleanMemRegionClosure count1(this);
@@ -1158,26 +1155,33 @@
ModRefBarrierSet* _mr_bs;
public:
PostMCRemSetClearClosure(G1CollectedHeap* g1h, ModRefBarrierSet* mr_bs) :
- _g1h(g1h), _mr_bs(mr_bs) { }
+ _g1h(g1h), _mr_bs(mr_bs) {}
+
bool doHeapRegion(HeapRegion* r) {
+ HeapRegionRemSet* hrrs = r->rem_set();
+
if (r->continuesHumongous()) {
+ // We'll assert that the strong code root list and RSet is empty
+ assert(hrrs->strong_code_roots_list_length() == 0, "sanity");
+ assert(hrrs->occupied() == 0, "RSet should be empty");
return false;
}
+
_g1h->reset_gc_time_stamps(r);
- HeapRegionRemSet* hrrs = r->rem_set();
- if (hrrs != NULL) hrrs->clear();
+ hrrs->clear();
// You might think here that we could clear just the cards
// corresponding to the used region. But no: if we leave a dirty card
// in a region we might allocate into, then it would prevent that card
// from being enqueued, and cause it to be missed.
// Re: the performance cost: we shouldn't be doing full GC anyway!
_mr_bs->clear(MemRegion(r->bottom(), r->end()));
+
return false;
}
};
void G1CollectedHeap::clear_rsets_post_compaction() {
- PostMCRemSetClearClosure rs_clear(this, mr_bs());
+ PostMCRemSetClearClosure rs_clear(this, g1_barrier_set());
heap_region_iterate(&rs_clear);
}
@@ -1251,31 +1255,6 @@
heap_region_iterate(&cl);
}
-double G1CollectedHeap::verify(bool guard, const char* msg) {
- double verify_time_ms = 0.0;
-
- if (guard && total_collections() >= VerifyGCStartAt) {
- double verify_start = os::elapsedTime();
- HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(msg);
- prepare_for_verify();
- Universe::verify(false /* silent */, VerifyOption_G1UsePrevMarking);
- verify_time_ms = (os::elapsedTime() - verify_start) * 1000;
- }
-
- return verify_time_ms;
-}
-
-void G1CollectedHeap::verify_before_gc() {
- double verify_time_ms = verify(VerifyBeforeGC, " VerifyBeforeGC:");
- g1_policy()->phase_times()->record_verify_before_time_ms(verify_time_ms);
-}
-
-void G1CollectedHeap::verify_after_gc() {
- double verify_time_ms = verify(VerifyAfterGC, " VerifyAfterGC:");
- g1_policy()->phase_times()->record_verify_after_time_ms(verify_time_ms);
-}
-
bool G1CollectedHeap::do_collection(bool explicit_gc,
bool clear_all_soft_refs,
size_t word_size) {
@@ -1286,7 +1265,7 @@
}
STWGCTimer* gc_timer = G1MarkSweep::gc_timer();
- gc_timer->register_gc_start(os::elapsed_counter());
+ gc_timer->register_gc_start();
SerialOldTracer* gc_tracer = G1MarkSweep::gc_tracer();
gc_tracer->report_gc_start(gc_cause(), gc_timer->gc_start());
@@ -1408,8 +1387,6 @@
MemoryService::track_memory_usage();
- verify_after_gc();
-
assert(!ref_processor_stw()->discovery_enabled(), "Postcondition");
ref_processor_stw()->verify_no_references_recorded();
@@ -1482,6 +1459,9 @@
heap_region_iterate(&rebuild_rs);
}
+ // Rebuild the strong code root lists for each region
+ rebuild_strong_code_roots();
+
if (true) { // FIXME
// Ask the permanent generation to adjust size for full collections
perm()->compute_new_size();
@@ -1509,6 +1489,8 @@
_hrs.verify_optional();
verify_region_sets_optional();
+ verify_after_gc();
+
// Start a new incremental collection set for the next pause
assert(g1_policy()->collection_set() == NULL, "must be");
g1_policy()->start_incremental_cset_building();
@@ -1546,8 +1528,7 @@
post_full_gc_dump(gc_timer);
}
- gc_timer->register_gc_end(os::elapsed_counter());
-
+ gc_timer->register_gc_end();
gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions());
return true;
@@ -1568,8 +1549,6 @@
void
G1CollectedHeap::
resize_if_necessary_after_full_collection(size_t word_size) {
- assert(MinHeapFreeRatio <= MaxHeapFreeRatio, "sanity check");
-
// Include the current allocation, if any, and bytes that will be
// pre-allocated to support collections, as "used".
const size_t used_after_gc = used();
@@ -2002,10 +1981,12 @@
size_t init_byte_size = collector_policy()->initial_heap_byte_size();
size_t max_byte_size = collector_policy()->max_heap_byte_size();
+ size_t heap_alignment = collector_policy()->max_alignment();
// Ensure that the sizes are properly aligned.
Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
+ Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap");
_cg1r = new ConcurrentG1Refine(this);
@@ -2029,14 +2010,14 @@
size_t total_reserved = 0;
total_reserved = add_and_check_overflow(total_reserved, max_byte_size);
- size_t pg_max_size = (size_t) align_size_up(pgs->max_size(), HeapRegion::GrainBytes);
+ size_t pg_max_size = (size_t) align_size_up(pgs->max_size(), heap_alignment);
total_reserved = add_and_check_overflow(total_reserved, pg_max_size);
Universe::check_alignment(total_reserved, HeapRegion::GrainBytes, "g1 heap and perm");
- char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
-
- ReservedHeapSpace heap_rs(total_reserved, HeapRegion::GrainBytes,
+ char* addr = Universe::preferred_heap_base(total_reserved, heap_alignment, Universe::UnscaledNarrowOop);
+
+ ReservedHeapSpace heap_rs(total_reserved, heap_alignment,
UseLargePages, addr);
if (UseCompressedOops) {
@@ -2044,17 +2025,17 @@
// Failed to reserve at specified address - the requested memory
// region is taken already, for example, by 'java' launcher.
// Try again to reserver heap higher.
- addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
-
- ReservedHeapSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
+ addr = Universe::preferred_heap_base(total_reserved, heap_alignment, Universe::ZeroBasedNarrowOop);
+
+ ReservedHeapSpace heap_rs0(total_reserved, heap_alignment,
UseLargePages, addr);
if (addr != NULL && !heap_rs0.is_reserved()) {
// Failed to reserve at specified address again - give up.
- addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
+ addr = Universe::preferred_heap_base(total_reserved, heap_alignment, Universe::HeapBasedNarrowOop);
assert(addr == NULL, "");
- ReservedHeapSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
+ ReservedHeapSpace heap_rs1(total_reserved, heap_alignment,
UseLargePages, addr);
heap_rs = heap_rs1;
} else {
@@ -2080,20 +2061,13 @@
// Create the gen rem set (and barrier set) for the entire reserved region.
_rem_set = collector_policy()->create_rem_set(_reserved, 2);
set_barrier_set(rem_set()->bs());
- if (barrier_set()->is_a(BarrierSet::ModRef)) {
- _mr_bs = (ModRefBarrierSet*)_barrier_set;
- } else {
- vm_exit_during_initialization("G1 requires a mod ref bs.");
+ if (!barrier_set()->is_a(BarrierSet::G1SATBCTLogging)) {
+ vm_exit_during_initialization("G1 requires a G1SATBLoggingCardTableModRefBS");
return JNI_ENOMEM;
}
// Also create a G1 rem set.
- if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
- _g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs());
- } else {
- vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
- return JNI_ENOMEM;
- }
+ _g1_rem_set = new G1RemSet(this, g1_barrier_set());
// Carve out the G1 part of the heap.
@@ -2517,7 +2491,7 @@
FullGCCount_lock->notify_all();
}
-void G1CollectedHeap::register_concurrent_cycle_start(jlong start_time) {
+void G1CollectedHeap::register_concurrent_cycle_start(const Ticks& start_time) {
_concurrent_cycle_started = true;
_gc_timer_cm->register_gc_start(start_time);
@@ -2527,7 +2501,7 @@
void G1CollectedHeap::register_concurrent_cycle_end() {
if (_concurrent_cycle_started) {
- _gc_timer_cm->register_gc_end(os::elapsed_counter());
+ _gc_timer_cm->register_gc_end();
if (_cm->has_aborted()) {
_gc_tracer_cm->report_concurrent_mode_failure();
@@ -3161,6 +3135,119 @@
return NULL; // keep some compilers happy
}
+// TODO: VerifyRootsClosure extends OopsInGenClosure so that we can
+// pass it as the perm_blk to SharedHeap::process_strong_roots.
+// When process_strong_roots stop calling perm_blk->younger_refs_iterate
+// we can change this closure to extend the simpler OopClosure.
+class VerifyRootsClosure: public OopsInGenClosure {
+private:
+ G1CollectedHeap* _g1h;
+ VerifyOption _vo;
+ bool _failures;
+public:
+ // _vo == UsePrevMarking -> use "prev" marking information,
+ // _vo == UseNextMarking -> use "next" marking information,
+ // _vo == UseMarkWord -> use mark word from object header.
+ VerifyRootsClosure(VerifyOption vo) :
+ _g1h(G1CollectedHeap::heap()),
+ _vo(vo),
+ _failures(false) { }
+
+ bool failures() { return _failures; }
+
+ template void do_oop_nv(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ if (_g1h->is_obj_dead_cond(obj, _vo)) {
+ gclog_or_tty->print_cr("Root location "PTR_FORMAT" "
+ "points to dead obj "PTR_FORMAT, p, (void*) obj);
+ if (_vo == VerifyOption_G1UseMarkWord) {
+ gclog_or_tty->print_cr(" Mark word: "PTR_FORMAT, (void*)(obj->mark()));
+ }
+ obj->print_on(gclog_or_tty);
+ _failures = true;
+ }
+ }
+ }
+
+ void do_oop(oop* p) { do_oop_nv(p); }
+ void do_oop(narrowOop* p) { do_oop_nv(p); }
+};
+
+class G1VerifyCodeRootOopClosure: public OopsInGenClosure {
+ G1CollectedHeap* _g1h;
+ OopClosure* _root_cl;
+ nmethod* _nm;
+ VerifyOption _vo;
+ bool _failures;
+
+ template void do_oop_work(T* p) {
+ // First verify that this root is live
+ _root_cl->do_oop(p);
+
+ if (!G1VerifyHeapRegionCodeRoots) {
+ // We're not verifying the code roots attached to heap region.
+ return;
+ }
+
+ // Don't check the code roots during marking verification in a full GC
+ if (_vo == VerifyOption_G1UseMarkWord) {
+ return;
+ }
+
+ // Now verify that the current nmethod (which contains p) is
+ // in the code root list of the heap region containing the
+ // object referenced by p.
+
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+
+ if (_g1h->is_in_g1_reserved(obj)) {
+ // Now fetch the region containing the object
+ HeapRegion* hr = _g1h->heap_region_containing(obj);
+ HeapRegionRemSet* hrrs = hr->rem_set();
+ // Verify that the strong code root list for this region
+ // contains the nmethod
+ if (!hrrs->strong_code_roots_list_contains(_nm)) {
+ gclog_or_tty->print_cr("Code root location "PTR_FORMAT" "
+ "from nmethod "PTR_FORMAT" not in strong "
+ "code roots for region ["PTR_FORMAT","PTR_FORMAT")",
+ p, _nm, hr->bottom(), hr->end());
+ _failures = true;
+ }
+ }
+ }
+ }
+
+public:
+ G1VerifyCodeRootOopClosure(G1CollectedHeap* g1h, OopClosure* root_cl, VerifyOption vo):
+ _g1h(g1h), _root_cl(root_cl), _vo(vo), _nm(NULL), _failures(false) {}
+
+ void do_oop(oop* p) { do_oop_work(p); }
+ void do_oop(narrowOop* p) { do_oop_work(p); }
+
+ void set_nmethod(nmethod* nm) { _nm = nm; }
+ bool failures() { return _failures; }
+};
+
+class G1VerifyCodeRootBlobClosure: public CodeBlobClosure {
+ G1VerifyCodeRootOopClosure* _oop_cl;
+
+public:
+ G1VerifyCodeRootBlobClosure(G1VerifyCodeRootOopClosure* oop_cl):
+ _oop_cl(oop_cl) {}
+
+ void do_code_blob(CodeBlob* cb) {
+ nmethod* nm = cb->as_nmethod_or_null();
+ if (nm != NULL) {
+ _oop_cl->set_nmethod(nm);
+ nm->oops_do(_oop_cl);
+ }
+ }
+};
+
class VerifyLivenessOopClosure: public OopClosure {
G1CollectedHeap* _g1h;
VerifyOption _vo;
@@ -3294,42 +3381,6 @@
}
};
-class VerifyRootsClosure: public OopsInGenClosure {
-private:
- G1CollectedHeap* _g1h;
- VerifyOption _vo;
- bool _failures;
-public:
- // _vo == UsePrevMarking -> use "prev" marking information,
- // _vo == UseNextMarking -> use "next" marking information,
- // _vo == UseMarkWord -> use mark word from object header.
- VerifyRootsClosure(VerifyOption vo) :
- _g1h(G1CollectedHeap::heap()),
- _vo(vo),
- _failures(false) { }
-
- bool failures() { return _failures; }
-
- template void do_oop_nv(T* p) {
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop)) {
- oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- if (_g1h->is_obj_dead_cond(obj, _vo)) {
- gclog_or_tty->print_cr("Root location "PTR_FORMAT" "
- "points to dead obj "PTR_FORMAT, p, (void*) obj);
- if (_vo == VerifyOption_G1UseMarkWord) {
- gclog_or_tty->print_cr(" Mark word: "PTR_FORMAT, (void*)(obj->mark()));
- }
- obj->print_on(gclog_or_tty);
- _failures = true;
- }
- }
- }
-
- void do_oop(oop* p) { do_oop_nv(p); }
- void do_oop(narrowOop* p) { do_oop_nv(p); }
-};
-
// This is the task used for parallel heap verification.
class G1ParVerifyTask: public AbstractGangTask {
@@ -3364,21 +3415,16 @@
}
};
-void G1CollectedHeap::verify(bool silent) {
- verify(silent, VerifyOption_G1UsePrevMarking);
-}
-
-void G1CollectedHeap::verify(bool silent,
- VerifyOption vo) {
+void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
if (SafepointSynchronize::is_at_safepoint()) {
+ assert(Thread::current()->is_VM_thread(),
+ "Expected to be executed serially by the VM thread at this point");
+
if (!silent) { gclog_or_tty->print("Roots (excluding permgen) "); }
VerifyRootsClosure rootsCl(vo);
- assert(Thread::current()->is_VM_thread(),
- "Expected to be executed serially by the VM thread at this point");
-
- CodeBlobToOopClosure blobsCl(&rootsCl, /*do_marking=*/ false);
-
+ G1VerifyCodeRootOopClosure codeRootsCl(this, &rootsCl, vo);
+ G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl);
// We apply the relevant closures to all the oops in the
// system dictionary, the string table and the code cache.
const int so = SO_AllClasses | SO_Strings | SO_CodeCache;
@@ -3473,6 +3519,34 @@
}
}
+void G1CollectedHeap::verify(bool silent) {
+ verify(silent, VerifyOption_G1UsePrevMarking);
+}
+
+double G1CollectedHeap::verify(bool guard, const char* msg) {
+ double verify_time_ms = 0.0;
+
+ if (guard && total_collections() >= VerifyGCStartAt) {
+ double verify_start = os::elapsedTime();
+ HandleMark hm; // Discard invalid handles created during verification
+ prepare_for_verify();
+ Universe::verify(VerifyOption_G1UsePrevMarking, msg);
+ verify_time_ms = (os::elapsedTime() - verify_start) * 1000;
+ }
+
+ return verify_time_ms;
+}
+
+void G1CollectedHeap::verify_before_gc() {
+ double verify_time_ms = verify(VerifyBeforeGC, " VerifyBeforeGC:");
+ g1_policy()->phase_times()->record_verify_before_time_ms(verify_time_ms);
+}
+
+void G1CollectedHeap::verify_after_gc() {
+ double verify_time_ms = verify(VerifyAfterGC, " VerifyAfterGC:");
+ g1_policy()->phase_times()->record_verify_after_time_ms(verify_time_ms);
+}
+
class PrintRegionClosure: public HeapRegionClosure {
outputStream* _st;
public:
@@ -3616,9 +3690,22 @@
AllocationProfiler::iterate_since_last_gc();
// Fill TLAB's and such
ensure_parsability(true);
+
+ if (G1SummarizeRSetStats && (G1SummarizeRSetStatsPeriod > 0) &&
+ (total_collections() % G1SummarizeRSetStatsPeriod == 0)) {
+ g1_rem_set()->print_periodic_summary_info("Before GC RS summary");
+ }
}
void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) {
+
+ if (G1SummarizeRSetStats &&
+ (G1SummarizeRSetStatsPeriod > 0) &&
+ // we are at the end of the GC. Total collections has already been increased.
+ ((total_collections() - 1) % G1SummarizeRSetStatsPeriod == 0)) {
+ g1_rem_set()->print_periodic_summary_info("After GC RS summary");
+ }
+
// FIXME: what is this about?
// I'm ignoring the "fill_newgen()" call if "alloc_event_enabled"
// is set.
@@ -3815,7 +3902,7 @@
return false;
}
- _gc_timer_stw->register_gc_start(os::elapsed_counter());
+ _gc_timer_stw->register_gc_start();
_gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start());
@@ -3880,8 +3967,9 @@
append_secondary_free_list_if_not_empty_with_lock();
}
- assert(check_young_list_well_formed(),
- "young list should be well formed");
+ assert(check_young_list_well_formed(), "young list should be well formed");
+ assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
+ "sanity check");
// Don't dynamically change the number of GC threads this early. A value of
// 0 is used to indicate serial work. When parallel work is done,
@@ -4193,15 +4281,10 @@
_gc_tracer_stw->report_evacuation_info(&evacuation_info);
_gc_tracer_stw->report_tenuring_threshold(_g1_policy->tenuring_threshold());
- _gc_timer_stw->register_gc_end(os::elapsed_counter());
+ _gc_timer_stw->register_gc_end();
_gc_tracer_stw->report_gc_end(_gc_timer_stw->gc_end(), _gc_timer_stw->time_partitions());
}
- if (G1SummarizeRSetStats &&
- (G1SummarizeRSetStatsPeriod > 0) &&
- (total_collections() % G1SummarizeRSetStatsPeriod == 0)) {
- g1_rem_set()->print_summary_info();
- }
// It should now be safe to tell the concurrent mark thread to start
// without its logging output interfering with the logging output
// that came from the pause.
@@ -4482,7 +4565,7 @@
: _g1h(g1h),
_refs(g1h->task_queue(queue_num)),
_dcq(&g1h->dirty_card_queue_set()),
- _ct_bs((CardTableModRefBS*)_g1h->barrier_set()),
+ _ct_bs(g1h->g1_barrier_set()),
_g1_rem(g1h->g1_rem_set()),
_hash_seed(17), _queue_num(queue_num),
_term_attempts(0),
@@ -4975,7 +5058,8 @@
scan_root_cl,
&push_heap_rs_cl,
scan_perm_cl,
- worker_id);
+ worker_id,
+ /* manages_code_roots */ true);
pss.end_strong_roots();
{
@@ -5009,67 +5093,6 @@
// *** Common G1 Evacuation Stuff
-// Closures that support the filtering of CodeBlobs scanned during
-// external root scanning.
-
-// Closure applied to reference fields in code blobs (specifically nmethods)
-// to determine whether an nmethod contains references that point into
-// the collection set. Used as a predicate when walking code roots so
-// that only nmethods that point into the collection set are added to the
-// 'marked' list.
-
-class G1FilteredCodeBlobToOopClosure : public CodeBlobToOopClosure {
-
- class G1PointsIntoCSOopClosure : public OopClosure {
- G1CollectedHeap* _g1;
- bool _points_into_cs;
- public:
- G1PointsIntoCSOopClosure(G1CollectedHeap* g1) :
- _g1(g1), _points_into_cs(false) { }
-
- bool points_into_cs() const { return _points_into_cs; }
-
- template
- void do_oop_nv(T* p) {
- if (!_points_into_cs) {
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop) &&
- _g1->in_cset_fast_test(oopDesc::decode_heap_oop_not_null(heap_oop))) {
- _points_into_cs = true;
- }
- }
- }
-
- virtual void do_oop(oop* p) { do_oop_nv(p); }
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
- };
-
- G1CollectedHeap* _g1;
-
-public:
- G1FilteredCodeBlobToOopClosure(G1CollectedHeap* g1, OopClosure* cl) :
- CodeBlobToOopClosure(cl, true), _g1(g1) { }
-
- virtual void do_code_blob(CodeBlob* cb) {
- nmethod* nm = cb->as_nmethod_or_null();
- if (nm != NULL && !(nm->test_oops_do_mark())) {
- G1PointsIntoCSOopClosure predicate_cl(_g1);
- nm->oops_do(&predicate_cl);
-
- if (predicate_cl.points_into_cs()) {
- // At least one of the reference fields or the oop relocations
- // in the nmethod points into the collection set. We have to
- // 'mark' this nmethod.
- // Note: Revisit the following if CodeBlobToOopClosure::do_code_blob()
- // or MarkingCodeBlobClosure::do_code_blob() change.
- if (!nm->test_set_oops_do_mark()) {
- do_newly_marked_nmethod(nm);
- }
- }
- }
- }
-};
-
// This method is run in a GC worker.
void
@@ -5079,7 +5102,8 @@
OopClosure* scan_non_heap_roots,
OopsInHeapRegionClosure* scan_rs,
OopsInGenClosure* scan_perm,
- int worker_i) {
+ int worker_i,
+ bool manages_code_roots) {
// First scan the strong roots, including the perm gen.
double ext_roots_start = os::elapsedTime();
@@ -5089,15 +5113,17 @@
BufferingOopsInGenClosure buf_scan_perm(scan_perm);
buf_scan_perm.set_generation(perm_gen());
- // Walk the code cache w/o buffering, because StarTask cannot handle
- // unaligned oop locations.
- G1FilteredCodeBlobToOopClosure eager_scan_code_roots(this, scan_non_heap_roots);
+ assert(so & SO_CodeCache || scan_rs != NULL, "must scan code roots somehow");
+ // Walk the code cache/strong code roots w/o buffering, because StarTask
+ // cannot handle unaligned oop locations.
+ CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, true /* do_marking */);
process_strong_roots(false, // no scoping; this is parallel code
collecting_perm_gen, so,
&buf_scan_non_heap_roots,
&eager_scan_code_roots,
- &buf_scan_perm);
+ &buf_scan_perm,
+ manages_code_roots);
// Now the CM ref_processor roots.
if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) {
@@ -5136,9 +5162,22 @@
}
g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms);
+ // If this is an initial mark pause, and we're not scanning
+ // the entire code cache, we need to mark the oops in the
+ // strong code root lists for the regions that are not in
+ // the collection set.
+ // Note all threads participate in this set of root tasks.
+ double mark_strong_code_roots_ms = 0.0;
+ if (g1_policy()->during_initial_mark_pause() && !(so & SO_CodeCache)) {
+ double mark_strong_roots_start = os::elapsedTime();
+ mark_strong_code_roots(worker_i);
+ mark_strong_code_roots_ms = (os::elapsedTime() - mark_strong_roots_start) * 1000.0;
+ }
+ g1_policy()->phase_times()->record_strong_code_root_mark_time(worker_i, mark_strong_code_roots_ms);
+
// Now scan the complement of the collection set.
if (scan_rs != NULL) {
- g1_rem_set()->oops_into_collection_set_do(scan_rs, worker_i);
+ g1_rem_set()->oops_into_collection_set_do(scan_rs, &eager_scan_code_roots, worker_i);
}
_process_strong_tasks->all_tasks_completed();
@@ -5151,6 +5190,102 @@
SharedHeap::process_weak_roots(root_closure, &roots_in_blobs, non_root_closure);
}
+class G1StringSymbolTableUnlinkTask : public AbstractGangTask {
+private:
+ BoolObjectClosure* _is_alive;
+ int _initial_string_table_size;
+ int _initial_symbol_table_size;
+
+ bool _process_strings;
+ int _strings_processed;
+ int _strings_removed;
+
+ bool _process_symbols;
+ int _symbols_processed;
+ int _symbols_removed;
+
+ bool _do_in_parallel;
+public:
+ G1StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) :
+ AbstractGangTask("Par String/Symbol table unlink"), _is_alive(is_alive),
+ _do_in_parallel(G1CollectedHeap::use_parallel_gc_threads()),
+ _process_strings(process_strings), _strings_processed(0), _strings_removed(0),
+ _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0) {
+
+ _initial_string_table_size = StringTable::the_table()->table_size();
+ _initial_symbol_table_size = SymbolTable::the_table()->table_size();
+ if (process_strings) {
+ StringTable::clear_parallel_claimed_index();
+ }
+ if (process_symbols) {
+ SymbolTable::clear_parallel_claimed_index();
+ }
+ }
+
+ ~G1StringSymbolTableUnlinkTask() {
+ guarantee(!_process_strings || !_do_in_parallel || StringTable::parallel_claimed_index() >= _initial_string_table_size,
+ err_msg("claim value "INT32_FORMAT" after unlink less than initial string table size "INT32_FORMAT,
+ StringTable::parallel_claimed_index(), _initial_string_table_size));
+ guarantee(!_process_symbols || !_do_in_parallel || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
+ err_msg("claim value "INT32_FORMAT" after unlink less than initial symbol table size "INT32_FORMAT,
+ SymbolTable::parallel_claimed_index(), _initial_symbol_table_size));
+ }
+
+ void work(uint worker_id) {
+ if (_do_in_parallel) {
+ int strings_processed = 0;
+ int strings_removed = 0;
+ int symbols_processed = 0;
+ int symbols_removed = 0;
+ if (_process_strings) {
+ StringTable::possibly_parallel_unlink(_is_alive, &strings_processed, &strings_removed);
+ Atomic::add(strings_processed, &_strings_processed);
+ Atomic::add(strings_removed, &_strings_removed);
+ }
+ if (_process_symbols) {
+ SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed);
+ Atomic::add(symbols_processed, &_symbols_processed);
+ Atomic::add(symbols_removed, &_symbols_removed);
+ }
+ } else {
+ if (_process_strings) {
+ StringTable::unlink(_is_alive, &_strings_processed, &_strings_removed);
+ }
+ if (_process_symbols) {
+ SymbolTable::unlink(&_symbols_processed, &_symbols_removed);
+ }
+ }
+ }
+
+ size_t strings_processed() const { return (size_t)_strings_processed; }
+ size_t strings_removed() const { return (size_t)_strings_removed; }
+
+ size_t symbols_processed() const { return (size_t)_symbols_processed; }
+ size_t symbols_removed() const { return (size_t)_symbols_removed; }
+};
+
+void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive,
+ bool process_strings, bool process_symbols) {
+ uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
+ _g1h->workers()->active_workers() : 1);
+
+ G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols);
+ if (G1CollectedHeap::use_parallel_gc_threads()) {
+ set_par_threads(n_workers);
+ workers()->run_task(&g1_unlink_task);
+ set_par_threads(0);
+ } else {
+ g1_unlink_task.work(0);
+ }
+ if (G1TraceStringSymbolTableScrubbing) {
+ gclog_or_tty->print_cr("Cleaned string and symbol table, "
+ "strings: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed, "
+ "symbols: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed",
+ g1_unlink_task.strings_processed(), g1_unlink_task.strings_removed(),
+ g1_unlink_task.symbols_processed(), g1_unlink_task.symbols_removed());
+ }
+}
+
// Weak Reference Processing support
// An always "is_alive" closure that is used to preserve referents.
@@ -5761,9 +5896,6 @@
process_discovered_references(n_workers);
// Weak root processing.
- // Note: when JSR 292 is enabled and code blobs can contain
- // non-perm oops then we will need to process the code blobs
- // here too.
{
G1STWIsAliveClosure is_alive(this);
G1KeepAliveClosure keep_alive(this);
@@ -5779,6 +5911,17 @@
hot_card_cache->reset_hot_cache();
hot_card_cache->set_use_cache(true);
+ // Migrate the strong code roots attached to each region in
+ // the collection set. Ideally we would like to do this
+ // after we have finished the scanning/evacuation of the
+ // strong code roots for a particular heap region.
+ migrate_strong_code_roots();
+
+ if (g1_policy()->during_initial_mark_pause()) {
+ // Reset the claim values set during marking the strong code roots
+ reset_heap_region_claim_values();
+ }
+
finalize_for_evac_failure();
if (evacuation_failed()) {
@@ -5912,11 +6055,11 @@
}
class G1ParCleanupCTTask : public AbstractGangTask {
- CardTableModRefBS* _ct_bs;
+ G1SATBCardTableModRefBS* _ct_bs;
G1CollectedHeap* _g1h;
HeapRegion* volatile _su_head;
public:
- G1ParCleanupCTTask(CardTableModRefBS* ct_bs,
+ G1ParCleanupCTTask(G1SATBCardTableModRefBS* ct_bs,
G1CollectedHeap* g1h) :
AbstractGangTask("G1 Par Cleanup CT Task"),
_ct_bs(ct_bs), _g1h(g1h) { }
@@ -5939,9 +6082,9 @@
#ifndef PRODUCT
class G1VerifyCardTableCleanup: public HeapRegionClosure {
G1CollectedHeap* _g1h;
- CardTableModRefBS* _ct_bs;
+ G1SATBCardTableModRefBS* _ct_bs;
public:
- G1VerifyCardTableCleanup(G1CollectedHeap* g1h, CardTableModRefBS* ct_bs)
+ G1VerifyCardTableCleanup(G1CollectedHeap* g1h, G1SATBCardTableModRefBS* ct_bs)
: _g1h(g1h), _ct_bs(ct_bs) { }
virtual bool doHeapRegion(HeapRegion* r) {
if (r->is_survivor()) {
@@ -5955,7 +6098,7 @@
void G1CollectedHeap::verify_not_dirty_region(HeapRegion* hr) {
// All of the region should be clean.
- CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set();
+ G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
MemRegion mr(hr->bottom(), hr->end());
ct_bs->verify_not_dirty_region(mr);
}
@@ -5968,13 +6111,17 @@
// not dirty that area (one less thing to have to do while holding
// a lock). So we can only verify that [bottom(),pre_dummy_top()]
// is dirty.
- CardTableModRefBS* ct_bs = (CardTableModRefBS*) barrier_set();
+ G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
MemRegion mr(hr->bottom(), hr->pre_dummy_top());
- ct_bs->verify_dirty_region(mr);
+ if (hr->is_young()) {
+ ct_bs->verify_g1_young_region(mr);
+ } else {
+ ct_bs->verify_dirty_region(mr);
+ }
}
void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) {
- CardTableModRefBS* ct_bs = (CardTableModRefBS*) barrier_set();
+ G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
for (HeapRegion* hr = head; hr != NULL; hr = hr->get_next_young_region()) {
verify_dirty_region(hr);
}
@@ -5986,7 +6133,7 @@
#endif
void G1CollectedHeap::cleanUpCardTable() {
- CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set());
+ G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
double start = os::elapsedTime();
{
@@ -6575,3 +6722,234 @@
_humongous_set.verify_end();
_free_list.verify_end();
}
+
+// Optimized nmethod scanning
+
+class RegisterNMethodOopClosure: public OopClosure {
+ G1CollectedHeap* _g1h;
+ nmethod* _nm;
+
+ template void do_oop_work(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ HeapRegion* hr = _g1h->heap_region_containing(obj);
+ if (hr == NULL) {
+ // reference into perm gen - ignore.
+ assert(_g1h->is_in_permanent(obj), "must be a reference into perm gen");
+ return;
+ }
+ assert(!hr->continuesHumongous(),
+ err_msg("trying to add code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
+ " starting at "HR_FORMAT,
+ _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
+
+ // HeapRegion::add_strong_code_root() avoids adding duplicate
+ // entries but having duplicates is OK since we "mark" nmethods
+ // as visited when we scan the strong code root lists during the GC.
+ hr->add_strong_code_root(_nm);
+ assert(hr->rem_set()->strong_code_roots_list_contains(_nm),
+ err_msg("failed to add code root "PTR_FORMAT" to remembered set of region "HR_FORMAT,
+ _nm, HR_FORMAT_PARAMS(hr)));
+ }
+ }
+
+public:
+ RegisterNMethodOopClosure(G1CollectedHeap* g1h, nmethod* nm) :
+ _g1h(g1h), _nm(nm) {}
+
+ void do_oop(oop* p) { do_oop_work(p); }
+ void do_oop(narrowOop* p) { do_oop_work(p); }
+};
+
+class UnregisterNMethodOopClosure: public OopClosure {
+ G1CollectedHeap* _g1h;
+ nmethod* _nm;
+
+ template void do_oop_work(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ HeapRegion* hr = _g1h->heap_region_containing(obj);
+ if (hr == NULL) {
+ // reference into perm gen - ignore.
+ assert(_g1h->is_in_permanent(obj), "must be a reference into perm gen");
+ return;
+ }
+ assert(!hr->continuesHumongous(),
+ err_msg("trying to remove code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
+ " starting at "HR_FORMAT,
+ _nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
+
+ hr->remove_strong_code_root(_nm);
+ assert(!hr->rem_set()->strong_code_roots_list_contains(_nm),
+ err_msg("failed to remove code root "PTR_FORMAT" of region "HR_FORMAT,
+ _nm, HR_FORMAT_PARAMS(hr))); }
+ }
+
+public:
+ UnregisterNMethodOopClosure(G1CollectedHeap* g1h, nmethod* nm) :
+ _g1h(g1h), _nm(nm) {}
+
+ void do_oop(oop* p) { do_oop_work(p); }
+ void do_oop(narrowOop* p) { do_oop_work(p); }
+};
+
+void G1CollectedHeap::register_nmethod(nmethod* nm) {
+ CollectedHeap::register_nmethod(nm);
+
+ guarantee(nm != NULL, "sanity");
+ RegisterNMethodOopClosure reg_cl(this, nm);
+ nm->oops_do(®_cl);
+}
+
+void G1CollectedHeap::unregister_nmethod(nmethod* nm) {
+ CollectedHeap::unregister_nmethod(nm);
+
+ guarantee(nm != NULL, "sanity");
+ UnregisterNMethodOopClosure reg_cl(this, nm);
+ nm->oops_do(®_cl, false, true);
+}
+
+class MigrateCodeRootsHeapRegionClosure: public HeapRegionClosure {
+public:
+ bool doHeapRegion(HeapRegion *hr) {
+ assert(!hr->isHumongous(),
+ err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
+ HR_FORMAT_PARAMS(hr)));
+ hr->migrate_strong_code_roots();
+ return false;
+ }
+};
+
+void G1CollectedHeap::migrate_strong_code_roots() {
+ MigrateCodeRootsHeapRegionClosure cl;
+ double migrate_start = os::elapsedTime();
+ collection_set_iterate(&cl);
+ double migration_time_ms = (os::elapsedTime() - migrate_start) * 1000.0;
+ g1_policy()->phase_times()->record_strong_code_root_migration_time(migration_time_ms);
+}
+
+// Mark all the code roots that point into regions *not* in the
+// collection set.
+//
+// Note we do not want to use a "marking" CodeBlobToOopClosure while
+// walking the the code roots lists of regions not in the collection
+// set. Suppose we have an nmethod (M) that points to objects in two
+// separate regions - one in the collection set (R1) and one not (R2).
+// Using a "marking" CodeBlobToOopClosure here would result in "marking"
+// nmethod M when walking the code roots for R1. When we come to scan
+// the code roots for R2, we would see that M is already marked and it
+// would be skipped and the objects in R2 that are referenced from M
+// would not be evacuated.
+
+class MarkStrongCodeRootCodeBlobClosure: public CodeBlobClosure {
+
+ class MarkStrongCodeRootOopClosure: public OopClosure {
+ ConcurrentMark* _cm;
+ HeapRegion* _hr;
+ uint _worker_id;
+
+ template void do_oop_work(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ // Only mark objects in the region (which is assumed
+ // to be not in the collection set).
+ if (_hr->is_in(obj)) {
+ _cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
+ }
+ }
+ }
+
+ public:
+ MarkStrongCodeRootOopClosure(ConcurrentMark* cm, HeapRegion* hr, uint worker_id) :
+ _cm(cm), _hr(hr), _worker_id(worker_id) {
+ assert(!_hr->in_collection_set(), "sanity");
+ }
+
+ void do_oop(narrowOop* p) { do_oop_work(p); }
+ void do_oop(oop* p) { do_oop_work(p); }
+ };
+
+ MarkStrongCodeRootOopClosure _oop_cl;
+
+public:
+ MarkStrongCodeRootCodeBlobClosure(ConcurrentMark* cm, HeapRegion* hr, uint worker_id):
+ _oop_cl(cm, hr, worker_id) {}
+
+ void do_code_blob(CodeBlob* cb) {
+ nmethod* nm = (cb == NULL) ? NULL : cb->as_nmethod_or_null();
+ if (nm != NULL) {
+ nm->oops_do(&_oop_cl);
+ }
+ }
+};
+
+class MarkStrongCodeRootsHRClosure: public HeapRegionClosure {
+ G1CollectedHeap* _g1h;
+ uint _worker_id;
+
+public:
+ MarkStrongCodeRootsHRClosure(G1CollectedHeap* g1h, uint worker_id) :
+ _g1h(g1h), _worker_id(worker_id) {}
+
+ bool doHeapRegion(HeapRegion *hr) {
+ HeapRegionRemSet* hrrs = hr->rem_set();
+ if (hr->continuesHumongous()) {
+ // Code roots should never be attached to a continuation of a humongous region
+ assert(hrrs->strong_code_roots_list_length() == 0,
+ err_msg("code roots should never be attached to continuations of humongous region "HR_FORMAT
+ " starting at "HR_FORMAT", but has "INT32_FORMAT,
+ HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()),
+ hrrs->strong_code_roots_list_length()));
+ return false;
+ }
+
+ if (hr->in_collection_set()) {
+ // Don't mark code roots into regions in the collection set here.
+ // They will be marked when we scan them.
+ return false;
+ }
+
+ MarkStrongCodeRootCodeBlobClosure cb_cl(_g1h->concurrent_mark(), hr, _worker_id);
+ hr->strong_code_roots_do(&cb_cl);
+ return false;
+ }
+};
+
+void G1CollectedHeap::mark_strong_code_roots(uint worker_id) {
+ MarkStrongCodeRootsHRClosure cl(this, worker_id);
+ if (G1CollectedHeap::use_parallel_gc_threads()) {
+ heap_region_par_iterate_chunked(&cl,
+ worker_id,
+ workers()->active_workers(),
+ HeapRegion::ParMarkRootClaimValue);
+ } else {
+ heap_region_iterate(&cl);
+ }
+}
+
+class RebuildStrongCodeRootClosure: public CodeBlobClosure {
+ G1CollectedHeap* _g1h;
+
+public:
+ RebuildStrongCodeRootClosure(G1CollectedHeap* g1h) :
+ _g1h(g1h) {}
+
+ void do_code_blob(CodeBlob* cb) {
+ nmethod* nm = (cb != NULL) ? cb->as_nmethod_or_null() : NULL;
+ if (nm == NULL) {
+ return;
+ }
+
+ if (ScavengeRootsInCode && nm->detect_scavenge_root_oops()) {
+ _g1h->register_nmethod(nm);
+ }
+ }
+};
+
+void G1CollectedHeap::rebuild_strong_code_roots() {
+ RebuildStrongCodeRootClosure blob_cl(this);
+ CodeCache::blobs_do(&blob_cl);
+}
--- ./hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed May 07 19:26:16 2014 -0700
@@ -31,6 +31,7 @@
#include "gc_implementation/g1/g1HRPrinter.hpp"
#include "gc_implementation/g1/g1MonitoringSupport.hpp"
#include "gc_implementation/g1/g1RemSet.hpp"
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/g1/g1YCTypes.hpp"
#include "gc_implementation/g1/heapRegionSeq.hpp"
#include "gc_implementation/g1/heapRegionSets.hpp"
@@ -46,6 +47,7 @@
// may combine concurrent marking with parallel, incremental compaction of
// heap subsets that will yield large amounts of garbage.
+// Forward declarations
class HeapRegion;
class HRRSCleanupTask;
class PermanentGenerationSpec;
@@ -69,6 +71,8 @@
class G1NewTracer;
class G1OldTracer;
class EvacuationFailedInfo;
+class nmethod;
+class Ticks;
typedef OverflowTaskQueue RefToScanQueue;
typedef GenericTaskQueueSet RefToScanQueueSet;
@@ -163,19 +167,6 @@
: G1AllocRegion("Mutator Alloc Region", false /* bot_updates */) { }
};
-// The G1 STW is alive closure.
-// An instance is embedded into the G1CH and used as the
-// (optional) _is_alive_non_header closure in the STW
-// reference processor. It is also extensively used during
-// reference processing during STW evacuation pauses.
-class G1STWIsAliveClosure: public BoolObjectClosure {
- G1CollectedHeap* _g1;
-public:
- G1STWIsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {}
- void do_object(oop p) { assert(false, "Do not call."); }
- bool do_object_b(oop p);
-};
-
class SurvivorGCAllocRegion : public G1AllocRegion {
protected:
virtual HeapRegion* allocate_new_region(size_t word_size, bool force);
@@ -194,6 +185,19 @@
: G1AllocRegion("Old GC Alloc Region", true /* bot_updates */) { }
};
+// The G1 STW is alive closure.
+// An instance is embedded into the G1CH and used as the
+// (optional) _is_alive_non_header closure in the STW
+// reference processor. It is also extensively used during
+// reference processing during STW evacuation pauses.
+class G1STWIsAliveClosure: public BoolObjectClosure {
+ G1CollectedHeap* _g1;
+public:
+ G1STWIsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {}
+ void do_object(oop p) { assert(false, "Do not call."); }
+ bool do_object_b(oop p);
+};
+
class RefineCardTableEntryClosure;
class G1CollectedHeap : public SharedHeap {
@@ -747,7 +751,7 @@
return _old_marking_cycles_completed;
}
- void register_concurrent_cycle_start(jlong start_time);
+ void register_concurrent_cycle_start(const Ticks& start_time);
void register_concurrent_cycle_end();
void trace_heap_after_concurrent_cycle();
@@ -792,8 +796,6 @@
// The g1 remembered set of the heap.
G1RemSet* _g1_rem_set;
- // And it's mod ref barrier set, used to track updates for the above.
- ModRefBarrierSet* _mr_bs;
// A set of cards that cover the objects for which the Rsets should be updated
// concurrently after the collection.
@@ -835,7 +837,8 @@
OopClosure* scan_non_heap_roots,
OopsInHeapRegionClosure* scan_rs,
OopsInGenClosure* scan_perm,
- int worker_i);
+ int worker_i,
+ bool manages_code_roots = false);
// Apply "blk" to all the weak roots of the system. These include
// JNI weak roots, the code cache, system dictionary, symbol table,
@@ -1127,7 +1130,6 @@
// The rem set and barrier set.
G1RemSet* g1_rem_set() const { return _g1_rem_set; }
- ModRefBarrierSet* mr_bs() const { return _mr_bs; }
// The rem set iterator.
HeapRegionRemSetIterator* rem_set_iterator(int i) {
@@ -1361,6 +1363,10 @@
virtual bool is_in_closed_subset(const void* p) const;
+ G1SATBCardTableModRefBS* g1_barrier_set() {
+ return (G1SATBCardTableModRefBS*) barrier_set();
+ }
+
// This resets the card table to all zeros. It is used after
// a collection pause which used the card table to claim cards.
void cleanUpCardTable();
@@ -1592,41 +1598,6 @@
virtual jlong millis_since_last_gc();
- // Perform any cleanup actions necessary before allowing a verification.
- virtual void prepare_for_verify();
-
- // Perform verification.
-
- // vo == UsePrevMarking -> use "prev" marking information,
- // vo == UseNextMarking -> use "next" marking information
- // vo == UseMarkWord -> use the mark word in the object header
- //
- // NOTE: Only the "prev" marking information is guaranteed to be
- // consistent most of the time, so most calls to this should use
- // vo == UsePrevMarking.
- // Currently, there is only one case where this is called with
- // vo == UseNextMarking, which is to verify the "next" marking
- // information at the end of remark.
- // Currently there is only one place where this is called with
- // vo == UseMarkWord, which is to verify the marking during a
- // full GC.
- void verify(bool silent, VerifyOption vo);
-
- // Override; it uses the "prev" marking information
- virtual void verify(bool silent);
-
- virtual void print_on(outputStream* st) const;
- virtual void print_extended_on(outputStream* st) const;
-
- virtual void print_gc_threads_on(outputStream* st) const;
- virtual void gc_threads_do(ThreadClosure* tc) const;
-
- // Override
- void print_tracing_info() const;
-
- // The following two methods are helpful for debugging RSet issues.
- void print_cset_rsets() PRODUCT_RETURN;
- void print_all_rsets() PRODUCT_RETURN;
// Convenience function to be used in situations where the heap type can be
// asserted to be this type.
@@ -1684,7 +1655,6 @@
// then call the region version of the same function.
// Added if it is in permanent gen it isn't dead.
- // Added if it is NULL it isn't dead.
bool is_obj_dead(const oop obj) const {
const HeapRegion* hr = heap_region_containing(obj);
@@ -1708,13 +1678,90 @@
else return is_obj_ill(obj, hr);
}
+ bool allocated_since_marking(oop obj, HeapRegion* hr, VerifyOption vo);
+ HeapWord* top_at_mark_start(HeapRegion* hr, VerifyOption vo);
+ bool is_marked(oop obj, VerifyOption vo);
+ const char* top_at_mark_start_str(VerifyOption vo);
+
+ ConcurrentMark* concurrent_mark() const { return _cm; }
+
+ // Refinement
+
+ ConcurrentG1Refine* concurrent_g1_refine() const { return _cg1r; }
+
+ // The dirty cards region list is used to record a subset of regions
+ // whose cards need clearing. The list if populated during the
+ // remembered set scanning and drained during the card table
+ // cleanup. Although the methods are reentrant, population/draining
+ // phases must not overlap. For synchronization purposes the last
+ // element on the list points to itself.
+ HeapRegion* _dirty_cards_region_list;
+ void push_dirty_cards_region(HeapRegion* hr);
+ HeapRegion* pop_dirty_cards_region();
+
+ // Optimized nmethod scanning support routines
+
+ // Register the given nmethod with the G1 heap
+ virtual void register_nmethod(nmethod* nm);
+
+ // Unregister the given nmethod from the G1 heap
+ virtual void unregister_nmethod(nmethod* nm);
+
+ // Migrate the nmethods in the code root lists of the regions
+ // in the collection set to regions in to-space. In the event
+ // of an evacuation failure, nmethods that reference objects
+ // that were not successfullly evacuated are not migrated.
+ void migrate_strong_code_roots();
+
+ // During an initial mark pause, mark all the code roots that
+ // point into regions *not* in the collection set.
+ void mark_strong_code_roots(uint worker_id);
+
+ // Rebuild the stong code root lists for each region
+ // after a full GC
+ void rebuild_strong_code_roots();
+
+ // Delete entries for dead interned string and clean up unreferenced symbols
+ // in symbol table, possibly in parallel.
+ void unlink_string_and_symbol_table(BoolObjectClosure* is_alive, bool unlink_strings = true, bool unlink_symbols = true);
+
+ // Verification
+
+ // The following is just to alert the verification code
+ // that a full collection has occurred and that the
+ // remembered sets are no longer up to date.
+ bool _full_collection;
+ void set_full_collection() { _full_collection = true;}
+ void clear_full_collection() {_full_collection = false;}
+ bool full_collection() {return _full_collection;}
+
+ // Perform any cleanup actions necessary before allowing a verification.
+ virtual void prepare_for_verify();
+
+ // Perform verification.
+
+ // vo == UsePrevMarking -> use "prev" marking information,
+ // vo == UseNextMarking -> use "next" marking information
+ // vo == UseMarkWord -> use the mark word in the object header
+ //
+ // NOTE: Only the "prev" marking information is guaranteed to be
+ // consistent most of the time, so most calls to this should use
+ // vo == UsePrevMarking.
+ // Currently, there is only one case where this is called with
+ // vo == UseNextMarking, which is to verify the "next" marking
+ // information at the end of remark.
+ // Currently there is only one place where this is called with
+ // vo == UseMarkWord, which is to verify the marking during a
+ // full GC.
+ void verify(bool silent, VerifyOption vo);
+
+ // Override; it uses the "prev" marking information
+ virtual void verify(bool silent);
+
// The methods below are here for convenience and dispatch the
// appropriate method depending on value of the given VerifyOption
- // parameter. The options for that parameter are:
- //
- // vo == UsePrevMarking -> use "prev" marking information,
- // vo == UseNextMarking -> use "next" marking information,
- // vo == UseMarkWord -> use mark word from object header
+ // parameter. The values for that parameter, and their meanings,
+ // are the same as those above.
bool is_obj_dead_cond(const oop obj,
const HeapRegion* hr,
@@ -1739,31 +1786,20 @@
return false; // keep some compilers happy
}
- bool allocated_since_marking(oop obj, HeapRegion* hr, VerifyOption vo);
- HeapWord* top_at_mark_start(HeapRegion* hr, VerifyOption vo);
- bool is_marked(oop obj, VerifyOption vo);
- const char* top_at_mark_start_str(VerifyOption vo);
+ // Printing
- // The following is just to alert the verification code
- // that a full collection has occurred and that the
- // remembered sets are no longer up to date.
- bool _full_collection;
- void set_full_collection() { _full_collection = true;}
- void clear_full_collection() {_full_collection = false;}
- bool full_collection() {return _full_collection;}
+ virtual void print_on(outputStream* st) const;
+ virtual void print_extended_on(outputStream* st) const;
- ConcurrentMark* concurrent_mark() const { return _cm; }
- ConcurrentG1Refine* concurrent_g1_refine() const { return _cg1r; }
+ virtual void print_gc_threads_on(outputStream* st) const;
+ virtual void gc_threads_do(ThreadClosure* tc) const;
- // The dirty cards region list is used to record a subset of regions
- // whose cards need clearing. The list if populated during the
- // remembered set scanning and drained during the card table
- // cleanup. Although the methods are reentrant, population/draining
- // phases must not overlap. For synchronization purposes the last
- // element on the list points to itself.
- HeapRegion* _dirty_cards_region_list;
- void push_dirty_cards_region(HeapRegion* hr);
- HeapRegion* pop_dirty_cards_region();
+ // Override
+ void print_tracing_info() const;
+
+ // The following two methods are helpful for debugging RSet issues.
+ void print_cset_rsets() PRODUCT_RETURN;
+ void print_all_rsets() PRODUCT_RETURN;
public:
void stop_conc_gc_threads();
@@ -1800,7 +1836,7 @@
G1CollectedHeap* _g1h;
RefToScanQueue* _refs;
DirtyCardQueue _dcq;
- CardTableModRefBS* _ct_bs;
+ G1SATBCardTableModRefBS* _ct_bs;
G1RemSet* _g1_rem;
G1ParGCAllocBuffer _surviving_alloc_buffer;
@@ -1839,7 +1875,7 @@
void add_to_undo_waste(size_t waste) { _undo_waste += waste; }
DirtyCardQueue& dirty_card_queue() { return _dcq; }
- CardTableModRefBS* ctbs() { return _ct_bs; }
+ G1SATBCardTableModRefBS* ctbs() { return _ct_bs; }
template void immediate_rs_update(HeapRegion* from, T* p, int tid) {
if (!from->is_survivor()) {
--- ./hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Wed May 07 19:26:16 2014 -0700
@@ -29,6 +29,7 @@
#include "gc_implementation/g1/g1CollectedHeap.hpp"
#include "gc_implementation/g1/g1AllocRegion.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "utilities/taskqueue.hpp"
@@ -131,7 +132,7 @@
assert(containing_hr->is_in(end - 1), "it should also contain end - 1");
MemRegion mr(start, end);
- ((CardTableModRefBS*)_g1h->barrier_set())->dirty(mr);
+ g1_barrier_set()->g1_mark_as_young(mr);
}
inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
--- ./hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed May 07 19:26:16 2014 -0700
@@ -310,7 +310,8 @@
void G1CollectorPolicy::initialize_flags() {
set_min_alignment(HeapRegion::GrainBytes);
size_t card_table_alignment = GenRemSet::max_alignment_constraint(rem_set_name());
- set_max_alignment(MAX2(card_table_alignment, min_alignment()));
+ size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
+ set_max_alignment(MAX3(card_table_alignment, min_alignment(), page_size));
if (SurvivorRatio < 1) {
vm_exit_during_initialization("Invalid survivor ratio specified");
}
--- ./hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp Wed May 07 19:26:16 2014 -0700
@@ -41,11 +41,11 @@
private:
G1CollectedHeap* _g1;
DirtyCardQueue *_dcq;
- CardTableModRefBS* _ct_bs;
+ G1SATBCardTableModRefBS* _ct_bs;
public:
UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) :
- _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) {}
+ _g1(g1), _ct_bs(_g1->g1_barrier_set()), _dcq(dcq) {}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop( oop* p) { do_oop_work(p); }
--- ./hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Wed May 07 19:26:16 2014 -0700
@@ -161,6 +161,8 @@
_last_update_rs_times_ms(_max_gc_threads, "%.1lf"),
_last_update_rs_processed_buffers(_max_gc_threads, "%d"),
_last_scan_rs_times_ms(_max_gc_threads, "%.1lf"),
+ _last_strong_code_root_scan_times_ms(_max_gc_threads, "%.1lf"),
+ _last_strong_code_root_mark_times_ms(_max_gc_threads, "%.1lf"),
_last_obj_copy_times_ms(_max_gc_threads, "%.1lf"),
_last_termination_times_ms(_max_gc_threads, "%.1lf"),
_last_termination_attempts(_max_gc_threads, SIZE_FORMAT),
@@ -182,6 +184,8 @@
_last_update_rs_times_ms.reset();
_last_update_rs_processed_buffers.reset();
_last_scan_rs_times_ms.reset();
+ _last_strong_code_root_scan_times_ms.reset();
+ _last_strong_code_root_mark_times_ms.reset();
_last_obj_copy_times_ms.reset();
_last_termination_times_ms.reset();
_last_termination_attempts.reset();
@@ -197,6 +201,8 @@
_last_update_rs_times_ms.verify();
_last_update_rs_processed_buffers.verify();
_last_scan_rs_times_ms.verify();
+ _last_strong_code_root_scan_times_ms.verify();
+ _last_strong_code_root_mark_times_ms.verify();
_last_obj_copy_times_ms.verify();
_last_termination_times_ms.verify();
_last_termination_attempts.verify();
@@ -210,6 +216,8 @@
_last_satb_filtering_times_ms.get(i) +
_last_update_rs_times_ms.get(i) +
_last_scan_rs_times_ms.get(i) +
+ _last_strong_code_root_scan_times_ms.get(i) +
+ _last_strong_code_root_mark_times_ms.get(i) +
_last_obj_copy_times_ms.get(i) +
_last_termination_times_ms.get(i);
@@ -239,6 +247,9 @@
// Now subtract the time taken to fix up roots in generated code
misc_time_ms += _cur_collection_code_root_fixup_time_ms;
+ // Strong code root migration time
+ misc_time_ms += _cur_strong_code_root_migration_time_ms;
+
// Subtract the time taken to clean the card table from the
// current value of "other time"
misc_time_ms += _cur_clear_ct_time_ms;
@@ -257,9 +268,13 @@
if (_last_satb_filtering_times_ms.sum() > 0.0) {
_last_satb_filtering_times_ms.print(2, "SATB Filtering (ms)");
}
+ if (_last_strong_code_root_mark_times_ms.sum() > 0.0) {
+ _last_strong_code_root_mark_times_ms.print(2, "Code Root Marking (ms)");
+ }
_last_update_rs_times_ms.print(2, "Update RS (ms)");
_last_update_rs_processed_buffers.print(3, "Processed Buffers");
_last_scan_rs_times_ms.print(2, "Scan RS (ms)");
+ _last_strong_code_root_scan_times_ms.print(2, "Code Root Scanning (ms)");
_last_obj_copy_times_ms.print(2, "Object Copy (ms)");
_last_termination_times_ms.print(2, "Termination (ms)");
if (G1Log::finest()) {
@@ -273,12 +288,17 @@
if (_last_satb_filtering_times_ms.sum() > 0.0) {
_last_satb_filtering_times_ms.print(1, "SATB Filtering (ms)");
}
+ if (_last_strong_code_root_mark_times_ms.sum() > 0.0) {
+ _last_strong_code_root_mark_times_ms.print(1, "Code Root Marking (ms)");
+ }
_last_update_rs_times_ms.print(1, "Update RS (ms)");
_last_update_rs_processed_buffers.print(2, "Processed Buffers");
_last_scan_rs_times_ms.print(1, "Scan RS (ms)");
+ _last_strong_code_root_scan_times_ms.print(1, "Code Root Scanning (ms)");
_last_obj_copy_times_ms.print(1, "Object Copy (ms)");
}
print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
+ print_stats(1, "Code Root Migration", _cur_strong_code_root_migration_time_ms);
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
double misc_time_ms = pause_time_sec * MILLIUNITS - accounted_time_ms();
print_stats(1, "Other", misc_time_ms);
--- ./hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed May 07 19:26:16 2014 -0700
@@ -119,6 +119,8 @@
WorkerDataArray _last_update_rs_times_ms;
WorkerDataArray _last_update_rs_processed_buffers;
WorkerDataArray _last_scan_rs_times_ms;
+ WorkerDataArray _last_strong_code_root_scan_times_ms;
+ WorkerDataArray _last_strong_code_root_mark_times_ms;
WorkerDataArray _last_obj_copy_times_ms;
WorkerDataArray _last_termination_times_ms;
WorkerDataArray _last_termination_attempts;
@@ -128,6 +130,7 @@
double _cur_collection_par_time_ms;
double _cur_collection_code_root_fixup_time_ms;
+ double _cur_strong_code_root_migration_time_ms;
double _cur_clear_ct_time_ms;
double _cur_ref_proc_time_ms;
@@ -179,6 +182,14 @@
_last_scan_rs_times_ms.set(worker_i, ms);
}
+ void record_strong_code_root_scan_time(uint worker_i, double ms) {
+ _last_strong_code_root_scan_times_ms.set(worker_i, ms);
+ }
+
+ void record_strong_code_root_mark_time(uint worker_i, double ms) {
+ _last_strong_code_root_mark_times_ms.set(worker_i, ms);
+ }
+
void record_obj_copy_time(uint worker_i, double ms) {
_last_obj_copy_times_ms.set(worker_i, ms);
}
@@ -208,6 +219,10 @@
_cur_collection_code_root_fixup_time_ms = ms;
}
+ void record_strong_code_root_migration_time(double ms) {
+ _cur_strong_code_root_migration_time_ms = ms;
+ }
+
void record_ref_proc_time(double ms) {
_cur_ref_proc_time_ms = ms;
}
@@ -294,6 +309,14 @@
return _last_scan_rs_times_ms.average();
}
+ double average_last_strong_code_root_scan_time(){
+ return _last_strong_code_root_scan_times_ms.average();
+ }
+
+ double average_last_strong_code_root_mark_time(){
+ return _last_strong_code_root_mark_times_ms.average();
+ }
+
double average_last_obj_copy_time() {
return _last_obj_copy_times_ms.average();
}
--- ./hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Wed May 07 19:26:16 2014 -0700
@@ -177,10 +177,8 @@
GenMarkSweep::follow_mdo_weak_refs();
assert(GenMarkSweep::_marking_stack.is_empty(), "just drained");
- // Visit interned string tables and delete unmarked oops
- StringTable::unlink(&GenMarkSweep::is_alive);
- // Clean up unreferenced symbols in symbol table.
- SymbolTable::unlink();
+ // Delete entries for dead interned string and clean up unreferenced symbols in symbol table.
+ G1CollectedHeap::heap()->unlink_string_and_symbol_table(&GenMarkSweep::is_alive);
assert(GenMarkSweep::_marking_stack.is_empty(),
"stack should be empty by now");
@@ -188,7 +186,6 @@
if (VerifyDuringGC) {
HandleMark hm; // handle scope
COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact);
- gclog_or_tty->print(" VerifyDuringGC:(full)[Verifying ");
Universe::heap()->prepare_for_verify();
// Note: we can verify only the heap here. When an object is
// marked, the previous value of the mark word (including
@@ -200,11 +197,13 @@
// fail. At the end of the GC, the orginal mark word values
// (including hash values) are restored to the appropriate
// objects.
- Universe::heap()->verify(/* silent */ false,
- /* option */ VerifyOption_G1UseMarkWord);
-
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
- gclog_or_tty->print_cr("]");
+ if (!VerifySilently) {
+ gclog_or_tty->print(" VerifyDuringGC:(full)[Verifying ");
+ }
+ Universe::heap()->verify(VerifySilently, VerifyOption_G1UseMarkWord);
+ if (!VerifySilently) {
+ gclog_or_tty->print_cr("]");
+ }
}
gc_tracer()->report_object_count_after_gc(&GenMarkSweep::is_alive);
@@ -235,7 +234,7 @@
public:
G1PrepareCompactClosure(CompactibleSpace* cs)
: _g1h(G1CollectedHeap::heap()),
- _mrbs(G1CollectedHeap::heap()->mr_bs()),
+ _mrbs(_g1h->g1_barrier_set()),
_cp(NULL, cs, cs->initialize_threshold()),
_humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { }
--- ./hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed May 07 19:26:16 2014 -0700
@@ -34,6 +34,7 @@
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
+#include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "memory/iterator.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/intHisto.hpp"
@@ -73,7 +74,8 @@
_ct_bs(ct_bs), _g1p(_g1->g1_policy()),
_cg1r(g1->concurrent_g1_refine()),
_cset_rs_update_cl(NULL),
- _cards_scanned(NULL), _total_cards_scanned(0)
+ _cards_scanned(NULL), _total_cards_scanned(0),
+ _prev_period_summary()
{
_seq_task = new SubTasksDone(NumSeqTasks);
guarantee(n_workers() > 0, "There should be some workers");
@@ -81,6 +83,9 @@
for (uint i = 0; i < n_workers(); i++) {
_cset_rs_update_cl[i] = NULL;
}
+ if (G1SummarizeRSetStats) {
+ _prev_period_summary.initialize(this);
+ }
}
G1RemSet::~G1RemSet() {
@@ -101,15 +106,25 @@
class ScanRSClosure : public HeapRegionClosure {
size_t _cards_done, _cards;
G1CollectedHeap* _g1h;
+
OopsInHeapRegionClosure* _oc;
+ CodeBlobToOopClosure* _code_root_cl;
+
G1BlockOffsetSharedArray* _bot_shared;
- CardTableModRefBS *_ct_bs;
- int _worker_i;
- int _block_size;
- bool _try_claimed;
+ G1SATBCardTableModRefBS *_ct_bs;
+
+ double _strong_code_root_scan_time_sec;
+ int _worker_i;
+ int _block_size;
+ bool _try_claimed;
+
public:
- ScanRSClosure(OopsInHeapRegionClosure* oc, int worker_i) :
+ ScanRSClosure(OopsInHeapRegionClosure* oc,
+ CodeBlobToOopClosure* code_root_cl,
+ int worker_i) :
_oc(oc),
+ _code_root_cl(code_root_cl),
+ _strong_code_root_scan_time_sec(0.0),
_cards(0),
_cards_done(0),
_worker_i(worker_i),
@@ -117,7 +132,7 @@
{
_g1h = G1CollectedHeap::heap();
_bot_shared = _g1h->bot_shared();
- _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set());
+ _ct_bs = _g1h->g1_barrier_set();
_block_size = MAX2(G1RSetScanBlockSize, 1);
}
@@ -157,6 +172,12 @@
card_start, card_start + G1BlockOffsetSharedArray::N_words);
}
+ void scan_strong_code_roots(HeapRegion* r) {
+ double scan_start = os::elapsedTime();
+ r->strong_code_roots_do(_code_root_cl);
+ _strong_code_root_scan_time_sec += (os::elapsedTime() - scan_start);
+ }
+
bool doHeapRegion(HeapRegion* r) {
assert(r->in_collection_set(), "should only be called on elements of CS.");
HeapRegionRemSet* hrrs = r->rem_set();
@@ -170,6 +191,7 @@
// _try_claimed || r->claim_iter()
// is true: either we're supposed to work on claimed-but-not-complete
// regions, or we successfully claimed the region.
+
HeapRegionRemSetIterator* iter = _g1h->rem_set_iterator(_worker_i);
hrrs->init_iterator(iter);
size_t card_index;
@@ -203,30 +225,43 @@
}
}
if (!_try_claimed) {
+ // Scan the strong code root list attached to the current region
+ scan_strong_code_roots(r);
+
hrrs->set_iter_complete();
}
return false;
}
+
+ double strong_code_root_scan_time_sec() {
+ return _strong_code_root_scan_time_sec;
+ }
+
size_t cards_done() { return _cards_done;}
size_t cards_looked_up() { return _cards;}
};
-void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
+void G1RemSet::scanRS(OopsInHeapRegionClosure* oc,
+ CodeBlobToOopClosure* code_root_cl,
+ int worker_i) {
double rs_time_start = os::elapsedTime();
HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
- ScanRSClosure scanRScl(oc, worker_i);
+ ScanRSClosure scanRScl(oc, code_root_cl, worker_i);
_g1->collection_set_iterate_from(startRegion, &scanRScl);
scanRScl.set_try_claimed();
_g1->collection_set_iterate_from(startRegion, &scanRScl);
- double scan_rs_time_sec = os::elapsedTime() - rs_time_start;
+ double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
+ - scanRScl.strong_code_root_scan_time_sec();
- assert( _cards_scanned != NULL, "invariant" );
+ assert(_cards_scanned != NULL, "invariant");
_cards_scanned[worker_i] = scanRScl.cards_done();
_g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
+ _g1p->phase_times()->record_strong_code_root_scan_time(worker_i,
+ scanRScl.strong_code_root_scan_time_sec() * 1000.0);
}
// Closure used for updating RSets and recording references that
@@ -286,7 +321,8 @@
}
void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
- int worker_i) {
+ CodeBlobToOopClosure* code_root_cl,
+ int worker_i) {
#if CARD_REPEAT_HISTO
ct_freq_update_histo_and_reset();
#endif
@@ -326,7 +362,7 @@
_g1p->phase_times()->record_update_rs_time(worker_i, 0.0);
}
if (G1UseParallelRSetScanning || (worker_i == 0)) {
- scanRS(oc, worker_i);
+ scanRS(oc, code_root_cl, worker_i);
} else {
_g1p->phase_times()->record_scan_rs_time(worker_i, 0.0);
}
@@ -472,12 +508,7 @@
ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) :
_g1h(G1CollectedHeap::heap()),
_region_bm(region_bm), _card_bm(card_bm),
- _ctbs(NULL)
- {
- ModRefBarrierSet* bs = _g1h->mr_bs();
- guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition");
- _ctbs = (CardTableModRefBS*)bs;
- }
+ _ctbs(_g1h->g1_barrier_set()) {}
bool doHeapRegion(HeapRegion* r) {
if (!r->continuesHumongous()) {
@@ -700,47 +731,29 @@
return has_refs_into_cset;
}
-class HRRSStatsIter: public HeapRegionClosure {
- size_t _occupied;
- size_t _total_mem_sz;
- size_t _max_mem_sz;
- HeapRegion* _max_mem_sz_region;
-public:
- HRRSStatsIter() :
- _occupied(0),
- _total_mem_sz(0),
- _max_mem_sz(0),
- _max_mem_sz_region(NULL)
- {}
+void G1RemSet::print_periodic_summary_info(const char* header) {
+ G1RemSetSummary current;
+ current.initialize(this);
- bool doHeapRegion(HeapRegion* r) {
- if (r->continuesHumongous()) return false;
- size_t mem_sz = r->rem_set()->mem_size();
- if (mem_sz > _max_mem_sz) {
- _max_mem_sz = mem_sz;
- _max_mem_sz_region = r;
- }
- _total_mem_sz += mem_sz;
- size_t occ = r->rem_set()->occupied();
- _occupied += occ;
- return false;
- }
- size_t total_mem_sz() { return _total_mem_sz; }
- size_t max_mem_sz() { return _max_mem_sz; }
- size_t occupied() { return _occupied; }
- HeapRegion* max_mem_sz_region() { return _max_mem_sz_region; }
-};
+ _prev_period_summary.subtract_from(¤t);
+ print_summary_info(&_prev_period_summary, header);
-class PrintRSThreadVTimeClosure : public ThreadClosure {
-public:
- virtual void do_thread(Thread *t) {
- ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t;
- gclog_or_tty->print(" %5.2f", crt->vtime_accum());
- }
-};
+ _prev_period_summary.set(¤t);
+}
void G1RemSet::print_summary_info() {
- G1CollectedHeap* g1 = G1CollectedHeap::heap();
+ G1RemSetSummary current;
+ current.initialize(this);
+
+ print_summary_info(¤t, " Cumulative RS summary");
+}
+
+void G1RemSet::print_summary_info(G1RemSetSummary * summary, const char * header) {
+ assert(summary != NULL, "just checking");
+
+ if (header != NULL) {
+ gclog_or_tty->print_cr("%s", header);
+ }
#if CARD_REPEAT_HISTO
gclog_or_tty->print_cr("\nG1 card_repeat count histogram: ");
@@ -748,52 +761,13 @@
card_repeat_count.print_on(gclog_or_tty);
#endif
- gclog_or_tty->print_cr("\n Concurrent RS processed %d cards",
- _conc_refine_cards);
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
- jint tot_processed_buffers =
- dcqs.processed_buffers_mut() + dcqs.processed_buffers_rs_thread();
- gclog_or_tty->print_cr(" Of %d completed buffers:", tot_processed_buffers);
- gclog_or_tty->print_cr(" %8d (%5.1f%%) by conc RS threads.",
- dcqs.processed_buffers_rs_thread(),
- 100.0*(float)dcqs.processed_buffers_rs_thread()/
- (float)tot_processed_buffers);
- gclog_or_tty->print_cr(" %8d (%5.1f%%) by mutator threads.",
- dcqs.processed_buffers_mut(),
- 100.0*(float)dcqs.processed_buffers_mut()/
- (float)tot_processed_buffers);
- gclog_or_tty->print_cr(" Conc RS threads times(s)");
- PrintRSThreadVTimeClosure p;
- gclog_or_tty->print(" ");
- g1->concurrent_g1_refine()->threads_do(&p);
- gclog_or_tty->print_cr("");
-
- HRRSStatsIter blk;
- g1->heap_region_iterate(&blk);
- gclog_or_tty->print_cr(" Total heap region rem set sizes = "SIZE_FORMAT"K."
- " Max = "SIZE_FORMAT"K.",
- blk.total_mem_sz()/K, blk.max_mem_sz()/K);
- gclog_or_tty->print_cr(" Static structures = "SIZE_FORMAT"K,"
- " free_lists = "SIZE_FORMAT"K.",
- HeapRegionRemSet::static_mem_size() / K,
- HeapRegionRemSet::fl_mem_size() / K);
- gclog_or_tty->print_cr(" "SIZE_FORMAT" occupied cards represented.",
- blk.occupied());
- HeapRegion* max_mem_sz_region = blk.max_mem_sz_region();
- HeapRegionRemSet* rem_set = max_mem_sz_region->rem_set();
- gclog_or_tty->print_cr(" Max size region = "HR_FORMAT", "
- "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.",
- HR_FORMAT_PARAMS(max_mem_sz_region),
- (rem_set->mem_size() + K - 1)/K,
- (rem_set->occupied() + K - 1)/K);
- gclog_or_tty->print_cr(" Did %d coarsenings.",
- HeapRegionRemSet::n_coarsenings());
+ summary->print_on(gclog_or_tty);
}
void G1RemSet::prepare_for_verify() {
if (G1HRRSFlushLogBuffersOnVerify &&
(VerifyBeforeGC || VerifyAfterGC)
- && !_g1->full_collection()) {
+ && (!_g1->full_collection() || G1VerifyRSetsDuringFullGC)) {
cleanupHRRS();
_g1->set_refine_cte_cl_concurrency(false);
if (SafepointSynchronize::is_at_safepoint()) {
--- ./hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Wed May 07 19:26:16 2014 -0700
@@ -25,6 +25,8 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP
+#include "gc_implementation/g1/g1RemSetSummary.hpp"
+
// A G1RemSet provides ways of iterating over pointers into a selected
// collection set.
@@ -37,9 +39,11 @@
// so that they can be used to update the individual region remsets.
class G1RemSet: public CHeapObj {
+private:
+ G1RemSetSummary _prev_period_summary;
protected:
G1CollectedHeap* _g1;
- unsigned _conc_refine_cards;
+ size_t _conc_refine_cards;
uint n_workers();
protected:
@@ -66,6 +70,8 @@
// references into the collection set.
OopsInHeapRegionClosure** _cset_rs_update_cl;
+ // Print the given summary info
+ virtual void print_summary_info(G1RemSetSummary * summary, const char * header = NULL);
public:
// This is called to reset dual hash tables after the gc pause
// is finished and the initial hash table is no longer being
@@ -75,14 +81,23 @@
G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
~G1RemSet();
- // Invoke "blk->do_oop" on all pointers into the CS in objects in regions
- // outside the CS (having invoked "blk->set_region" to set the "from"
- // region correctly beforehand.) The "worker_i" param is for the
- // parallel case where the number of the worker thread calling this
- // function can be helpful in partitioning the work to be done. It
- // should be the same as the "i" passed to the calling thread's
- // work(i) function. In the sequential case this param will be ingored.
- void oops_into_collection_set_do(OopsInHeapRegionClosure* blk, int worker_i);
+ // Invoke "blk->do_oop" on all pointers into the collection set
+ // from objects in regions outside the collection set (having
+ // invoked "blk->set_region" to set the "from" region correctly
+ // beforehand.)
+ //
+ // Invoke code_root_cl->do_code_blob on the unmarked nmethods
+ // on the strong code roots list for each region in the
+ // collection set.
+ //
+ // The "worker_i" param is for the parallel case where the id
+ // of the worker thread calling this function can be helpful in
+ // partitioning the work to be done. It should be the same as
+ // the "i" passed to the calling thread's work(i) function.
+ // In the sequential case this param will be ignored.
+ void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
+ CodeBlobToOopClosure* code_root_cl,
+ int worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
// call. Must call each of these once before and after (in sequential
@@ -92,7 +107,10 @@
void prepare_for_oops_into_collection_set_do();
void cleanup_after_oops_into_collection_set_do();
- void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
+ void scanRS(OopsInHeapRegionClosure* oc,
+ CodeBlobToOopClosure* code_root_cl,
+ int worker_i);
+
void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i);
CardTableModRefBS* ct_bs() { return _ct_bs; }
@@ -123,11 +141,18 @@
int worker_i,
bool check_for_refs_into_cset);
- // Print any relevant summary info.
+ // Print accumulated summary info from the start of the VM.
virtual void print_summary_info();
+ // Print accumulated summary info from the last time called.
+ virtual void print_periodic_summary_info(const char* header);
+
// Prepare remembered set for verification.
virtual void prepare_for_verify();
+
+ size_t conc_refine_cards() const {
+ return _conc_refine_cards;
+ }
};
class CountNonCleanMemRegionClosure: public MemRegionClosure {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/concurrentG1Refine.hpp"
+#include "gc_implementation/g1/concurrentG1RefineThread.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/g1RemSet.inline.hpp"
+#include "gc_implementation/g1/g1RemSetSummary.hpp"
+#include "gc_implementation/g1/heapRegionRemSet.hpp"
+#include "runtime/thread.hpp"
+
+class GetRSThreadVTimeClosure : public ThreadClosure {
+private:
+ G1RemSetSummary* _summary;
+ uint _counter;
+
+public:
+ GetRSThreadVTimeClosure(G1RemSetSummary * summary) : ThreadClosure(), _summary(summary), _counter(0) {
+ assert(_summary != NULL, "just checking");
+ }
+
+ virtual void do_thread(Thread* t) {
+ ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t;
+ _summary->set_rs_thread_vtime(_counter, crt->vtime_accum());
+ _counter++;
+ }
+};
+
+void G1RemSetSummary::update() {
+ _num_refined_cards = remset()->conc_refine_cards();
+ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+ _num_processed_buf_mutator = dcqs.processed_buffers_mut();
+ _num_processed_buf_rs_threads = dcqs.processed_buffers_rs_thread();
+
+ _num_coarsenings = HeapRegionRemSet::n_coarsenings();
+
+ ConcurrentG1Refine * cg1r = G1CollectedHeap::heap()->concurrent_g1_refine();
+ if (_rs_threads_vtimes != NULL) {
+ GetRSThreadVTimeClosure p(this);
+ cg1r->worker_threads_do(&p);
+ }
+ set_sampling_thread_vtime(cg1r->sampling_thread()->vtime_accum());
+}
+
+void G1RemSetSummary::set_rs_thread_vtime(uint thread, double value) {
+ assert(_rs_threads_vtimes != NULL, "just checking");
+ assert(thread < _num_vtimes, "just checking");
+ _rs_threads_vtimes[thread] = value;
+}
+
+double G1RemSetSummary::rs_thread_vtime(uint thread) const {
+ assert(_rs_threads_vtimes != NULL, "just checking");
+ assert(thread < _num_vtimes, "just checking");
+ return _rs_threads_vtimes[thread];
+}
+
+void G1RemSetSummary::initialize(G1RemSet* remset) {
+ assert(_rs_threads_vtimes == NULL, "just checking");
+ assert(remset != NULL, "just checking");
+
+ _remset = remset;
+ _num_vtimes = ConcurrentG1Refine::thread_num();
+ _rs_threads_vtimes = NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC);
+ memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes);
+
+ update();
+}
+
+void G1RemSetSummary::set(G1RemSetSummary* other) {
+ assert(other != NULL, "just checking");
+ assert(remset() == other->remset(), "just checking");
+ assert(_num_vtimes == other->_num_vtimes, "just checking");
+
+ _num_refined_cards = other->num_concurrent_refined_cards();
+
+ _num_processed_buf_mutator = other->num_processed_buf_mutator();
+ _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads();
+
+ _num_coarsenings = other->_num_coarsenings;
+
+ memcpy(_rs_threads_vtimes, other->_rs_threads_vtimes, sizeof(double) * _num_vtimes);
+
+ set_sampling_thread_vtime(other->sampling_thread_vtime());
+}
+
+void G1RemSetSummary::subtract_from(G1RemSetSummary* other) {
+ assert(other != NULL, "just checking");
+ assert(remset() == other->remset(), "just checking");
+ assert(_num_vtimes == other->_num_vtimes, "just checking");
+
+ _num_refined_cards = other->num_concurrent_refined_cards() - _num_refined_cards;
+
+ _num_processed_buf_mutator = other->num_processed_buf_mutator() - _num_processed_buf_mutator;
+ _num_processed_buf_rs_threads = other->num_processed_buf_rs_threads() - _num_processed_buf_rs_threads;
+
+ _num_coarsenings = other->num_coarsenings() - _num_coarsenings;
+
+ for (uint i = 0; i < _num_vtimes; i++) {
+ set_rs_thread_vtime(i, other->rs_thread_vtime(i) - rs_thread_vtime(i));
+ }
+
+ _sampling_thread_vtime = other->sampling_thread_vtime() - _sampling_thread_vtime;
+}
+
+static double percent_of(size_t numerator, size_t denominator) {
+ if (denominator != 0) {
+ return (double)numerator / denominator * 100.0f;
+ } else {
+ return 0.0f;
+ }
+}
+
+static size_t round_to_K(size_t value) {
+ return value / K;
+}
+
+class RegionTypeCounter VALUE_OBJ_CLASS_SPEC {
+private:
+ const char* _name;
+
+ size_t _rs_mem_size;
+ size_t _cards_occupied;
+ size_t _amount;
+
+ size_t _code_root_mem_size;
+ size_t _code_root_elems;
+
+ double rs_mem_size_percent_of(size_t total) {
+ return percent_of(_rs_mem_size, total);
+ }
+
+ double cards_occupied_percent_of(size_t total) {
+ return percent_of(_cards_occupied, total);
+ }
+
+ double code_root_mem_size_percent_of(size_t total) {
+ return percent_of(_code_root_mem_size, total);
+ }
+
+ double code_root_elems_percent_of(size_t total) {
+ return percent_of(_code_root_elems, total);
+ }
+
+ size_t amount() const { return _amount; }
+
+public:
+
+ RegionTypeCounter(const char* name) : _name(name), _rs_mem_size(0), _cards_occupied(0),
+ _amount(0), _code_root_mem_size(0), _code_root_elems(0) { }
+
+ void add(size_t rs_mem_size, size_t cards_occupied, size_t code_root_mem_size,
+ size_t code_root_elems) {
+ _rs_mem_size += rs_mem_size;
+ _cards_occupied += cards_occupied;
+ _code_root_mem_size += code_root_mem_size;
+ _code_root_elems += code_root_elems;
+ _amount++;
+ }
+
+ size_t rs_mem_size() const { return _rs_mem_size; }
+ size_t cards_occupied() const { return _cards_occupied; }
+
+ size_t code_root_mem_size() const { return _code_root_mem_size; }
+ size_t code_root_elems() const { return _code_root_elems; }
+
+ void print_rs_mem_info_on(outputStream * out, size_t total) {
+ out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
+ round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
+ }
+
+ void print_cards_occupied_info_on(outputStream * out, size_t total) {
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) entries by "SIZE_FORMAT" %s regions",
+ cards_occupied(), cards_occupied_percent_of(total), amount(), _name);
+ }
+
+ void print_code_root_mem_info_on(outputStream * out, size_t total) {
+ out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
+ round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
+ }
+
+ void print_code_root_elems_info_on(outputStream * out, size_t total) {
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) elements by "SIZE_FORMAT" %s regions",
+ code_root_elems(), code_root_elems_percent_of(total), amount(), _name);
+ }
+};
+
+
+class HRRSStatsIter: public HeapRegionClosure {
+private:
+ RegionTypeCounter _young;
+ RegionTypeCounter _humonguous;
+ RegionTypeCounter _free;
+ RegionTypeCounter _old;
+ RegionTypeCounter _all;
+
+ size_t _max_rs_mem_sz;
+ HeapRegion* _max_rs_mem_sz_region;
+
+ size_t total_rs_mem_sz() const { return _all.rs_mem_size(); }
+ size_t total_cards_occupied() const { return _all.cards_occupied(); }
+
+ size_t max_rs_mem_sz() const { return _max_rs_mem_sz; }
+ HeapRegion* max_rs_mem_sz_region() const { return _max_rs_mem_sz_region; }
+
+ size_t _max_code_root_mem_sz;
+ HeapRegion* _max_code_root_mem_sz_region;
+
+ size_t total_code_root_mem_sz() const { return _all.code_root_mem_size(); }
+ size_t total_code_root_elems() const { return _all.code_root_elems(); }
+
+ size_t max_code_root_mem_sz() const { return _max_code_root_mem_sz; }
+ HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; }
+
+public:
+ HRRSStatsIter() : _all("All"), _young("Young"), _humonguous("Humonguous"),
+ _free("Free"), _old("Old"), _max_code_root_mem_sz_region(NULL), _max_rs_mem_sz_region(NULL),
+ _max_rs_mem_sz(0), _max_code_root_mem_sz(0)
+ {}
+
+ bool doHeapRegion(HeapRegion* r) {
+ HeapRegionRemSet* hrrs = r->rem_set();
+
+ // HeapRegionRemSet::mem_size() includes the
+ // size of the strong code roots
+ size_t rs_mem_sz = hrrs->mem_size();
+ if (rs_mem_sz > _max_rs_mem_sz) {
+ _max_rs_mem_sz = rs_mem_sz;
+ _max_rs_mem_sz_region = r;
+ }
+ size_t occupied_cards = hrrs->occupied();
+ size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size();
+ if (code_root_mem_sz > max_code_root_mem_sz()) {
+ _max_code_root_mem_sz_region = r;
+ }
+ size_t code_root_elems = hrrs->strong_code_roots_list_length();
+
+ RegionTypeCounter* current = NULL;
+ if (r->is_young()) {
+ current = &_young;
+ } else if (r->isHumongous()) {
+ current = &_humonguous;
+ } else if (r->is_empty()) {
+ current = &_free;
+ } else {
+ current = &_old;
+ }
+ current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
+ _all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems);
+
+ return false;
+ }
+
+ void print_summary_on(outputStream* out) {
+ RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL };
+
+ out->print_cr("\n Current rem set statistics");
+ out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K."
+ " Max = "SIZE_FORMAT"K.",
+ round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz()));
+ for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
+ (*current)->print_rs_mem_info_on(out, total_rs_mem_sz());
+ }
+
+ out->print_cr(" Static structures = "SIZE_FORMAT"K,"
+ " free_lists = "SIZE_FORMAT"K.",
+ round_to_K(HeapRegionRemSet::static_mem_size()),
+ round_to_K(HeapRegionRemSet::fl_mem_size()));
+
+ out->print_cr(" "SIZE_FORMAT" occupied cards represented.",
+ total_cards_occupied());
+ for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
+ (*current)->print_cards_occupied_info_on(out, total_cards_occupied());
+ }
+
+ // Largest sized rem set region statistics
+ HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set();
+ out->print_cr(" Region with largest rem set = "HR_FORMAT", "
+ "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.",
+ HR_FORMAT_PARAMS(max_rs_mem_sz_region()),
+ round_to_K(rem_set->mem_size()),
+ round_to_K(rem_set->occupied()));
+
+ // Strong code root statistics
+ HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set();
+ out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K."
+ " Max = "SIZE_FORMAT"K.",
+ round_to_K(total_code_root_mem_sz()),
+ round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()));
+ for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
+ (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz());
+ }
+
+ out->print_cr(" "SIZE_FORMAT" code roots represented.",
+ total_code_root_elems());
+ for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
+ (*current)->print_code_root_elems_info_on(out, total_code_root_elems());
+ }
+
+ out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", "
+ "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".",
+ HR_FORMAT_PARAMS(max_code_root_mem_sz_region()),
+ round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()),
+ round_to_K(max_code_root_rem_set->strong_code_roots_list_length()));
+ }
+};
+
+void G1RemSetSummary::print_on(outputStream* out) {
+ out->print_cr("\n Recent concurrent refinement statistics");
+ out->print_cr(" Processed "SIZE_FORMAT" cards",
+ num_concurrent_refined_cards());
+ out->print_cr(" Of "SIZE_FORMAT" completed buffers:", num_processed_buf_total());
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by concurrent RS threads.",
+ num_processed_buf_total(),
+ percent_of(num_processed_buf_rs_threads(), num_processed_buf_total()));
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by mutator threads.",
+ num_processed_buf_mutator(),
+ percent_of(num_processed_buf_mutator(), num_processed_buf_total()));
+ out->print_cr(" Did "SIZE_FORMAT" coarsenings.", num_coarsenings());
+ out->print_cr(" Concurrent RS threads times (s)");
+ out->print(" ");
+ for (uint i = 0; i < _num_vtimes; i++) {
+ out->print(" %5.2f", rs_thread_vtime(i));
+ }
+ out->cr();
+ out->print_cr(" Concurrent sampling threads times (s)");
+ out->print_cr(" %5.2f", sampling_thread_vtime());
+
+ HRRSStatsIter blk;
+ G1CollectedHeap::heap()->heap_region_iterate(&blk);
+ blk.print_summary_on(out);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.hpp Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSETSUMMARY_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSETSUMMARY_HPP
+
+#include "utilities/ostream.hpp"
+
+class G1RemSet;
+
+// A G1RemSetSummary manages statistical information about the G1RemSet
+
+class G1RemSetSummary VALUE_OBJ_CLASS_SPEC {
+private:
+ friend class GetRSThreadVTimeClosure;
+
+ G1RemSet* _remset;
+
+ G1RemSet* remset() const {
+ return _remset;
+ }
+
+ size_t _num_refined_cards;
+ size_t _num_processed_buf_mutator;
+ size_t _num_processed_buf_rs_threads;
+
+ size_t _num_coarsenings;
+
+ double* _rs_threads_vtimes;
+ size_t _num_vtimes;
+
+ double _sampling_thread_vtime;
+
+ void set_rs_thread_vtime(uint thread, double value);
+ void set_sampling_thread_vtime(double value) {
+ _sampling_thread_vtime = value;
+ }
+
+ void free_and_null() {
+ if (_rs_threads_vtimes) {
+ FREE_C_HEAP_ARRAY(double, _rs_threads_vtimes, mtGC);
+ _rs_threads_vtimes = NULL;
+ _num_vtimes = 0;
+ }
+ }
+
+ // update this summary with current data from various places
+ void update();
+
+public:
+ G1RemSetSummary() : _remset(NULL), _num_refined_cards(0),
+ _num_processed_buf_mutator(0), _num_processed_buf_rs_threads(0), _num_coarsenings(0),
+ _rs_threads_vtimes(NULL), _num_vtimes(0), _sampling_thread_vtime(0.0f) {
+ }
+
+ ~G1RemSetSummary() {
+ free_and_null();
+ }
+
+ // set the counters in this summary to the values of the others
+ void set(G1RemSetSummary* other);
+ // subtract all counters from the other summary, and set them in the current
+ void subtract_from(G1RemSetSummary* other);
+
+ // initialize and get the first sampling
+ void initialize(G1RemSet* remset);
+
+ void print_on(outputStream* out);
+
+ double rs_thread_vtime(uint thread) const;
+
+ double sampling_thread_vtime() const {
+ return _sampling_thread_vtime;
+ }
+
+ size_t num_concurrent_refined_cards() const {
+ return _num_refined_cards;
+ }
+
+ size_t num_processed_buf_mutator() const {
+ return _num_processed_buf_mutator;
+ }
+
+ size_t num_processed_buf_rs_threads() const {
+ return _num_processed_buf_rs_threads;
+ }
+
+ size_t num_processed_buf_total() const {
+ return num_processed_buf_mutator() + num_processed_buf_rs_threads();
+ }
+
+ size_t num_coarsenings() const {
+ return _num_coarsenings;
+ }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSETSUMMARY_HPP
--- ./hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Wed May 07 19:26:16 2014 -0700
@@ -76,6 +76,46 @@
}
}
+bool G1SATBCardTableModRefBS::mark_card_deferred(size_t card_index) {
+ jbyte val = _byte_map[card_index];
+ // It's already processed
+ if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
+ return false;
+ }
+
+ if (val == g1_young_gen) {
+ // the card is for a young gen region. We don't need to keep track of all pointers into young
+ return false;
+ }
+
+ // Cached bit can be installed either on a clean card or on a claimed card.
+ jbyte new_val = val;
+ if (val == clean_card_val()) {
+ new_val = (jbyte)deferred_card_val();
+ } else {
+ if (val & claimed_card_val()) {
+ new_val = val | (jbyte)deferred_card_val();
+ }
+ }
+ if (new_val != val) {
+ Atomic::cmpxchg(new_val, &_byte_map[card_index], val);
+ }
+ return true;
+}
+
+void G1SATBCardTableModRefBS::g1_mark_as_young(const MemRegion& mr) {
+ jbyte *const first = byte_for(mr.start());
+ jbyte *const last = byte_after(mr.last());
+
+ memset(first, g1_young_gen, last - first);
+}
+
+#ifndef PRODUCT
+void G1SATBCardTableModRefBS::verify_g1_young_region(MemRegion mr) {
+ verify_region(mr, g1_young_gen, true);
+}
+#endif
+
G1SATBCardTableLoggingModRefBS::
G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
int max_covered_regions) :
@@ -88,7 +128,11 @@
void
G1SATBCardTableLoggingModRefBS::write_ref_field_work(void* field,
oop new_val) {
- jbyte* byte = byte_for(field);
+ volatile jbyte* byte = byte_for(field);
+ if (*byte == g1_young_gen) {
+ return;
+ }
+ OrderAccess::storeload();
if (*byte != dirty_card) {
*byte = dirty_card;
Thread* thr = Thread::current();
@@ -120,7 +164,7 @@
void
G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr, bool whole_heap) {
- jbyte* byte = byte_for(mr.start());
+ volatile jbyte* byte = byte_for(mr.start());
jbyte* last_byte = byte_for(mr.last());
Thread* thr = Thread::current();
if (whole_heap) {
@@ -129,25 +173,35 @@
byte++;
}
} else {
- // Enqueue if necessary.
- if (thr->is_Java_thread()) {
- JavaThread* jt = (JavaThread*)thr;
- while (byte <= last_byte) {
- if (*byte != dirty_card) {
- *byte = dirty_card;
- jt->dirty_card_queue().enqueue(byte);
+ // skip all consecutive young cards
+ for (; byte <= last_byte && *byte == g1_young_gen; byte++);
+
+ if (byte <= last_byte) {
+ OrderAccess::storeload();
+ // Enqueue if necessary.
+ if (thr->is_Java_thread()) {
+ JavaThread* jt = (JavaThread*)thr;
+ for (; byte <= last_byte; byte++) {
+ if (*byte == g1_young_gen) {
+ continue;
+ }
+ if (*byte != dirty_card) {
+ *byte = dirty_card;
+ jt->dirty_card_queue().enqueue(byte);
+ }
}
- byte++;
- }
- } else {
- MutexLockerEx x(Shared_DirtyCardQ_lock,
- Mutex::_no_safepoint_check_flag);
- while (byte <= last_byte) {
- if (*byte != dirty_card) {
- *byte = dirty_card;
- _dcqs.shared_dirty_card_queue()->enqueue(byte);
+ } else {
+ MutexLockerEx x(Shared_DirtyCardQ_lock,
+ Mutex::_no_safepoint_check_flag);
+ for (; byte <= last_byte; byte++) {
+ if (*byte == g1_young_gen) {
+ continue;
+ }
+ if (*byte != dirty_card) {
+ *byte = dirty_card;
+ _dcqs.shared_dirty_card_queue()->enqueue(byte);
+ }
}
- byte++;
}
}
}
--- ./hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Wed May 07 19:26:16 2014 -0700
@@ -37,7 +37,14 @@
// snapshot-at-the-beginning marking.
class G1SATBCardTableModRefBS: public CardTableModRefBSForCTRS {
+protected:
+ enum G1CardValues {
+ g1_young_gen = CT_MR_BS_last_reserved << 1
+ };
+
public:
+ static int g1_young_card_val() { return g1_young_gen; }
+
// Add "pre_val" to a set of objects that may have been disconnected from the
// pre-marking object graph.
static void enqueue(oop pre_val);
@@ -88,6 +95,45 @@
write_ref_array_pre_work(dst, count);
}
}
+
+/*
+ Claimed and deferred bits are used together in G1 during the evacuation
+ pause. These bits can have the following state transitions:
+ 1. The claimed bit can be put over any other card state. Except that
+ the "dirty -> dirty and claimed" transition is checked for in
+ G1 code and is not used.
+ 2. Deferred bit can be set only if the previous state of the card
+ was either clean or claimed. mark_card_deferred() is wait-free.
+ We do not care if the operation is be successful because if
+ it does not it will only result in duplicate entry in the update
+ buffer because of the "cache-miss". So it's not worth spinning.
+ */
+
+ bool is_card_claimed(size_t card_index) {
+ jbyte val = _byte_map[card_index];
+ return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
+ }
+
+ void set_card_claimed(size_t card_index) {
+ jbyte val = _byte_map[card_index];
+ if (val == clean_card_val()) {
+ val = (jbyte)claimed_card_val();
+ } else {
+ val |= (jbyte)claimed_card_val();
+ }
+ _byte_map[card_index] = val;
+ }
+
+ void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN;
+ void g1_mark_as_young(const MemRegion& mr);
+
+ bool mark_card_deferred(size_t card_index);
+
+ bool is_card_deferred(size_t card_index) {
+ jbyte val = _byte_map[card_index];
+ return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
+ }
+
};
// Adds card-table logging to the post-barrier.
--- ./hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Wed May 07 19:26:16 2014 -0700
@@ -71,6 +71,9 @@
diagnostic(bool, G1TraceConcRefinement, false, \
"Trace G1 concurrent refinement") \
\
+ experimental(bool, G1TraceStringSymbolTableScrubbing, false, \
+ "Trace information string and symbol table scrubbing.") \
+ \
product(double, G1ConcMarkStepDurationMillis, 10.0, \
"Target duration of individual concurrent marking steps " \
"in milliseconds.") \
@@ -332,7 +335,14 @@
\
develop(bool, G1EvacuationFailureALotDuringMixedGC, true, \
"Force use of evacuation failure handling during mixed " \
- "evacuation pauses")
+ "evacuation pauses") \
+ \
+ diagnostic(bool, G1VerifyRSetsDuringFullGC, false, \
+ "If true, perform verification of each heap region's " \
+ "remembered set when verifying the heap during a full GC.") \
+ \
+ diagnostic(bool, G1VerifyHeapRegionCodeRoots, false, \
+ "Verify the code root lists attached to each heap region.")
G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
--- ./hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed May 07 19:26:16 2014 -0700
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "code/nmethod.hpp"
#include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
@@ -50,144 +51,6 @@
OopClosure* oc) :
_r_bottom(r->bottom()), _r_end(r->end()), _oc(oc) { }
-class VerifyLiveClosure: public OopClosure {
-private:
- G1CollectedHeap* _g1h;
- CardTableModRefBS* _bs;
- oop _containing_obj;
- bool _failures;
- int _n_failures;
- VerifyOption _vo;
-public:
- // _vo == UsePrevMarking -> use "prev" marking information,
- // _vo == UseNextMarking -> use "next" marking information,
- // _vo == UseMarkWord -> use mark word from object header.
- VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) :
- _g1h(g1h), _bs(NULL), _containing_obj(NULL),
- _failures(false), _n_failures(0), _vo(vo)
- {
- BarrierSet* bs = _g1h->barrier_set();
- if (bs->is_a(BarrierSet::CardTableModRef))
- _bs = (CardTableModRefBS*)bs;
- }
-
- void set_containing_obj(oop obj) {
- _containing_obj = obj;
- }
-
- bool failures() { return _failures; }
- int n_failures() { return _n_failures; }
-
- virtual void do_oop(narrowOop* p) { do_oop_work(p); }
- virtual void do_oop( oop* p) { do_oop_work(p); }
-
- void print_object(outputStream* out, oop obj) {
-#ifdef PRODUCT
- klassOop k = obj->klass();
- const char* class_name = instanceKlass::cast(k)->external_name();
- out->print_cr("class name %s", class_name);
-#else // PRODUCT
- obj->print_on(out);
-#endif // PRODUCT
- }
-
- template
- void do_oop_work(T* p) {
- assert(_containing_obj != NULL, "Precondition");
- assert(!_g1h->is_obj_dead_cond(_containing_obj, _vo),
- "Precondition");
- T heap_oop = oopDesc::load_heap_oop(p);
- if (!oopDesc::is_null(heap_oop)) {
- oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
- bool failed = false;
- if (!_g1h->is_in_closed_subset(obj) || _g1h->is_obj_dead_cond(obj, _vo)) {
- MutexLockerEx x(ParGCRareEvent_lock,
- Mutex::_no_safepoint_check_flag);
-
- if (!_failures) {
- gclog_or_tty->print_cr("");
- gclog_or_tty->print_cr("----------");
- }
- if (!_g1h->is_in_closed_subset(obj)) {
- HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
- gclog_or_tty->print_cr("Field "PTR_FORMAT
- " of live obj "PTR_FORMAT" in region "
- "["PTR_FORMAT", "PTR_FORMAT")",
- p, (void*) _containing_obj,
- from->bottom(), from->end());
- print_object(gclog_or_tty, _containing_obj);
- gclog_or_tty->print_cr("points to obj "PTR_FORMAT" not in the heap",
- (void*) obj);
- } else {
- HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
- HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
- gclog_or_tty->print_cr("Field "PTR_FORMAT
- " of live obj "PTR_FORMAT" in region "
- "["PTR_FORMAT", "PTR_FORMAT")",
- p, (void*) _containing_obj,
- from->bottom(), from->end());
- print_object(gclog_or_tty, _containing_obj);
- gclog_or_tty->print_cr("points to dead obj "PTR_FORMAT" in region "
- "["PTR_FORMAT", "PTR_FORMAT")",
- (void*) obj, to->bottom(), to->end());
- print_object(gclog_or_tty, obj);
- }
- gclog_or_tty->print_cr("----------");
- gclog_or_tty->flush();
- _failures = true;
- failed = true;
- _n_failures++;
- }
-
- if (!_g1h->full_collection()) {
- HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
- HeapRegion* to = _g1h->heap_region_containing(obj);
- if (from != NULL && to != NULL &&
- from != to &&
- !to->isHumongous()) {
- jbyte cv_obj = *_bs->byte_for_const(_containing_obj);
- jbyte cv_field = *_bs->byte_for_const(p);
- const jbyte dirty = CardTableModRefBS::dirty_card_val();
-
- bool is_bad = !(from->is_young()
- || to->rem_set()->contains_reference(p)
- || !G1HRRSFlushLogBuffersOnVerify && // buffers were not flushed
- (_containing_obj->is_objArray() ?
- cv_field == dirty
- : cv_obj == dirty || cv_field == dirty));
- if (is_bad) {
- MutexLockerEx x(ParGCRareEvent_lock,
- Mutex::_no_safepoint_check_flag);
-
- if (!_failures) {
- gclog_or_tty->print_cr("");
- gclog_or_tty->print_cr("----------");
- }
- gclog_or_tty->print_cr("Missing rem set entry:");
- gclog_or_tty->print_cr("Field "PTR_FORMAT" "
- "of obj "PTR_FORMAT", "
- "in region "HR_FORMAT,
- p, (void*) _containing_obj,
- HR_FORMAT_PARAMS(from));
- _containing_obj->print_on(gclog_or_tty);
- gclog_or_tty->print_cr("points to obj "PTR_FORMAT" "
- "in region "HR_FORMAT,
- (void*) obj,
- HR_FORMAT_PARAMS(to));
- obj->print_on(gclog_or_tty);
- gclog_or_tty->print_cr("Obj head CTE = %d, field CTE = %d.",
- cv_obj, cv_field);
- gclog_or_tty->print_cr("----------");
- gclog_or_tty->flush();
- _failures = true;
- if (!failed) _n_failures++;
- }
- }
- }
- }
- }
-};
-
template
HeapWord* walk_mem_region_loop(ClosureType* cl, G1CollectedHeap* g1h,
HeapRegion* hr,
@@ -314,6 +177,11 @@
region_size = MAX_REGION_SIZE;
}
+ if (region_size != G1HeapRegionSize) {
+ // Update the flag to make sure that PrintFlagsFinal logs the correct value
+ FLAG_SET_ERGO(uintx, G1HeapRegionSize, region_size);
+ }
+
// And recalculate the log.
region_size_log = log2_long((jlong) region_size);
@@ -363,7 +231,7 @@
if (!par) {
// If this is parallel, this will be done later.
HeapRegionRemSet* hrrs = rem_set();
- if (hrrs != NULL) hrrs->clear();
+ hrrs->clear();
_claimed = InitialClaimValue;
}
zero_marked_bytes();
@@ -504,6 +372,7 @@
_rem_set(NULL), _recorded_rs_length(0), _predicted_elapsed_time_ms(0),
_predicted_bytes_to_copy(0)
{
+ _rem_set = new HeapRegionRemSet(sharedOffsetArray, this);
_orig_end = mr.end();
// Note that initialize() will set the start of the unmarked area of the
// region.
@@ -511,8 +380,6 @@
set_top(bottom());
set_saved_mark();
- _rem_set = new HeapRegionRemSet(sharedOffsetArray, this);
-
assert(HeapRegionRemSet::num_par_rem_sets() > 0, "Invariant.");
}
@@ -732,6 +599,161 @@
return NULL;
}
+// Code roots support
+
+void HeapRegion::add_strong_code_root(nmethod* nm) {
+ HeapRegionRemSet* hrrs = rem_set();
+ hrrs->add_strong_code_root(nm);
+}
+
+void HeapRegion::remove_strong_code_root(nmethod* nm) {
+ HeapRegionRemSet* hrrs = rem_set();
+ hrrs->remove_strong_code_root(nm);
+}
+
+void HeapRegion::migrate_strong_code_roots() {
+ assert(in_collection_set(), "only collection set regions");
+ assert(!isHumongous(),
+ err_msg("humongous region "HR_FORMAT" should not have been added to collection set",
+ HR_FORMAT_PARAMS(this)));
+
+ HeapRegionRemSet* hrrs = rem_set();
+ hrrs->migrate_strong_code_roots();
+}
+
+void HeapRegion::strong_code_roots_do(CodeBlobClosure* blk) const {
+ HeapRegionRemSet* hrrs = rem_set();
+ hrrs->strong_code_roots_do(blk);
+}
+
+class VerifyStrongCodeRootOopClosure: public OopClosure {
+ const HeapRegion* _hr;
+ nmethod* _nm;
+ bool _failures;
+ bool _has_oops_in_region;
+
+ template void do_oop_work(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+
+ // Note: not all the oops embedded in the nmethod are in the
+ // current region. We only look at those which are.
+ if (_hr->is_in(obj)) {
+ // Object is in the region. Check that its less than top
+ if (_hr->top() <= (HeapWord*)obj) {
+ // Object is above top
+ gclog_or_tty->print_cr("Object "PTR_FORMAT" in region "
+ "["PTR_FORMAT", "PTR_FORMAT") is above "
+ "top "PTR_FORMAT,
+ obj, _hr->bottom(), _hr->end(), _hr->top());
+ _failures = true;
+ return;
+ }
+ // Nmethod has at least one oop in the current region
+ _has_oops_in_region = true;
+ }
+ }
+ }
+
+public:
+ VerifyStrongCodeRootOopClosure(const HeapRegion* hr, nmethod* nm):
+ _hr(hr), _failures(false), _has_oops_in_region(false) {}
+
+ void do_oop(narrowOop* p) { do_oop_work(p); }
+ void do_oop(oop* p) { do_oop_work(p); }
+
+ bool failures() { return _failures; }
+ bool has_oops_in_region() { return _has_oops_in_region; }
+};
+
+class VerifyStrongCodeRootCodeBlobClosure: public CodeBlobClosure {
+ const HeapRegion* _hr;
+ bool _failures;
+public:
+ VerifyStrongCodeRootCodeBlobClosure(const HeapRegion* hr) :
+ _hr(hr), _failures(false) {}
+
+ void do_code_blob(CodeBlob* cb) {
+ nmethod* nm = (cb == NULL) ? NULL : cb->as_nmethod_or_null();
+ if (nm != NULL) {
+ // Verify that the nemthod is live
+ if (!nm->is_alive()) {
+ gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has dead nmethod "
+ PTR_FORMAT" in its strong code roots",
+ _hr->bottom(), _hr->end(), nm);
+ _failures = true;
+ } else {
+ VerifyStrongCodeRootOopClosure oop_cl(_hr, nm);
+ nm->oops_do(&oop_cl);
+ if (!oop_cl.has_oops_in_region()) {
+ gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has nmethod "
+ PTR_FORMAT" in its strong code roots "
+ "with no pointers into region",
+ _hr->bottom(), _hr->end(), nm);
+ _failures = true;
+ } else if (oop_cl.failures()) {
+ gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has other "
+ "failures for nmethod "PTR_FORMAT,
+ _hr->bottom(), _hr->end(), nm);
+ _failures = true;
+ }
+ }
+ }
+ }
+
+ bool failures() { return _failures; }
+};
+
+void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const {
+ if (!G1VerifyHeapRegionCodeRoots) {
+ // We're not verifying code roots.
+ return;
+ }
+ if (vo == VerifyOption_G1UseMarkWord) {
+ // Marking verification during a full GC is performed after class
+ // unloading, code cache unloading, etc so the strong code roots
+ // attached to each heap region are in an inconsistent state. They won't
+ // be consistent until the strong code roots are rebuilt after the
+ // actual GC. Skip verifying the strong code roots in this particular
+ // time.
+ assert(VerifyDuringGC, "only way to get here");
+ return;
+ }
+
+ HeapRegionRemSet* hrrs = rem_set();
+ int strong_code_roots_length = hrrs->strong_code_roots_list_length();
+
+ // if this region is empty then there should be no entries
+ // on its strong code root list
+ if (is_empty()) {
+ if (strong_code_roots_length > 0) {
+ gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is empty "
+ "but has "INT32_FORMAT" code root entries",
+ bottom(), end(), strong_code_roots_length);
+ *failures = true;
+ }
+ return;
+ }
+
+ if (continuesHumongous()) {
+ if (strong_code_roots_length > 0) {
+ gclog_or_tty->print_cr("region "HR_FORMAT" is a continuation of a humongous "
+ "region but has "INT32_FORMAT" code root entries",
+ HR_FORMAT_PARAMS(this), strong_code_roots_length);
+ *failures = true;
+ }
+ return;
+ }
+
+ VerifyStrongCodeRootCodeBlobClosure cb_cl(this);
+ strong_code_roots_do(&cb_cl);
+
+ if (cb_cl.failures()) {
+ *failures = true;
+ }
+}
+
void HeapRegion::print() const { print_on(gclog_or_tty); }
void HeapRegion::print_on(outputStream* st) const {
if (isHumongous()) {
@@ -760,10 +782,143 @@
G1OffsetTableContigSpace::print_on(st);
}
-void HeapRegion::verify() const {
- bool dummy = false;
- verify(VerifyOption_G1UsePrevMarking, /* failures */ &dummy);
-}
+class VerifyLiveClosure: public OopClosure {
+private:
+ G1CollectedHeap* _g1h;
+ CardTableModRefBS* _bs;
+ oop _containing_obj;
+ bool _failures;
+ int _n_failures;
+ VerifyOption _vo;
+public:
+ // _vo == UsePrevMarking -> use "prev" marking information,
+ // _vo == UseNextMarking -> use "next" marking information,
+ // _vo == UseMarkWord -> use mark word from object header.
+ VerifyLiveClosure(G1CollectedHeap* g1h, VerifyOption vo) :
+ _g1h(g1h), _bs(NULL), _containing_obj(NULL),
+ _failures(false), _n_failures(0), _vo(vo)
+ {
+ BarrierSet* bs = _g1h->barrier_set();
+ if (bs->is_a(BarrierSet::CardTableModRef))
+ _bs = (CardTableModRefBS*)bs;
+ }
+
+ void set_containing_obj(oop obj) {
+ _containing_obj = obj;
+ }
+
+ bool failures() { return _failures; }
+ int n_failures() { return _n_failures; }
+
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
+ virtual void do_oop( oop* p) { do_oop_work(p); }
+
+ void print_object(outputStream* out, oop obj) {
+#ifdef PRODUCT
+ klassOop k = obj->klass();
+ const char* class_name = instanceKlass::cast(k)->external_name();
+ out->print_cr("class name %s", class_name);
+#else // PRODUCT
+ obj->print_on(out);
+#endif // PRODUCT
+ }
+
+ template
+ void do_oop_work(T* p) {
+ assert(_containing_obj != NULL, "Precondition");
+ assert(!_g1h->is_obj_dead_cond(_containing_obj, _vo),
+ "Precondition");
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ bool failed = false;
+ if (!_g1h->is_in_closed_subset(obj) || _g1h->is_obj_dead_cond(obj, _vo)) {
+ MutexLockerEx x(ParGCRareEvent_lock,
+ Mutex::_no_safepoint_check_flag);
+
+ if (!_failures) {
+ gclog_or_tty->print_cr("");
+ gclog_or_tty->print_cr("----------");
+ }
+ if (!_g1h->is_in_closed_subset(obj)) {
+ HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
+ gclog_or_tty->print_cr("Field "PTR_FORMAT
+ " of live obj "PTR_FORMAT" in region "
+ "["PTR_FORMAT", "PTR_FORMAT")",
+ p, (void*) _containing_obj,
+ from->bottom(), from->end());
+ print_object(gclog_or_tty, _containing_obj);
+ gclog_or_tty->print_cr("points to obj "PTR_FORMAT" not in the heap",
+ (void*) obj);
+ } else {
+ HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
+ HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
+ gclog_or_tty->print_cr("Field "PTR_FORMAT
+ " of live obj "PTR_FORMAT" in region "
+ "["PTR_FORMAT", "PTR_FORMAT")",
+ p, (void*) _containing_obj,
+ from->bottom(), from->end());
+ print_object(gclog_or_tty, _containing_obj);
+ gclog_or_tty->print_cr("points to dead obj "PTR_FORMAT" in region "
+ "["PTR_FORMAT", "PTR_FORMAT")",
+ (void*) obj, to->bottom(), to->end());
+ print_object(gclog_or_tty, obj);
+ }
+ gclog_or_tty->print_cr("----------");
+ gclog_or_tty->flush();
+ _failures = true;
+ failed = true;
+ _n_failures++;
+ }
+
+ if (!_g1h->full_collection() || G1VerifyRSetsDuringFullGC) {
+ HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
+ HeapRegion* to = _g1h->heap_region_containing(obj);
+ if (from != NULL && to != NULL &&
+ from != to &&
+ !to->isHumongous()) {
+ jbyte cv_obj = *_bs->byte_for_const(_containing_obj);
+ jbyte cv_field = *_bs->byte_for_const(p);
+ const jbyte dirty = CardTableModRefBS::dirty_card_val();
+
+ bool is_bad = !(from->is_young()
+ || to->rem_set()->contains_reference(p)
+ || !G1HRRSFlushLogBuffersOnVerify && // buffers were not flushed
+ (_containing_obj->is_objArray() ?
+ cv_field == dirty
+ : cv_obj == dirty || cv_field == dirty));
+ if (is_bad) {
+ MutexLockerEx x(ParGCRareEvent_lock,
+ Mutex::_no_safepoint_check_flag);
+
+ if (!_failures) {
+ gclog_or_tty->print_cr("");
+ gclog_or_tty->print_cr("----------");
+ }
+ gclog_or_tty->print_cr("Missing rem set entry:");
+ gclog_or_tty->print_cr("Field "PTR_FORMAT" "
+ "of obj "PTR_FORMAT", "
+ "in region "HR_FORMAT,
+ p, (void*) _containing_obj,
+ HR_FORMAT_PARAMS(from));
+ _containing_obj->print_on(gclog_or_tty);
+ gclog_or_tty->print_cr("points to obj "PTR_FORMAT" "
+ "in region "HR_FORMAT,
+ (void*) obj,
+ HR_FORMAT_PARAMS(to));
+ obj->print_on(gclog_or_tty);
+ gclog_or_tty->print_cr("Obj head CTE = %d, field CTE = %d.",
+ cv_obj, cv_field);
+ gclog_or_tty->print_cr("----------");
+ gclog_or_tty->flush();
+ _failures = true;
+ if (!failed) _n_failures++;
+ }
+ }
+ }
+ }
+ }
+};
// This really ought to be commoned up into OffsetTableContigSpace somehow.
// We would need a mechanism to make that code skip dead objects.
@@ -903,6 +1058,13 @@
*failures = true;
return;
}
+
+ verify_strong_code_roots(vo, failures);
+}
+
+void HeapRegion::verify() const {
+ bool dummy = false;
+ verify(VerifyOption_G1UsePrevMarking, /* failures */ &dummy);
}
// G1OffsetTableContigSpace code; copied from space.cpp. Hope this can go
--- ./hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Wed May 07 19:26:16 2014 -0700
@@ -51,6 +51,7 @@
class HeapRegionRemSetIterator;
class HeapRegion;
class HeapRegionSetBase;
+class nmethod;
#define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
#define HR_FORMAT_PARAMS(_hr_) \
@@ -374,7 +375,8 @@
RebuildRSClaimValue = 5,
ParEvacFailureClaimValue = 6,
AggregateCountClaimValue = 7,
- VerifyCountClaimValue = 8
+ VerifyCountClaimValue = 8,
+ ParMarkRootClaimValue = 9
};
inline HeapWord* par_allocate_no_bot_updates(size_t word_size) {
@@ -801,6 +803,25 @@
virtual void reset_after_compaction();
+ // Routines for managing a list of code roots (attached to the
+ // this region's RSet) that point into this heap region.
+ void add_strong_code_root(nmethod* nm);
+ void remove_strong_code_root(nmethod* nm);
+
+ // During a collection, migrate the successfully evacuated
+ // strong code roots that referenced into this region to the
+ // new regions that they now point into. Unsuccessfully
+ // evacuated code roots are not migrated.
+ void migrate_strong_code_roots();
+
+ // Applies blk->do_code_blob() to each of the entries in
+ // the strong code roots list for this region
+ void strong_code_roots_do(CodeBlobClosure* blk) const;
+
+ // Verify that the entries on the strong code root list for this
+ // region are live and include at least one pointer into this region.
+ void verify_strong_code_roots(VerifyOption vo, bool* failures) const;
+
void print() const;
void print_on(outputStream* st) const;
--- ./hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed May 07 19:26:16 2014 -0700
@@ -33,6 +33,7 @@
#include "oops/oop.inline.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/globalDefinitions.hpp"
+#include "utilities/growableArray.hpp"
class PerRegionTable: public CHeapObj {
friend class OtherRegionsTable;
@@ -706,10 +707,11 @@
// Cast away const in this case.
MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag);
size_t sum = 0;
- PerRegionTable * cur = _first_all_fine_prts;
- while (cur != NULL) {
- sum += cur->mem_size();
- cur = cur->next();
+ // all PRTs are of the same size so it is sufficient to query only one of them.
+ if (_first_all_fine_prts != NULL) {
+ assert(_last_all_fine_prts != NULL &&
+ _first_all_fine_prts->mem_size() == _last_all_fine_prts->mem_size(), "check that mem_size() is constant");
+ sum += _first_all_fine_prts->mem_size() * _n_fine_entries;
}
sum += (sizeof(PerRegionTable*) * _max_fine_entries);
sum += (_coarse_map.size_in_words() * HeapWordSize);
@@ -845,7 +847,7 @@
HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
HeapRegion* hr)
- : _bosa(bosa), _other_regions(hr) {
+ : _bosa(bosa), _strong_code_roots_list(NULL), _other_regions(hr) {
reset_for_par_iteration();
}
@@ -909,6 +911,12 @@
}
void HeapRegionRemSet::clear() {
+ if (_strong_code_roots_list != NULL) {
+ delete _strong_code_roots_list;
+ }
+ _strong_code_roots_list = new (ResourceObj::C_HEAP, mtGC)
+ GrowableArray(10, 0, NULL, true);
+
_other_regions.clear();
assert(occupied() == 0, "Should be clear.");
reset_for_par_iteration();
@@ -926,6 +934,126 @@
_other_regions.scrub(ctbs, region_bm, card_bm);
}
+
+// Code roots support
+
+void HeapRegionRemSet::add_strong_code_root(nmethod* nm) {
+ assert(nm != NULL, "sanity");
+ // Search for the code blob from the RHS to avoid
+ // duplicate entries as much as possible
+ if (_strong_code_roots_list->find_from_end(nm) < 0) {
+ // Code blob isn't already in the list
+ _strong_code_roots_list->push(nm);
+ }
+}
+
+void HeapRegionRemSet::remove_strong_code_root(nmethod* nm) {
+ assert(nm != NULL, "sanity");
+ int idx = _strong_code_roots_list->find(nm);
+ if (idx >= 0) {
+ _strong_code_roots_list->remove_at(idx);
+ }
+ // Check that there were no duplicates
+ guarantee(_strong_code_roots_list->find(nm) < 0, "duplicate entry found");
+}
+
+class NMethodMigrationOopClosure : public OopClosure {
+ G1CollectedHeap* _g1h;
+ HeapRegion* _from;
+ nmethod* _nm;
+
+ uint _num_self_forwarded;
+
+ template void do_oop_work(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ if (obj->is_perm()) {
+ // reference into perm gen - ignore.
+ return;
+ } else if (_from->is_in(obj)) {
+ // Reference still points into the source region.
+ // Since roots are immediately evacuated this means that
+ // we must have self forwarded the object
+ assert(obj->is_forwarded(),
+ err_msg("code roots should be immediately evacuated. "
+ "Ref: "PTR_FORMAT", "
+ "Obj: "PTR_FORMAT", "
+ "Region: "HR_FORMAT,
+ p, (void*) obj, HR_FORMAT_PARAMS(_from)));
+ assert(obj->forwardee() == obj,
+ err_msg("not self forwarded? obj = "PTR_FORMAT, (void*)obj));
+
+ // The object has been self forwarded.
+ // Note, if we're during an initial mark pause, there is
+ // no need to explicitly mark object. It will be marked
+ // during the regular evacuation failure handling code.
+ _num_self_forwarded++;
+ } else {
+ // The reference points into a promotion or to-space region
+ HeapRegion* to = _g1h->heap_region_containing(obj);
+ to->rem_set()->add_strong_code_root(_nm);
+ }
+ }
+ }
+
+public:
+ NMethodMigrationOopClosure(G1CollectedHeap* g1h, HeapRegion* from, nmethod* nm):
+ _g1h(g1h), _from(from), _nm(nm), _num_self_forwarded(0) {}
+
+ void do_oop(narrowOop* p) { do_oop_work(p); }
+ void do_oop(oop* p) { do_oop_work(p); }
+
+ uint retain() { return _num_self_forwarded > 0; }
+};
+
+void HeapRegionRemSet::migrate_strong_code_roots() {
+ assert(hr()->in_collection_set(), "only collection set regions");
+ assert(!hr()->isHumongous(),
+ err_msg("humongous region "HR_FORMAT" should not have been added to the collection set",
+ HR_FORMAT_PARAMS(hr())));
+
+ ResourceMark rm;
+
+ // List of code blobs to retain for this region
+ GrowableArray to_be_retained(10);
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+ while (_strong_code_roots_list->is_nonempty()) {
+ nmethod *nm = _strong_code_roots_list->pop();
+ if (nm != NULL) {
+ NMethodMigrationOopClosure oop_cl(g1h, hr(), nm);
+ nm->oops_do(&oop_cl);
+ if (oop_cl.retain()) {
+ to_be_retained.push(nm);
+ }
+ }
+ }
+
+ // Now push any code roots we need to retain
+ assert(to_be_retained.is_empty() || hr()->evacuation_failed(),
+ "Retained nmethod list must be empty or "
+ "evacuation of this region failed");
+
+ while (to_be_retained.is_nonempty()) {
+ nmethod* nm = to_be_retained.pop();
+ assert(nm != NULL, "sanity");
+ add_strong_code_root(nm);
+ }
+}
+
+void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const {
+ for (int i = 0; i < _strong_code_roots_list->length(); i += 1) {
+ nmethod* nm = _strong_code_roots_list->at(i);
+ blk->do_code_blob(nm);
+ }
+}
+
+size_t HeapRegionRemSet::strong_code_roots_mem_size() {
+ return sizeof(GrowableArray) +
+ _strong_code_roots_list->max_length() * sizeof(nmethod*);
+}
+
//-------------------- Iteration --------------------
HeapRegionRemSetIterator::
--- ./hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed May 07 19:26:16 2014 -0700
@@ -37,6 +37,7 @@
class HeapRegionRemSetIterator;
class PerRegionTable;
class SparsePRT;
+class nmethod;
// Essentially a wrapper around SparsePRTCleanupTask. See
// sparsePRT.hpp for more details.
@@ -191,6 +192,10 @@
G1BlockOffsetSharedArray* _bosa;
G1BlockOffsetSharedArray* bosa() const { return _bosa; }
+ // A list of code blobs (nmethods) whose code contains pointers into
+ // the region that owns this RSet.
+ GrowableArray* _strong_code_roots_list;
+
OtherRegionsTable _other_regions;
enum ParIterState { Unclaimed, Claimed, Complete };
@@ -285,11 +290,13 @@
void init_iterator(HeapRegionRemSetIterator* iter) const;
// The actual # of bytes this hr_remset takes up.
+ // Note also includes the strong code root set.
size_t mem_size() {
return _other_regions.mem_size()
// This correction is necessary because the above includes the second
// part.
- + sizeof(this) - sizeof(OtherRegionsTable);
+ + (sizeof(this) - sizeof(OtherRegionsTable))
+ + strong_code_roots_mem_size();
}
// Returns the memory occupancy of all static data structures associated
@@ -307,6 +314,37 @@
bool contains_reference(OopOrNarrowOopStar from) const {
return _other_regions.contains_reference(from);
}
+
+ // Routines for managing the list of code roots that point into
+ // the heap region that owns this RSet.
+ void add_strong_code_root(nmethod* nm);
+ void remove_strong_code_root(nmethod* nm);
+
+ // During a collection, migrate the successfully evacuated strong
+ // code roots that referenced into the region that owns this RSet
+ // to the RSets of the new regions that they now point into.
+ // Unsuccessfully evacuated code roots are not migrated.
+ void migrate_strong_code_roots();
+
+ // Applies blk->do_code_blob() to each of the entries in
+ // the strong code roots list
+ void strong_code_roots_do(CodeBlobClosure* blk) const;
+
+ // Returns the number of elements in the strong code roots list
+ int strong_code_roots_list_length() {
+ return _strong_code_roots_list->length();
+ }
+
+ // Returns true if the strong code roots contains the given
+ // nmethod.
+ bool strong_code_roots_list_contains(nmethod* nm) {
+ return _strong_code_roots_list->contains(nm);
+ }
+
+ // Returns the amount of memory, in bytes, currently
+ // consumed by the strong code roots.
+ size_t strong_code_roots_mem_size();
+
void print() const;
// Called during a stop-world phase to perform any deferred cleanups.
--- ./hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Wed May 07 19:26:16 2014 -0700
@@ -79,6 +79,10 @@
void reset() { if (_buf != NULL) _index = _sz; }
+ void enqueue(volatile void* ptr) {
+ enqueue((void*)(ptr));
+ }
+
// Enqueues the given "obj".
void enqueue(void* ptr) {
if (!_active) return;
--- ./hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed May 07 19:26:16 2014 -0700
@@ -923,7 +923,7 @@
GenCollectedHeap* gch = GenCollectedHeap::heap();
- _gc_timer->register_gc_start(os::elapsed_counter());
+ _gc_timer->register_gc_start();
assert(gch->kind() == CollectedHeap::GenCollectedHeap,
"not a CMS generational heap");
@@ -1100,7 +1100,7 @@
gch->trace_heap_after_gc(&gc_tracer);
gc_tracer.report_tenuring_threshold(tenuring_threshold());
- _gc_timer->register_gc_end(os::elapsed_counter());
+ _gc_timer->register_gc_end();
gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
}
--- ./hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Wed May 07 19:26:16 2014 -0700
@@ -90,14 +90,16 @@
og_min_size, og_max_size,
yg_min_size, yg_max_size);
- // The ReservedSpace ctor used below requires that the page size for the perm
- // gen is <= the page size for the rest of the heap (young + old gens).
const size_t og_page_sz = os::page_size_for_region(yg_min_size + og_min_size,
yg_max_size + og_max_size,
8);
- const size_t pg_page_sz = MIN2(os::page_size_for_region(pg_min_size,
- pg_max_size, 16),
- og_page_sz);
+
+ // Use the same page size for both perm gen and old gen,
+ // to allow large pages to be allocated when the heap is reserved
+ // for the implementations that can't 'commit' large pages.
+ // NEEDS_CLEANUP. ReservedHeapSpace/ReservedSpace that takes both
+ // a prefix and a suffix alignment can now be removed.
+ const size_t pg_page_sz = og_page_sz;
const size_t pg_align = set_alignment(_perm_gen_alignment, pg_page_sz);
const size_t og_align = set_alignment(_old_gen_alignment, og_page_sz);
@@ -138,12 +140,9 @@
total_reserved = add_and_check_overflow(total_reserved, og_max_size);
total_reserved = add_and_check_overflow(total_reserved, yg_max_size);
- char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
+ assert(is_size_aligned(total_reserved, og_align), "Must be");
- // The main part of the heap (old gen + young gen) can often use a larger page
- // size than is needed or wanted for the perm gen. Use the "compound
- // alignment" ReservedSpace ctor to avoid having to use the same page size for
- // all gens.
+ char* addr = Universe::preferred_heap_base(total_reserved, og_align, Universe::UnscaledNarrowOop);
ReservedHeapSpace heap_rs(pg_max_size, pg_align, og_max_size + yg_max_size,
og_align, addr);
@@ -153,12 +152,12 @@
// Failed to reserve at specified address - the requested memory
// region is taken already, for example, by 'java' launcher.
// Try again to reserver heap higher.
- addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
+ addr = Universe::preferred_heap_base(total_reserved, og_align, Universe::ZeroBasedNarrowOop);
ReservedHeapSpace heap_rs0(pg_max_size, pg_align, og_max_size + yg_max_size,
og_align, addr);
if (addr != NULL && !heap_rs0.is_reserved()) {
// Failed to reserve at specified address again - give up.
- addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
+ addr = Universe::preferred_heap_base(total_reserved, og_align, Universe::HeapBasedNarrowOop);
assert(addr == NULL, "");
ReservedHeapSpace heap_rs1(pg_max_size, pg_align, og_max_size + yg_max_size,
og_align, addr);
--- ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Wed May 07 19:26:16 2014 -0700
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
+#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
#include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
#include "gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
@@ -78,6 +79,38 @@
_old_gen_policy_is_ready = false;
}
+size_t PSAdaptiveSizePolicy::calculate_free_based_on_live(size_t live, uintx ratio_as_percentage) {
+ // We want to calculate how much free memory there can be based on the
+ // amount of live data currently in the old gen. Using the formula:
+ // ratio * (free + live) = free
+ // Some equation solving later we get:
+ // free = (live * ratio) / (1 - ratio)
+
+ const double ratio = ratio_as_percentage / 100.0;
+ const double ratio_inverse = 1.0 - ratio;
+ const double tmp = live * ratio;
+ size_t free = (size_t)(tmp / ratio_inverse);
+
+ return free;
+}
+
+size_t PSAdaptiveSizePolicy::calculated_old_free_size_in_bytes() const {
+ size_t free_size = (size_t)(_promo_size + avg_promoted()->padded_average());
+ size_t live = ParallelScavengeHeap::heap()->old_gen()->used_in_bytes();
+
+ if (MinHeapFreeRatio != 0) {
+ size_t min_free = calculate_free_based_on_live(live, MinHeapFreeRatio);
+ free_size = MAX2(free_size, min_free);
+ }
+
+ if (MaxHeapFreeRatio != 100) {
+ size_t max_free = calculate_free_based_on_live(live, MaxHeapFreeRatio);
+ free_size = MIN2(max_free, free_size);
+ }
+
+ return free_size;
+}
+
void PSAdaptiveSizePolicy::major_collection_begin() {
// Update the interval time
_major_timer.stop();
@@ -1107,3 +1140,18 @@
st,
PSScavenge::tenuring_threshold());
}
+
+#ifndef PRODUCT
+
+void TestOldFreeSpaceCalculation_test() {
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 20) == 25, "Calculation of free memory failed");
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 50) == 100, "Calculation of free memory failed");
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 60) == 150, "Calculation of free memory failed");
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(100, 75) == 300, "Calculation of free memory failed");
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 20) == 100, "Calculation of free memory failed");
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 50) == 400, "Calculation of free memory failed");
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 60) == 600, "Calculation of free memory failed");
+ assert(PSAdaptiveSizePolicy::calculate_free_based_on_live(400, 75) == 1200, "Calculation of free memory failed");
+}
+
+#endif /* !PRODUCT */
--- ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Wed May 07 19:26:16 2014 -0700
@@ -238,7 +238,6 @@
void major_collection_begin();
void major_collection_end(size_t amount_live, GCCause::Cause gc_cause);
- //
void tenured_allocation(size_t size) {
_avg_pretenured->sample(size);
}
@@ -246,9 +245,9 @@
// Accessors
// NEEDS_CLEANUP should use sizes.hpp
- size_t calculated_old_free_size_in_bytes() const {
- return (size_t)(_promo_size + avg_promoted()->padded_average());
- }
+ static size_t calculate_free_based_on_live(size_t live, uintx ratio_as_percentage);
+
+ size_t calculated_old_free_size_in_bytes() const;
size_t average_old_live_in_bytes() const {
return (size_t) avg_old_live()->average();
--- ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed May 07 19:26:16 2014 -0700
@@ -116,7 +116,7 @@
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
GCCause::Cause gc_cause = heap->gc_cause();
- _gc_timer->register_gc_start(os::elapsed_counter());
+ _gc_timer->register_gc_start();
_gc_tracer->report_gc_start(gc_cause, _gc_timer->gc_start());
PSAdaptiveSizePolicy* size_policy = heap->size_policy();
@@ -149,8 +149,7 @@
if (VerifyBeforeGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(" VerifyBeforeGC:");
- Universe::verify();
+ Universe::verify(" VerifyBeforeGC:");
}
// Verify object start arrays
@@ -359,8 +358,7 @@
if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(" VerifyAfterGC:");
- Universe::verify();
+ Universe::verify(" VerifyAfterGC:");
}
// Re-verify object start arrays
@@ -386,7 +384,7 @@
ParallelTaskTerminator::print_termination_counts();
#endif
- _gc_timer->register_gc_end(os::elapsed_counter());
+ _gc_timer->register_gc_end();
_gc_tracer->report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
--- ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -1034,8 +1034,7 @@
if (VerifyBeforeGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(" VerifyBeforeGC:");
- Universe::verify();
+ Universe::verify(" VerifyBeforeGC:");
}
// Verify object start arrays
@@ -2041,7 +2040,7 @@
ParallelScavengeHeap* heap = gc_heap();
- _gc_timer.register_gc_start(os::elapsed_counter());
+ _gc_timer.register_gc_start();
_gc_tracer.report_gc_start(heap->gc_cause(), _gc_timer.gc_start());
TimeStamp marking_start;
@@ -2248,8 +2247,7 @@
if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(" VerifyAfterGC:");
- Universe::verify();
+ Universe::verify(" VerifyAfterGC:");
}
// Re-verify object start arrays
@@ -2285,7 +2283,7 @@
ParallelTaskTerminator::print_termination_counts();
#endif
- _gc_timer.register_gc_end(os::elapsed_counter());
+ _gc_timer.register_gc_end();
_gc_tracer.report_dense_prefix(dense_prefix(old_space_id));
_gc_tracer.report_gc_end(_gc_timer.gc_end(), _gc_timer.time_partitions());
--- ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed May 07 19:26:16 2014 -0700
@@ -266,7 +266,7 @@
assert(_preserved_mark_stack.is_empty(), "should be empty");
assert(_preserved_oop_stack.is_empty(), "should be empty");
- _gc_timer.register_gc_start(os::elapsed_counter());
+ _gc_timer.register_gc_start();
TimeStamp scavenge_entry;
TimeStamp scavenge_midpoint;
@@ -325,8 +325,7 @@
if (VerifyBeforeGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(" VerifyBeforeGC:");
- Universe::verify();
+ Universe::verify(" VerifyBeforeGC:");
}
{
@@ -536,8 +535,19 @@
counters->update_survivor_overflowed(_survivor_overflow);
}
+ size_t max_young_size = young_gen->max_size();
+
+ // Deciding a free ratio in the young generation is tricky, so if
+ // MinHeapFreeRatio or MaxHeapFreeRatio are in use (implicating
+ // that the old generation size may have been limited because of them) we
+ // should then limit our young generation size using NewRatio to have it
+ // follow the old generation size.
+ if (MinHeapFreeRatio != 0 || MaxHeapFreeRatio != 100) {
+ max_young_size = MIN2(old_gen->capacity_in_bytes() / NewRatio, young_gen->max_size());
+ }
+
size_t survivor_limit =
- size_policy->max_survivor_size(young_gen->max_size());
+ size_policy->max_survivor_size(max_young_size);
_tenuring_threshold =
size_policy->compute_survivor_space_size_and_threshold(
_survivor_overflow,
@@ -560,8 +570,7 @@
// Do call at minor collections?
// Don't check if the size_policy is ready at this
// level. Let the size_policy check that internally.
- if (UseAdaptiveSizePolicy &&
- UseAdaptiveGenerationSizePolicyAtMinorCollection &&
+ if (UseAdaptiveGenerationSizePolicyAtMinorCollection &&
((gc_cause != GCCause::_java_lang_system_gc) ||
UseAdaptiveSizePolicyWithSystemGC)) {
@@ -570,7 +579,7 @@
young_gen->from_space()->capacity_in_bytes() +
young_gen->to_space()->capacity_in_bytes(),
"Sizes of space in young gen are out-of-bounds");
- size_t max_eden_size = young_gen->max_size() -
+ size_t max_eden_size = max_young_size -
young_gen->from_space()->capacity_in_bytes() -
young_gen->to_space()->capacity_in_bytes();
size_policy->compute_generation_free_space(young_gen->used_in_bytes(),
@@ -661,8 +670,7 @@
if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(" VerifyAfterGC:");
- Universe::verify();
+ Universe::verify(" VerifyAfterGC:");
}
heap->print_heap_after_gc();
@@ -689,7 +697,7 @@
#endif
- _gc_timer.register_gc_end(os::elapsed_counter());
+ _gc_timer.register_gc_end();
_gc_tracer.report_gc_end(_gc_timer.gc_end(), _gc_timer.time_partitions());
--- ./hotspot/src/share/vm/gc_implementation/shared/gcTimer.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/gcTimer.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, 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
@@ -25,52 +25,55 @@
#include "precompiled.hpp"
#include "gc_implementation/shared/gcTimer.hpp"
#include "utilities/growableArray.hpp"
+#include "utilities/ticks.inline.hpp"
-void GCTimer::register_gc_start(jlong time) {
+// the "time" parameter for most functions
+// has a default value set by Ticks::now()
+
+void GCTimer::register_gc_start(const Ticks& time) {
_time_partitions.clear();
_gc_start = time;
}
-void GCTimer::register_gc_end(jlong time) {
+void GCTimer::register_gc_end(const Ticks& time) {
assert(!_time_partitions.has_active_phases(),
"We should have ended all started phases, before ending the GC");
_gc_end = time;
}
-void GCTimer::register_gc_pause_start(const char* name, jlong time) {
+void GCTimer::register_gc_pause_start(const char* name, const Ticks& time) {
_time_partitions.report_gc_phase_start(name, time);
}
-void GCTimer::register_gc_pause_end(jlong time) {
+void GCTimer::register_gc_pause_end(const Ticks& time) {
_time_partitions.report_gc_phase_end(time);
}
-void GCTimer::register_gc_phase_start(const char* name, jlong time) {
+void GCTimer::register_gc_phase_start(const char* name, const Ticks& time) {
_time_partitions.report_gc_phase_start(name, time);
}
-void GCTimer::register_gc_phase_end(jlong time) {
+void GCTimer::register_gc_phase_end(const Ticks& time) {
_time_partitions.report_gc_phase_end(time);
}
-
-void STWGCTimer::register_gc_start(jlong time) {
+void STWGCTimer::register_gc_start(const Ticks& time) {
GCTimer::register_gc_start(time);
register_gc_pause_start("GC Pause", time);
}
-void STWGCTimer::register_gc_end(jlong time) {
+void STWGCTimer::register_gc_end(const Ticks& time) {
register_gc_pause_end(time);
GCTimer::register_gc_end(time);
}
-void ConcurrentGCTimer::register_gc_pause_start(const char* name, jlong time) {
- GCTimer::register_gc_pause_start(name, time);
+void ConcurrentGCTimer::register_gc_pause_start(const char* name) {
+ GCTimer::register_gc_pause_start(name);
}
-void ConcurrentGCTimer::register_gc_pause_end(jlong time) {
- GCTimer::register_gc_pause_end(time);
+void ConcurrentGCTimer::register_gc_pause_end() {
+ GCTimer::register_gc_pause_end();
}
void PhasesStack::clear() {
@@ -111,11 +114,11 @@
void TimePartitions::clear() {
_phases->clear();
_active_phases.clear();
- _sum_of_pauses = 0;
- _longest_pause = 0;
+ _sum_of_pauses = Tickspan();
+ _longest_pause = Tickspan();
}
-void TimePartitions::report_gc_phase_start(const char* name, jlong time) {
+void TimePartitions::report_gc_phase_start(const char* name, const Ticks& time) {
assert(_phases->length() <= 1000, "Too many recored phases?");
int level = _active_phases.count();
@@ -133,13 +136,13 @@
void TimePartitions::update_statistics(GCPhase* phase) {
// FIXME: This should only be done for pause phases
if (phase->level() == 0) {
- jlong pause = phase->end() - phase->start();
+ const Tickspan pause = phase->end() - phase->start();
_sum_of_pauses += pause;
_longest_pause = MAX2(pause, _longest_pause);
}
}
-void TimePartitions::report_gc_phase_end(jlong time) {
+void TimePartitions::report_gc_phase_end(const Ticks& time) {
int phase_index = _active_phases.pop();
GCPhase* phase = _phases->adr_at(phase_index);
phase->set_end(time);
@@ -157,14 +160,6 @@
return _phases->adr_at(index);
}
-jlong TimePartitions::sum_of_pauses() {
- return _sum_of_pauses;
-}
-
-jlong TimePartitions::longest_pause() {
- return _longest_pause;
-}
-
bool TimePartitions::has_active_phases() {
return _active_phases.count() > 0;
}
@@ -194,7 +189,7 @@
max_nested_pause_phases();
}
- static void validate_pause_phase(GCPhase* phase, int level, const char* name, jlong start, jlong end) {
+ static void validate_pause_phase(GCPhase* phase, int level, const char* name, const Ticks& start, const Ticks& end) {
assert(phase->level() == level, "Incorrect level");
assert(strcmp(phase->name(), name) == 0, "Incorrect name");
assert(phase->start() == start, "Incorrect start");
@@ -209,8 +204,8 @@
TimePartitionPhasesIterator iter(&time_partitions);
validate_pause_phase(iter.next(), 0, "PausePhase", 2, 8);
- assert(time_partitions.sum_of_pauses() == 8-2, "Incorrect");
- assert(time_partitions.longest_pause() == 8-2, "Incorrect");
+ assert(time_partitions.sum_of_pauses() == Ticks(8) - Ticks(2), "Incorrect");
+ assert(time_partitions.longest_pause() == Ticks(8) - Ticks(2), "Incorrect");
assert(!iter.has_next(), "Too many elements");
}
@@ -227,8 +222,8 @@
validate_pause_phase(iter.next(), 0, "PausePhase1", 2, 3);
validate_pause_phase(iter.next(), 0, "PausePhase2", 4, 6);
- assert(time_partitions.sum_of_pauses() == 3, "Incorrect");
- assert(time_partitions.longest_pause() == 2, "Incorrect");
+ assert(time_partitions.sum_of_pauses() == Ticks(3) - Ticks(0), "Incorrect");
+ assert(time_partitions.longest_pause() == Ticks(2) - Ticks(0), "Incorrect");
assert(!iter.has_next(), "Too many elements");
}
@@ -245,8 +240,8 @@
validate_pause_phase(iter.next(), 0, "PausePhase", 2, 5);
validate_pause_phase(iter.next(), 1, "SubPhase", 3, 4);
- assert(time_partitions.sum_of_pauses() == 3, "Incorrect");
- assert(time_partitions.longest_pause() == 3, "Incorrect");
+ assert(time_partitions.sum_of_pauses() == Ticks(3) - Ticks(0), "Incorrect");
+ assert(time_partitions.longest_pause() == Ticks(3) - Ticks(0), "Incorrect");
assert(!iter.has_next(), "Too many elements");
}
@@ -269,8 +264,8 @@
validate_pause_phase(iter.next(), 2, "SubPhase2", 4, 7);
validate_pause_phase(iter.next(), 3, "SubPhase3", 5, 6);
- assert(time_partitions.sum_of_pauses() == 7, "Incorrect");
- assert(time_partitions.longest_pause() == 7, "Incorrect");
+ assert(time_partitions.sum_of_pauses() == Ticks(7) - Ticks(0), "Incorrect");
+ assert(time_partitions.longest_pause() == Ticks(7) - Ticks(0), "Incorrect");
assert(!iter.has_next(), "Too many elements");
}
@@ -298,8 +293,8 @@
validate_pause_phase(iter.next(), 1, "SubPhase3", 7, 8);
validate_pause_phase(iter.next(), 1, "SubPhase4", 9, 10);
- assert(time_partitions.sum_of_pauses() == 9, "Incorrect");
- assert(time_partitions.longest_pause() == 9, "Incorrect");
+ assert(time_partitions.sum_of_pauses() == Ticks(9) - Ticks(0), "Incorrect");
+ assert(time_partitions.longest_pause() == Ticks(9) - Ticks(0), "Incorrect");
assert(!iter.has_next(), "Too many elements");
}
@@ -336,8 +331,8 @@
validate_pause_phase(iter.next(), 2, "SubPhase22", 12, 13);
validate_pause_phase(iter.next(), 1, "SubPhase3", 15, 16);
- assert(time_partitions.sum_of_pauses() == 15, "Incorrect");
- assert(time_partitions.longest_pause() == 15, "Incorrect");
+ assert(time_partitions.sum_of_pauses() == Ticks(15) - Ticks(0), "Incorrect");
+ assert(time_partitions.longest_pause() == Ticks(15) - Ticks(0), "Incorrect");
assert(!iter.has_next(), "Too many elements");
}
--- ./hotspot/src/share/vm/gc_implementation/shared/gcTimer.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/gcTimer.hpp Wed May 07 19:26:16 2014 -0700
@@ -28,6 +28,7 @@
#include "memory/allocation.hpp"
#include "prims/jni_md.h"
#include "utilities/macros.hpp"
+#include "utilities/ticks.hpp"
class ConcurrentPhase;
class GCPhase;
@@ -45,21 +46,21 @@
class GCPhase {
const char* _name;
int _level;
- jlong _start;
- jlong _end;
+ Ticks _start;
+ Ticks _end;
public:
void set_name(const char* name) { _name = name; }
- const char* name() { return _name; }
+ const char* name() const { return _name; }
- int level() { return _level; }
+ int level() const { return _level; }
void set_level(int level) { _level = level; }
- jlong start() { return _start; }
- void set_start(jlong time) { _start = time; }
+ const Ticks start() const { return _start; }
+ void set_start(const Ticks& time) { _start = time; }
- jlong end() { return _end; }
- void set_end(jlong time) { _end = time; }
+ const Ticks end() const { return _end; }
+ void set_end(const Ticks& time) { _end = time; }
virtual void accept(PhaseVisitor* visitor) = 0;
};
@@ -102,22 +103,22 @@
GrowableArray* _phases;
PhasesStack _active_phases;
- jlong _sum_of_pauses;
- jlong _longest_pause;
+ Tickspan _sum_of_pauses;
+ Tickspan _longest_pause;
public:
TimePartitions();
~TimePartitions();
void clear();
- void report_gc_phase_start(const char* name, jlong time);
- void report_gc_phase_end(jlong time);
+ void report_gc_phase_start(const char* name, const Ticks& time);
+ void report_gc_phase_end(const Ticks& time);
int num_phases() const;
GCPhase* phase_at(int index) const;
- jlong sum_of_pauses();
- jlong longest_pause();
+ const Tickspan sum_of_pauses() const { return _sum_of_pauses; }
+ const Tickspan longest_pause() const { return _longest_pause; }
bool has_active_phases();
private:
@@ -133,40 +134,37 @@
class GCTimer : public ResourceObj {
NOT_PRODUCT(friend class GCTimerTest;)
protected:
- jlong _gc_start;
- jlong _gc_end;
+ Ticks _gc_start;
+ Ticks _gc_end;
TimePartitions _time_partitions;
public:
- virtual void register_gc_start(jlong time);
- virtual void register_gc_end(jlong time);
+ virtual void register_gc_start(const Ticks& time = Ticks::now());
+ virtual void register_gc_end(const Ticks& time = Ticks::now());
- void register_gc_phase_start(const char* name, jlong time);
- void register_gc_phase_end(jlong time);
+ void register_gc_phase_start(const char* name, const Ticks& time);
+ void register_gc_phase_end(const Ticks& time);
- jlong gc_start() { return _gc_start; }
- jlong gc_end() { return _gc_end; }
+ const Ticks gc_start() const { return _gc_start; }
+ const Ticks gc_end() const { return _gc_end; }
TimePartitions* time_partitions() { return &_time_partitions; }
- long longest_pause();
- long sum_of_pauses();
-
protected:
- void register_gc_pause_start(const char* name, jlong time);
- void register_gc_pause_end(jlong time);
+ void register_gc_pause_start(const char* name, const Ticks& time = Ticks::now());
+ void register_gc_pause_end(const Ticks& time = Ticks::now());
};
class STWGCTimer : public GCTimer {
public:
- virtual void register_gc_start(jlong time);
- virtual void register_gc_end(jlong time);
+ virtual void register_gc_start(const Ticks& time = Ticks::now());
+ virtual void register_gc_end(const Ticks& time = Ticks::now());
};
class ConcurrentGCTimer : public GCTimer {
public:
- void register_gc_pause_start(const char* name, jlong time);
- void register_gc_pause_end(jlong time);
+ void register_gc_pause_start(const char* name);
+ void register_gc_pause_end();
};
class TimePartitionPhasesIterator {
--- ./hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp Wed May 07 19:26:16 2014 -0700
@@ -33,6 +33,7 @@
#include "memory/referenceProcessorStats.hpp"
#include "runtime/os.hpp"
#include "utilities/globalDefinitions.hpp"
+#include "utilities/ticks.inline.hpp"
#ifndef SERIALGC
#include "gc_implementation/g1/evacuationInfo.hpp"
@@ -46,7 +47,7 @@
return GCTracer_next_gc_id++;
}
-void GCTracer::report_gc_start_impl(GCCause::Cause cause, jlong timestamp) {
+void GCTracer::report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp) {
assert_unset_gc_id();
GCId gc_id = create_new_gc_id();
@@ -55,7 +56,7 @@
_shared_gc_info.set_start_timestamp(timestamp);
}
-void GCTracer::report_gc_start(GCCause::Cause cause, jlong timestamp) {
+void GCTracer::report_gc_start(GCCause::Cause cause, const Ticks& timestamp) {
assert_unset_gc_id();
report_gc_start_impl(cause, timestamp);
@@ -65,7 +66,7 @@
return _shared_gc_info.id() != SharedGCInfo::UNSET_GCID;
}
-void GCTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) {
+void GCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
assert_set_gc_id();
_shared_gc_info.set_sum_of_pauses(time_partitions->sum_of_pauses());
@@ -76,7 +77,7 @@
send_garbage_collection_event();
}
-void GCTracer::report_gc_end(jlong timestamp, TimePartitions* time_partitions) {
+void GCTracer::report_gc_end(const Ticks& timestamp, TimePartitions* time_partitions) {
assert_set_gc_id();
report_gc_end_impl(timestamp, time_partitions);
@@ -97,10 +98,10 @@
const GCId _gc_id;
const double _size_threshold_percentage;
const size_t _total_size_in_words;
- const jlong _timestamp;
+ const Ticks _timestamp;
public:
- ObjectCountEventSenderClosure(GCId gc_id, size_t total_size_in_words, jlong timestamp) :
+ ObjectCountEventSenderClosure(GCId gc_id, size_t total_size_in_words, const Ticks& timestamp) :
_gc_id(gc_id),
_size_threshold_percentage(ObjectCountCutOffPercent / 100),
_total_size_in_words(total_size_in_words),
@@ -154,8 +155,7 @@
ObjectCountFilter object_filter(is_alive_cl);
HeapInspection::populate_table(&cit, false, &object_filter);
- jlong timestamp = os::elapsed_counter();
- ObjectCountEventSenderClosure event_sender(_shared_gc_info.id(), cit.size_of_instances_in_words(), timestamp);
+ ObjectCountEventSenderClosure event_sender(_shared_gc_info.id(), cit.size_of_instances_in_words(), Ticks::now());
cit.iterate(&event_sender);
}
}
@@ -168,7 +168,7 @@
send_perm_gen_summary_event(when, perm_gen_summary);
}
-void YoungGCTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) {
+void YoungGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
assert_set_gc_id();
assert(_tenuring_threshold != UNSET_TENURING_THRESHOLD, "Tenuring threshold has not been reported");
@@ -188,14 +188,14 @@
_tenuring_threshold = tenuring_threshold;
}
-void OldGCTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) {
+void OldGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
assert_set_gc_id();
GCTracer::report_gc_end_impl(timestamp, time_partitions);
send_old_gc_event();
}
-void ParallelOldTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) {
+void ParallelOldTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
assert_set_gc_id();
OldGCTracer::report_gc_end_impl(timestamp, time_partitions);
@@ -221,7 +221,7 @@
_g1_young_gc_info.set_type(type);
}
-void G1NewTracer::report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions) {
+void G1NewTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
assert_set_gc_id();
YoungGCTracer::report_gc_end_impl(timestamp, time_partitions);
--- ./hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp Wed May 07 19:26:16 2014 -0700
@@ -34,6 +34,7 @@
#ifndef SERIALGC
#include "gc_implementation/g1/g1YCTypes.hpp"
#endif
+#include "utilities/ticks.hpp"
typedef uint GCId;
@@ -46,8 +47,6 @@
class BoolObjectClosure;
class SharedGCInfo VALUE_OBJ_CLASS_SPEC {
- static const jlong UNSET_TIMESTAMP = -1;
-
public:
static const GCId UNSET_GCID = (GCId)-1;
@@ -55,23 +54,30 @@
GCId _id;
GCName _name;
GCCause::Cause _cause;
- jlong _start_timestamp;
- jlong _end_timestamp;
- jlong _sum_of_pauses;
- jlong _longest_pause;
+ Ticks _start_timestamp;
+ Ticks _end_timestamp;
+ Tickspan _sum_of_pauses;
+ Tickspan _longest_pause;
public:
- SharedGCInfo(GCName name) : _id(UNSET_GCID), _name(name), _cause(GCCause::_last_gc_cause),
- _start_timestamp(UNSET_TIMESTAMP), _end_timestamp(UNSET_TIMESTAMP), _sum_of_pauses(0), _longest_pause(0) {}
+ SharedGCInfo(GCName name) :
+ _id(UNSET_GCID),
+ _name(name),
+ _cause(GCCause::_last_gc_cause),
+ _start_timestamp(),
+ _end_timestamp(),
+ _sum_of_pauses(),
+ _longest_pause() {
+ }
void set_id(GCId id) { _id = id; }
GCId id() const { return _id; }
- void set_start_timestamp(jlong timestamp) { _start_timestamp = timestamp; }
- jlong start_timestamp() const { return _start_timestamp; }
+ void set_start_timestamp(const Ticks& timestamp) { _start_timestamp = timestamp; }
+ const Ticks start_timestamp() const { return _start_timestamp; }
- void set_end_timestamp(jlong timestamp) { _end_timestamp = timestamp; }
- jlong end_timestamp() const { return _end_timestamp; }
+ void set_end_timestamp(const Ticks& timestamp) { _end_timestamp = timestamp; }
+ const Ticks end_timestamp() const { return _end_timestamp; }
void set_name(GCName name) { _name = name; }
GCName name() const { return _name; }
@@ -79,11 +85,11 @@
void set_cause(GCCause::Cause cause) { _cause = cause; }
GCCause::Cause cause() const { return _cause; }
- void set_sum_of_pauses(jlong duration) { _sum_of_pauses = duration; }
- jlong sum_of_pauses() const { return _sum_of_pauses; }
+ void set_sum_of_pauses(const Tickspan& duration) { _sum_of_pauses = duration; }
+ const Tickspan sum_of_pauses() const { return _sum_of_pauses; }
- void set_longest_pause(jlong duration) { _longest_pause = duration; }
- jlong longest_pause() const { return _longest_pause; }
+ void set_longest_pause(const Tickspan& duration) { _longest_pause = duration; }
+ const Tickspan longest_pause() const { return _longest_pause; }
};
class ParallelOldGCInfo VALUE_OBJ_CLASS_SPEC {
@@ -115,8 +121,8 @@
SharedGCInfo _shared_gc_info;
public:
- void report_gc_start(GCCause::Cause cause, jlong timestamp);
- void report_gc_end(jlong timestamp, TimePartitions* time_partitions);
+ void report_gc_start(GCCause::Cause cause, const Ticks& timestamp);
+ void report_gc_end(const Ticks& timestamp, TimePartitions* time_partitions);
void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const PermGenSummary& perm_gen_summary) const;
void report_gc_reference_stats(const ReferenceProcessorStats& rp) const;
void report_object_count_after_gc(BoolObjectClosure* object_filter);
@@ -125,8 +131,8 @@
protected:
GCTracer(GCName name) : _shared_gc_info(name) {}
- virtual void report_gc_start_impl(GCCause::Cause cause, jlong timestamp);
- virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions);
+ virtual void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp);
+ virtual void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions);
private:
void send_garbage_collection_event() const;
@@ -143,7 +149,7 @@
protected:
YoungGCTracer(GCName name) : GCTracer(name), _tenuring_threshold(UNSET_TENURING_THRESHOLD) {}
- virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions);
+ virtual void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions);
public:
void report_promotion_failed(const PromotionFailedInfo& pf_info);
@@ -157,7 +163,7 @@
class OldGCTracer : public GCTracer {
protected:
OldGCTracer(GCName name) : GCTracer(name) {}
- virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions);
+ virtual void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions);
public:
void report_concurrent_mode_failure();
@@ -175,7 +181,7 @@
void report_dense_prefix(void* dense_prefix);
protected:
- void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions);
+ void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions);
private:
void send_parallel_old_event() const;
@@ -209,7 +215,7 @@
G1NewTracer() : YoungGCTracer(G1New) {}
void report_yc_type(G1YCType type);
- void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions);
+ void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions);
void report_evacuation_info(EvacuationInfo* info);
void report_evacuation_failed(EvacuationFailedInfo& ef_info);
--- ./hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Wed May 07 19:26:16 2014 -0700
@@ -28,8 +28,10 @@
#include "gc_implementation/shared/gcTrace.hpp"
#include "gc_implementation/shared/gcWhen.hpp"
#include "gc_implementation/shared/copyFailedInfo.hpp"
+#include "runtime/os.hpp"
#include "trace/traceBackend.hpp"
#include "trace/tracing.hpp"
+
#ifndef SERIALGC
#include "gc_implementation/g1/evacuationInfo.hpp"
#include "gc_implementation/g1/g1YCTypes.hpp"
--- ./hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, 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
@@ -43,11 +43,13 @@
# include "thread_bsd.inline.hpp"
#endif
+#include "utilities/ticks.inline.hpp"
+
GCTraceTime::GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer) :
- _title(title), _doit(doit), _print_cr(print_cr), _timer(timer) {
+ _title(title), _doit(doit), _print_cr(print_cr), _timer(timer), _start_counter() {
if (_doit || _timer != NULL) {
- _start_counter = os::elapsed_counter();
+ _start_counter.stamp();
}
if (_timer != NULL) {
@@ -66,10 +68,10 @@
}
GCTraceTime::~GCTraceTime() {
- jlong stop_counter = 0;
+ Ticks stop_counter;
if (_doit || _timer != NULL) {
- stop_counter = os::elapsed_counter();
+ stop_counter.stamp();
}
if (_timer != NULL) {
@@ -77,11 +79,12 @@
}
if (_doit) {
- double seconds = TimeHelper::counter_to_seconds(stop_counter - _start_counter);
+ const Tickspan duration = stop_counter - _start_counter;
+ double duration_in_seconds = TicksToTimeHelper::seconds(duration);
if (_print_cr) {
- gclog_or_tty->print_cr(", %3.7f secs]", seconds);
+ gclog_or_tty->print_cr(", %3.7f secs]", duration_in_seconds);
} else {
- gclog_or_tty->print(", %3.7f secs]", seconds);
+ gclog_or_tty->print(", %3.7f secs]", duration_in_seconds);
}
gclog_or_tty->flush();
}
--- ./hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp Wed May 07 19:26:16 2014 -0700
@@ -26,6 +26,7 @@
#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP
#include "prims/jni_md.h"
+#include "utilities/ticks.hpp"
class GCTimer;
@@ -34,7 +35,7 @@
bool _doit;
bool _print_cr;
GCTimer* _timer;
- jlong _start_counter;
+ Ticks _start_counter;
public:
GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer);
--- ./hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp Wed May 07 19:26:16 2014 -0700
@@ -28,8 +28,10 @@
#include "memory/heapInspection.hpp"
#include "trace/tracing.hpp"
#include "utilities/globalDefinitions.hpp"
+#include "utilities/ticks.hpp"
-void ObjectCountEventSender::send(const KlassInfoEntry* entry, GCId gc_id, jlong timestamp) {
+void ObjectCountEventSender::send(const KlassInfoEntry* entry, GCId gc_id, const Ticks& timestamp) {
+#if INCLUDE_TRACE
assert(Tracing::is_event_enabled(EventObjectCountAfterGC::eventId),
"Only call this method if the event is enabled");
@@ -40,6 +42,8 @@
event.set_totalSize(entry->words() * BytesPerWord);
event.set_endtime(timestamp);
event.commit();
+
+#endif
}
bool ObjectCountEventSender::should_send_event() {
--- ./hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp Wed May 07 19:26:16 2014 -0700
@@ -29,10 +29,11 @@
#include "memory/allocation.hpp"
class KlassInfoEntry;
+class Ticks;
class ObjectCountEventSender : public AllStatic {
public:
- static void send(const KlassInfoEntry* entry, GCId gc_id, jlong timestamp);
+ static void send(const KlassInfoEntry* entry, GCId gc_id, const Ticks& timestamp);
static bool should_send_event();
};
--- ./hotspot/src/share/vm/gc_interface/collectedHeap.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_interface/collectedHeap.cpp Wed May 07 19:26:16 2014 -0700
@@ -121,6 +121,14 @@
}
}
+void CollectedHeap::register_nmethod(nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+}
+
+void CollectedHeap::unregister_nmethod(nmethod* nm) {
+ assert_locked_or_safepoint(CodeCache_lock);
+}
+
void CollectedHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) {
const GCHeapSummary& heap_summary = create_heap_summary();
const PermGenSummary& perm_summary = create_perm_gen_summary();
--- ./hotspot/src/share/vm/gc_interface/collectedHeap.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed May 07 19:26:16 2014 -0700
@@ -49,6 +49,7 @@
class Thread;
class ThreadClosure;
class VirtualSpaceSummary;
+class nmethod;
class GCMessage : public FormatBuffer<1024> {
public:
@@ -667,6 +668,11 @@
void print_heap_before_gc();
void print_heap_after_gc();
+ // Registering and unregistering an nmethod (compiled code) with the heap.
+ // Override with specific mechanism for each specialized heap type.
+ virtual void register_nmethod(nmethod* nm);
+ virtual void unregister_nmethod(nmethod* nm);
+
void trace_heap_before_gc(GCTracer* gc_tracer);
void trace_heap_after_gc(GCTracer* gc_tracer);
--- ./hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -1222,3 +1222,24 @@
size_of_arguments * Interpreter::stackElementSize);
IRT_END
#endif
+
+// This is a support of the JVMTI PopFrame interface.
+// Make sure it is an invokestatic of a polymorphic intrinsic that has a member_name argument
+// and return it as a vm_result so that it can be reloaded in the list of invokestatic parameters.
+// The dmh argument is a reference to a DirectMethoHandle that has a member name field.
+IRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread, address dmh,
+ methodOopDesc* method, address bcp))
+ Bytecodes::Code code = Bytecodes::code_at(method, bcp);
+ if (code != Bytecodes::_invokestatic) {
+ return;
+ }
+ constantPoolOopDesc* cpool = method->constants();
+ int cp_index = Bytes::get_native_u2(bcp + 1) + constantPoolOopDesc::CPCACHE_INDEX_TAG;
+ Symbol* cname = cpool->klass_name_at(cpool->klass_ref_index_at(cp_index));
+ Symbol* mname = cpool->name_ref_at(cp_index);
+
+ if (MethodHandles::has_member_arg(cname, mname)) {
+ oop member_name = java_lang_invoke_DirectMethodHandle::member((oop)dmh);
+ thread->set_vm_result(member_name);
+ }
+IRT_END
--- ./hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -106,6 +106,7 @@
static void create_exception(JavaThread* thread, char* name, char* message);
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
+ static void member_name_arg_or_null(JavaThread* thread, address dmh, methodOopDesc* m, address bcp);
static void throw_pending_exception(JavaThread* thread);
// Statics & fields
--- ./hotspot/src/share/vm/memory/cardTableModRefBS.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/cardTableModRefBS.cpp Wed May 07 19:26:16 2014 -0700
@@ -400,60 +400,6 @@
inline_write_ref_field(field, newVal);
}
-/*
- Claimed and deferred bits are used together in G1 during the evacuation
- pause. These bits can have the following state transitions:
- 1. The claimed bit can be put over any other card state. Except that
- the "dirty -> dirty and claimed" transition is checked for in
- G1 code and is not used.
- 2. Deferred bit can be set only if the previous state of the card
- was either clean or claimed. mark_card_deferred() is wait-free.
- We do not care if the operation is be successful because if
- it does not it will only result in duplicate entry in the update
- buffer because of the "cache-miss". So it's not worth spinning.
- */
-
-
-bool CardTableModRefBS::claim_card(size_t card_index) {
- jbyte val = _byte_map[card_index];
- assert(val != dirty_card_val(), "Shouldn't claim a dirty card");
- while (val == clean_card_val() ||
- (val & (clean_card_mask_val() | claimed_card_val())) != claimed_card_val()) {
- jbyte new_val = val;
- if (val == clean_card_val()) {
- new_val = (jbyte)claimed_card_val();
- } else {
- new_val = val | (jbyte)claimed_card_val();
- }
- jbyte res = Atomic::cmpxchg(new_val, &_byte_map[card_index], val);
- if (res == val) {
- return true;
- }
- val = res;
- }
- return false;
-}
-
-bool CardTableModRefBS::mark_card_deferred(size_t card_index) {
- jbyte val = _byte_map[card_index];
- // It's already processed
- if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
- return false;
- }
- // Cached bit can be installed either on a clean card or on a claimed card.
- jbyte new_val = val;
- if (val == clean_card_val()) {
- new_val = (jbyte)deferred_card_val();
- } else {
- if (val & claimed_card_val()) {
- new_val = val | (jbyte)deferred_card_val();
- }
- }
- if (new_val != val) {
- Atomic::cmpxchg(new_val, &_byte_map[card_index], val);
- }
- return true;
-}
void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp,
MemRegion mr,
--- ./hotspot/src/share/vm/memory/cardTableModRefBS.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/cardTableModRefBS.hpp Wed May 07 19:26:16 2014 -0700
@@ -344,34 +344,10 @@
_byte_map[card_index] = dirty_card_val();
}
- bool is_card_claimed(size_t card_index) {
- jbyte val = _byte_map[card_index];
- return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
- }
-
- void set_card_claimed(size_t card_index) {
- jbyte val = _byte_map[card_index];
- if (val == clean_card_val()) {
- val = (jbyte)claimed_card_val();
- } else {
- val |= (jbyte)claimed_card_val();
- }
- _byte_map[card_index] = val;
- }
-
- bool claim_card(size_t card_index);
-
bool is_card_clean(size_t card_index) {
return _byte_map[card_index] == clean_card_val();
}
- bool is_card_deferred(size_t card_index) {
- jbyte val = _byte_map[card_index];
- return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
- }
-
- bool mark_card_deferred(size_t card_index);
-
// Card marking array base (adjusted for heap low boundary)
// This would be the 0th element of _byte_map, if the heap started at 0x0.
// But since the heap starts at some higher address, this points to somewhere
--- ./hotspot/src/share/vm/memory/collectorPolicy.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/collectorPolicy.cpp Wed May 07 19:26:16 2014 -0700
@@ -230,6 +230,8 @@
alignment = lcm(os::large_page_size(), alignment);
}
+ assert(alignment >= min_alignment(), "Must be");
+
return alignment;
}
--- ./hotspot/src/share/vm/memory/defNewGeneration.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/defNewGeneration.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, 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
@@ -538,7 +538,7 @@
GenCollectedHeap* gch = GenCollectedHeap::heap();
- _gc_timer->register_gc_start(os::elapsed_counter());
+ _gc_timer->register_gc_start();
DefNewTracer gc_tracer;
gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start());
@@ -682,7 +682,7 @@
gch->trace_heap_after_gc(&gc_tracer);
gc_tracer.report_tenuring_threshold(tenuring_threshold());
- _gc_timer->register_gc_end(os::elapsed_counter());
+ _gc_timer->register_gc_end();
gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
}
@@ -1004,6 +1004,9 @@
// have to use it here, as well.
HeapWord* result = eden()->par_allocate(word_size);
if (result != NULL) {
+ if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
+ _next_gen->sample_eden_chunk();
+ }
return result;
}
do {
@@ -1034,13 +1037,19 @@
// circular dependency at compile time.
if (result == NULL) {
result = allocate_from_space(word_size);
+ } else if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
+ _next_gen->sample_eden_chunk();
}
return result;
}
HeapWord* DefNewGeneration::par_allocate(size_t word_size,
bool is_tlab) {
- return eden()->par_allocate(word_size);
+ HeapWord* res = eden()->par_allocate(word_size);
+ if (CMSEdenChunksRecordAlways && _next_gen != NULL) {
+ _next_gen->sample_eden_chunk();
+ }
+ return res;
}
void DefNewGeneration::gc_prologue(bool full) {
--- ./hotspot/src/share/vm/memory/genCollectedHeap.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/genCollectedHeap.cpp Wed May 07 19:26:16 2014 -0700
@@ -99,17 +99,19 @@
guarantee(HeapWordSize == wordSize, "HeapWordSize must equal wordSize");
// The heap must be at least as aligned as generations.
- size_t alignment = Generation::GenGrain;
+ size_t gen_alignment = Generation::GenGrain;
_gen_specs = gen_policy()->generations();
PermanentGenerationSpec *perm_gen_spec =
collector_policy()->permanent_generation();
+ size_t heap_alignment = collector_policy()->max_alignment();
+
// Make sure the sizes are all aligned.
for (i = 0; i < _n_gens; i++) {
- _gen_specs[i]->align(alignment);
+ _gen_specs[i]->align(gen_alignment);
}
- perm_gen_spec->align(alignment);
+ perm_gen_spec->align(heap_alignment);
// If we are dumping the heap, then allocate a wasted block of address
// space in order to push the heap to a lower address. This extra
@@ -130,9 +132,9 @@
char* heap_address;
size_t total_reserved = 0;
int n_covered_regions = 0;
- ReservedSpace heap_rs(0);
+ ReservedSpace heap_rs;
- heap_address = allocate(alignment, perm_gen_spec, &total_reserved,
+ heap_address = allocate(heap_alignment, perm_gen_spec, &total_reserved,
&n_covered_regions, &heap_rs);
if (UseSharedSpaces) {
@@ -142,7 +144,7 @@
}
FileMapInfo* mapinfo = FileMapInfo::current_info();
mapinfo->fail_continue("Unable to reserve shared region.");
- allocate(alignment, perm_gen_spec, &total_reserved, &n_covered_regions,
+ allocate(heap_alignment, perm_gen_spec, &total_reserved, &n_covered_regions,
&heap_rs);
}
}
@@ -207,19 +209,21 @@
const size_t pageSize = UseLargePages ?
os::large_page_size() : os::vm_page_size();
+ assert(alignment % pageSize == 0, "Must be");
+
for (int i = 0; i < _n_gens; i++) {
total_reserved = add_and_check_overflow(total_reserved, _gen_specs[i]->max_size());
n_covered_regions += _gen_specs[i]->n_covered_regions();
}
- assert(total_reserved % pageSize == 0,
- err_msg("Gen size; total_reserved=" SIZE_FORMAT ", pageSize="
- SIZE_FORMAT, total_reserved, pageSize));
+ assert(total_reserved % alignment == 0,
+ err_msg("Gen size; total_reserved=" SIZE_FORMAT ", alignment="
+ SIZE_FORMAT, total_reserved, alignment));
total_reserved = add_and_check_overflow(total_reserved, perm_gen_spec->max_size());
- assert(total_reserved % pageSize == 0,
- err_msg("Perm size; total_reserved=" SIZE_FORMAT ", pageSize="
+ assert(total_reserved % alignment == 0,
+ err_msg("Perm size; total_reserved=" SIZE_FORMAT ", alignment="
SIZE_FORMAT ", perm gen max=" SIZE_FORMAT, total_reserved,
- pageSize, perm_gen_spec->max_size()));
+ alignment, perm_gen_spec->max_size()));
n_covered_regions += perm_gen_spec->n_covered_regions();
@@ -229,7 +233,9 @@
total_reserved = add_and_check_overflow(total_reserved, misc);
if (UseLargePages) {
+ assert(misc == 0, "CDS does not support Large Pages");
assert(total_reserved != 0, "total_reserved cannot be 0");
+ assert(is_size_aligned(total_reserved, os::large_page_size()), "Must be");
total_reserved = round_up_and_check_overflow(total_reserved, os::large_page_size());
}
@@ -250,7 +256,7 @@
} else {
heap_address = NULL; // any address will do.
if (UseCompressedOops) {
- heap_address = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
+ heap_address = Universe::preferred_heap_base(total_reserved, alignment, Universe::UnscaledNarrowOop);
*_total_reserved = total_reserved;
*_n_covered_regions = n_covered_regions;
*heap_rs = ReservedHeapSpace(total_reserved, alignment,
@@ -260,13 +266,13 @@
// Failed to reserve at specified address - the requested memory
// region is taken already, for example, by 'java' launcher.
// Try again to reserver heap higher.
- heap_address = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
+ heap_address = Universe::preferred_heap_base(total_reserved, alignment, Universe::ZeroBasedNarrowOop);
*heap_rs = ReservedHeapSpace(total_reserved, alignment,
UseLargePages, heap_address);
if (heap_address != NULL && !heap_rs->is_reserved()) {
// Failed to reserve at specified address again - give up.
- heap_address = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
+ heap_address = Universe::preferred_heap_base(total_reserved, alignment, Universe::HeapBasedNarrowOop);
assert(heap_address == NULL, "");
*heap_rs = ReservedHeapSpace(total_reserved, alignment,
UseLargePages, heap_address);
@@ -538,8 +544,7 @@
prepare_for_verify();
prepared_for_verification = true;
}
- gclog_or_tty->print(" VerifyBeforeGC:");
- Universe::verify();
+ Universe::verify(" VerifyBeforeGC:");
}
COMPILER2_PRESENT(DerivedPointerTable::clear());
@@ -610,8 +615,7 @@
if (VerifyAfterGC && i >= VerifyGCLevel &&
total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
- gclog_or_tty->print(" VerifyAfterGC:");
- Universe::verify();
+ Universe::verify(" VerifyAfterGC:");
}
if (PrintGCDetails) {
@@ -932,12 +936,13 @@
// Returns "TRUE" iff "p" points into the committed areas of the heap.
bool GenCollectedHeap::is_in(const void* p) const {
#ifndef ASSERT
- guarantee(VerifyBeforeGC ||
- VerifyDuringGC ||
- VerifyBeforeExit ||
- PrintAssembly ||
- tty->count() != 0 || // already printing
- VerifyAfterGC ||
+ guarantee(VerifyBeforeGC ||
+ VerifyDuringGC ||
+ VerifyBeforeExit ||
+ VerifyDuringStartup ||
+ PrintAssembly ||
+ tty->count() != 0 || // already printing
+ VerifyAfterGC ||
VMError::fatal_error_in_progress(), "too expensive");
#endif
--- ./hotspot/src/share/vm/memory/generation.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/generation.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -476,16 +476,16 @@
x(ref_processor(), gch->reserved_region());
STWGCTimer* gc_timer = GenMarkSweep::gc_timer();
- gc_timer->register_gc_start(os::elapsed_counter());
+ gc_timer->register_gc_start();
SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
GenMarkSweep::invoke_at_safepoint(_level, ref_processor(), clear_all_soft_refs);
- gc_timer->register_gc_end(os::elapsed_counter());
+ gc_timer->register_gc_end();
- gc_tracer->report_gc_end(os::elapsed_counter(), gc_timer->time_partitions());
+ gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions());
SpecializationStats::print();
}
--- ./hotspot/src/share/vm/memory/generation.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/generation.hpp Wed May 07 19:26:16 2014 -0700
@@ -457,6 +457,7 @@
// expected to be GC worker thread-local, with the worker index
// indicated by "thr_num".
virtual void* get_data_recorder(int thr_num) { return NULL; }
+ virtual void sample_eden_chunk() {}
// Some generations may require some cleanup actions before allowing
// a verification.
--- ./hotspot/src/share/vm/memory/iterator.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/iterator.cpp Wed May 07 19:26:16 2014 -0700
@@ -70,7 +70,7 @@
}
void CodeBlobToOopClosure::do_newly_marked_nmethod(nmethod* nm) {
- nm->oops_do(_cl, /*do_strong_roots_only=*/ true);
+ nm->oops_do(_cl, /*do_strong_roots_only=*/ true, /*allow_zombie=*/ false);
}
void CodeBlobToOopClosure::do_code_blob(CodeBlob* cb) {
--- ./hotspot/src/share/vm/memory/sharedHeap.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/sharedHeap.cpp Wed May 07 19:26:16 2014 -0700
@@ -64,7 +64,8 @@
}
_sh = this; // ch is static, should be set only once.
if ((UseParNewGC ||
- (UseConcMarkSweepGC && CMSParallelRemarkEnabled) ||
+ (UseConcMarkSweepGC && (CMSParallelInitialMarkEnabled ||
+ CMSParallelRemarkEnabled)) ||
UseG1GC) &&
ParallelGCThreads > 0) {
_workers = new FlexibleWorkGang("Parallel GC Threads", ParallelGCThreads,
@@ -148,7 +149,8 @@
ScanningOption so,
OopClosure* roots,
CodeBlobClosure* code_roots,
- OopsInGenClosure* perm_blk) {
+ OopsInGenClosure* perm_blk,
+ bool manages_code_roots) {
StrongRootsScope srs(this, activate_scope);
// General strong roots.
assert(_strong_roots_parity != 0, "must have called prologue code");
@@ -216,7 +218,7 @@
CodeCache::blobs_do(code_roots);
}
} else if (so & (SO_SystemClasses|SO_AllClasses)) {
- if (!collecting_perm_gen) {
+ if (!manages_code_roots && !collecting_perm_gen) {
// If we are collecting from class statics, but we are not going to
// visit all of the CodeCache, collect from the non-perm roots if any.
// This makes the code cache function temporarily as a source of strong
--- ./hotspot/src/share/vm/memory/sharedHeap.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/sharedHeap.hpp Wed May 07 19:26:16 2014 -0700
@@ -267,7 +267,8 @@
ScanningOption so,
OopClosure* roots,
CodeBlobClosure* code_roots,
- OopsInGenClosure* perm_blk);
+ OopsInGenClosure* perm_blk,
+ bool manages_code_roots = false);
// Apply "blk" to all the weak roots of the system. These include
// JNI weak roots, the code cache, system dictionary, symbol table,
--- ./hotspot/src/share/vm/memory/universe.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/universe.cpp Wed May 07 19:26:16 2014 -0700
@@ -826,17 +826,23 @@
// 32Gb
// OopEncodingHeapMax == NarrowOopHeapMax << LogMinObjAlignmentInBytes;
-char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) {
+char* Universe::preferred_heap_base(size_t heap_size, size_t alignment, NARROW_OOP_MODE mode) {
+ assert(is_size_aligned((size_t)OopEncodingHeapMax, alignment), "Must be");
+ assert(is_size_aligned((size_t)NarrowOopHeapMax, alignment), "Must be");
+ assert(is_size_aligned(heap_size, alignment), "Must be");
+
+ uintx heap_base_min_address_aligned = align_size_up(HeapBaseMinAddress, alignment);
+
size_t base = 0;
#ifdef _LP64
if (UseCompressedOops) {
assert(mode == UnscaledNarrowOop ||
mode == ZeroBasedNarrowOop ||
mode == HeapBasedNarrowOop, "mode is invalid");
- const size_t total_size = heap_size + HeapBaseMinAddress;
+ const size_t total_size = heap_size + heap_base_min_address_aligned;
// Return specified base for the first request.
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
- base = HeapBaseMinAddress;
+ base = heap_base_min_address_aligned;
} else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) {
if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) &&
(Universe::narrow_oop_shift() == 0)) {
@@ -882,6 +888,8 @@
}
}
#endif
+
+ assert(is_ptr_aligned((char*)base, alignment), "Must be");
return (char*)base; // also return NULL (don't care) for 32-bit VM
}
@@ -1366,7 +1374,7 @@
st->print_cr("}");
}
-void Universe::verify(bool silent, VerifyOption option) {
+void Universe::verify(VerifyOption option, const char* prefix, bool silent) {
if (SharedSkipVerify) {
return;
}
@@ -1387,11 +1395,12 @@
HandleMark hm; // Handles created during verification can be zapped
_verify_count++;
+ if (!silent) gclog_or_tty->print(prefix);
if (!silent) gclog_or_tty->print("[Verifying ");
if (!silent) gclog_or_tty->print("threads ");
Threads::verify();
+ if (!silent) gclog_or_tty->print("heap ");
heap()->verify(silent, option);
-
if (!silent) gclog_or_tty->print("syms ");
SymbolTable::verify();
if (!silent) gclog_or_tty->print("strs ");
--- ./hotspot/src/share/vm/memory/universe.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/memory/universe.hpp Wed May 07 19:26:16 2014 -0700
@@ -380,7 +380,7 @@
static NARROW_OOP_MODE narrow_oop_mode();
- static char* preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode);
+ static char* preferred_heap_base(size_t heap_size, size_t alignment, NARROW_OOP_MODE mode);
// Historic gc information
static size_t get_heap_capacity_at_last_gc() { return _heap_capacity_at_last_gc; }
@@ -419,12 +419,12 @@
// Debugging
static bool verify_in_progress() { return _verify_in_progress; }
- static void verify(bool silent, VerifyOption option);
- static void verify(bool silent) {
- verify(silent, VerifyOption_Default /* option */);
+ static void verify(VerifyOption option, const char* prefix, bool silent = VerifySilently);
+ static void verify(const char* prefix, bool silent = VerifySilently) {
+ verify(VerifyOption_Default, prefix, silent);
}
- static void verify() {
- verify(false /* silent */);
+ static void verify(bool silent = VerifySilently) {
+ verify("", silent);
}
static int verify_count() { return _verify_count; }
--- ./hotspot/src/share/vm/oops/constantPoolOop.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/oops/constantPoolOop.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -1026,24 +1026,13 @@
case JVM_CONSTANT_InvokeDynamic:
{
- int k1 = invoke_dynamic_bootstrap_method_ref_index_at(index1);
- int k2 = cp2->invoke_dynamic_bootstrap_method_ref_index_at(index2);
- bool match = compare_entry_to(k1, cp2, k2, CHECK_false);
- if (!match) return false;
- k1 = invoke_dynamic_name_and_type_ref_index_at(index1);
- k2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2);
- match = compare_entry_to(k1, cp2, k2, CHECK_false);
- if (!match) return false;
- int argc = invoke_dynamic_argument_count_at(index1);
- if (argc == cp2->invoke_dynamic_argument_count_at(index2)) {
- for (int j = 0; j < argc; j++) {
- k1 = invoke_dynamic_argument_index_at(index1, j);
- k2 = cp2->invoke_dynamic_argument_index_at(index2, j);
- match = compare_entry_to(k1, cp2, k2, CHECK_false);
- if (!match) return false;
- }
- return true; // got through loop; all elements equal
- }
+ int k1 = invoke_dynamic_name_and_type_ref_index_at(index1);
+ int k2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2);
+ int i1 = invoke_dynamic_bootstrap_specifier_index(index1);
+ int i2 = cp2->invoke_dynamic_bootstrap_specifier_index(index2);
+ bool match = compare_entry_to(k1, cp2, k2, CHECK_false) &&
+ compare_operand_to(i1, cp2, i2, CHECK_false);
+ return match;
} break;
case JVM_CONSTANT_UnresolvedString:
@@ -1078,12 +1067,135 @@
} // end compare_entry_to()
+// Resize the operands array with delta_len and delta_size.
+// Used in RedefineClasses for CP merge.
+void constantPoolOopDesc::resize_operands(int delta_len, int delta_size, TRAPS) {
+ int old_len = operand_array_length(operands());
+ int new_len = old_len + delta_len;
+ int min_len = (delta_len > 0) ? old_len : new_len;
+
+ int old_size = operands()->length();
+ int new_size = old_size + delta_size;
+ int min_size = (delta_size > 0) ? old_size : new_size;
+
+ typeArrayHandle new_ops = oopFactory::new_permanent_intArray(new_size, CHECK);
+
+ // Set index in the resized array for existing elements only
+ for (int idx = 0; idx < min_len; idx++) {
+ int offset = operand_offset_at(idx); // offset in original array
+ operand_offset_at_put(new_ops(), idx, offset + 2*delta_len); // offset in resized array
+ }
+ // Copy the bootstrap specifiers only
+ Copy::conjoint_memory_atomic(operands()->short_at_addr(2*old_len),
+ new_ops->short_at_addr(2*new_len),
+ (min_size - 2*min_len) * sizeof(u2));
+ // Explicit deallocation of old operands array is not needed for 7u
+ set_operands(new_ops());
+} // end resize_operands()
+
+
+// Extend the operands array with the length and size of the ext_cp operands.
+// Used in RedefineClasses for CP merge.
+void constantPoolOopDesc::extend_operands(constantPoolHandle ext_cp, TRAPS) {
+ int delta_len = operand_array_length(ext_cp->operands());
+ if (delta_len == 0) {
+ return; // nothing to do
+ }
+ int delta_size = ext_cp->operands()->length();
+
+ assert(delta_len > 0 && delta_size > 0, "extended operands array must be bigger");
+
+ if (operand_array_length(operands()) == 0) {
+ typeArrayHandle new_ops = oopFactory::new_permanent_intArray(delta_size, CHECK);
+ // The first element index defines the offset of second part
+ operand_offset_at_put(new_ops(), 0, 2*delta_len); // offset in new array
+ set_operands(new_ops());
+ } else {
+ resize_operands(delta_len, delta_size, CHECK);
+ }
+
+} // end extend_operands()
+
+
+// Shrink the operands array to a smaller array with new_len length.
+// Used in RedefineClasses for CP merge.
+void constantPoolOopDesc::shrink_operands(int new_len, TRAPS) {
+ int old_len = operand_array_length(operands());
+ if (new_len == old_len) {
+ return; // nothing to do
+ }
+ assert(new_len < old_len, "shrunken operands array must be smaller");
+
+ int free_base = operand_next_offset_at(new_len - 1);
+ int delta_len = new_len - old_len;
+ int delta_size = 2*delta_len + free_base - operands()->length();
+
+ resize_operands(delta_len, delta_size, CHECK);
+
+} // end shrink_operands()
+
+
+void constantPoolOopDesc::copy_operands(constantPoolHandle from_cp,
+ constantPoolHandle to_cp,
+ TRAPS) {
+
+ int from_oplen = operand_array_length(from_cp->operands());
+ int old_oplen = operand_array_length(to_cp->operands());
+ if (from_oplen != 0) {
+ // append my operands to the target's operands array
+ if (old_oplen == 0) {
+ to_cp->set_operands(from_cp->operands()); // reuse; do not merge
+ } else {
+ int old_len = to_cp->operands()->length();
+ int from_len = from_cp->operands()->length();
+ int old_off = old_oplen * sizeof(u2);
+ int from_off = from_oplen * sizeof(u2);
+ typeArrayHandle new_operands = oopFactory::new_permanent_intArray(old_len + from_len, CHECK);
+ int fillp = 0, len = 0;
+ // first part of dest
+ Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(0),
+ new_operands->short_at_addr(fillp),
+ (len = old_off) * sizeof(u2));
+ fillp += len;
+ // first part of src
+ Copy::conjoint_memory_atomic(from_cp->operands()->short_at_addr(0),
+ new_operands->short_at_addr(fillp),
+ (len = from_off) * sizeof(u2));
+ fillp += len;
+ // second part of dest
+ Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(old_off),
+ new_operands->short_at_addr(fillp),
+ (len = old_len - old_off) * sizeof(u2));
+ fillp += len;
+ // second part of src
+ Copy::conjoint_memory_atomic(from_cp->operands()->short_at_addr(from_off),
+ new_operands->short_at_addr(fillp),
+ (len = from_len - from_off) * sizeof(u2));
+ fillp += len;
+ assert(fillp == new_operands->length(), "");
+
+ // Adjust indexes in the first part of the copied operands array.
+ for (int j = 0; j < from_oplen; j++) {
+ int offset = operand_offset_at(new_operands(), old_oplen + j);
+ assert(offset == operand_offset_at(from_cp->operands(), j), "correct copy");
+ offset += old_len; // every new tuple is preceded by old_len extra u2's
+ operand_offset_at_put(new_operands(), old_oplen + j, offset);
+ }
+
+ // replace target operands array with combined array
+ to_cp->set_operands(new_operands());
+ }
+ }
+} // end copy_operands()
+
+
// Copy this constant pool's entries at start_i to end_i (inclusive)
// to the constant pool to_cp's entries starting at to_i. A total of
// (end_i - start_i) + 1 entries are copied.
void constantPoolOopDesc::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i,
constantPoolHandle to_cp, int to_i, TRAPS) {
+
int dest_i = to_i; // leave original alone for debug purposes
for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
@@ -1104,56 +1216,9 @@
break;
}
}
+ copy_operands(from_cp, to_cp, CHECK);
- int from_oplen = operand_array_length(from_cp->operands());
- int old_oplen = operand_array_length(to_cp->operands());
- if (from_oplen != 0) {
- // append my operands to the target's operands array
- if (old_oplen == 0) {
- to_cp->set_operands(from_cp->operands()); // reuse; do not merge
- } else {
- int old_len = to_cp->operands()->length();
- int from_len = from_cp->operands()->length();
- int old_off = old_oplen * sizeof(u2);
- int from_off = from_oplen * sizeof(u2);
- typeArrayHandle new_operands = oopFactory::new_permanent_shortArray(old_len + from_len, CHECK);
- int fillp = 0, len = 0;
- // first part of dest
- Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(0),
- new_operands->short_at_addr(fillp),
- (len = old_off) * sizeof(u2));
- fillp += len;
- // first part of src
- Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(0),
- new_operands->short_at_addr(fillp),
- (len = from_off) * sizeof(u2));
- fillp += len;
- // second part of dest
- Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(old_off),
- new_operands->short_at_addr(fillp),
- (len = old_len - old_off) * sizeof(u2));
- fillp += len;
- // second part of src
- Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(from_off),
- new_operands->short_at_addr(fillp),
- (len = from_len - from_off) * sizeof(u2));
- fillp += len;
- assert(fillp == new_operands->length(), "");
-
- // Adjust indexes in the first part of the copied operands array.
- for (int j = 0; j < from_oplen; j++) {
- int offset = operand_offset_at(new_operands(), old_oplen + j);
- assert(offset == operand_offset_at(from_cp->operands(), j), "correct copy");
- offset += old_len; // every new tuple is preceded by old_len extra u2's
- operand_offset_at_put(new_operands(), old_oplen + j, offset);
- }
-
- // replace target operands array with combined array
- to_cp->set_operands(new_operands());
- }
- }
-
-} // end copy_cp_to()
+} // end copy_cp_to_impl()
// Copy this constant pool's entry at from_i to the constant pool
@@ -1337,6 +1402,46 @@
} // end find_matching_entry()
+// Compare this constant pool's bootstrap specifier at idx1 to the constant pool
+// cp2's bootstrap specifier at idx2.
+bool constantPoolOopDesc::compare_operand_to(int idx1, constantPoolHandle cp2, int idx2, TRAPS) {
+ int k1 = operand_bootstrap_method_ref_index_at(idx1);
+ int k2 = cp2->operand_bootstrap_method_ref_index_at(idx2);
+ bool match = compare_entry_to(k1, cp2, k2, CHECK_false);
+
+ if (!match) {
+ return false;
+ }
+ int argc = operand_argument_count_at(idx1);
+ if (argc == cp2->operand_argument_count_at(idx2)) {
+ for (int j = 0; j < argc; j++) {
+ k1 = operand_argument_index_at(idx1, j);
+ k2 = cp2->operand_argument_index_at(idx2, j);
+ match = compare_entry_to(k1, cp2, k2, CHECK_false);
+ if (!match) {
+ return false;
+ }
+ }
+ return true; // got through loop; all elements equal
+ }
+ return false;
+} // end compare_operand_to()
+
+// Search constant pool search_cp for a bootstrap specifier that matches
+// this constant pool's bootstrap specifier at pattern_i index.
+// Return the index of a matching bootstrap specifier or (-1) if there is no match.
+int constantPoolOopDesc::find_matching_operand(int pattern_i,
+ constantPoolHandle search_cp, int search_len, TRAPS) {
+ for (int i = 0; i < search_len; i++) {
+ bool found = compare_operand_to(pattern_i, search_cp, i, CHECK_(-1));
+ if (found) {
+ return i;
+ }
+ }
+ return -1; // bootstrap specifier not found; return unused index (-1)
+} // end find_matching_operand()
+
+
#ifndef PRODUCT
const char* constantPoolOopDesc::printable_name_at(int which) {
--- ./hotspot/src/share/vm/oops/constantPoolOop.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/oops/constantPoolOop.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -565,6 +565,47 @@
_indy_argc_offset = 1, // u2 argc
_indy_argv_offset = 2 // u2 argv[argc]
};
+
+ // These functions are used in RedefineClasses for CP merge
+
+ int operand_offset_at(int bootstrap_specifier_index) {
+ assert(0 <= bootstrap_specifier_index &&
+ bootstrap_specifier_index < operand_array_length(operands()),
+ "Corrupted CP operands");
+ return operand_offset_at(operands(), bootstrap_specifier_index);
+ }
+ int operand_bootstrap_method_ref_index_at(int bootstrap_specifier_index) {
+ int offset = operand_offset_at(bootstrap_specifier_index);
+ return operands()->short_at(offset + _indy_bsm_offset);
+ }
+ int operand_argument_count_at(int bootstrap_specifier_index) {
+ int offset = operand_offset_at(bootstrap_specifier_index);
+ int argc = operands()->short_at(offset + _indy_argc_offset);
+ return argc;
+ }
+ int operand_argument_index_at(int bootstrap_specifier_index, int j) {
+ int offset = operand_offset_at(bootstrap_specifier_index);
+ return operands()->short_at(offset + _indy_argv_offset + j);
+ }
+ int operand_next_offset_at(int bootstrap_specifier_index) {
+ int offset = operand_offset_at(bootstrap_specifier_index) + _indy_argv_offset
+ + operand_argument_count_at(bootstrap_specifier_index);
+ return offset;
+ }
+ // Compare a bootsrap specifier in the operands arrays
+ bool compare_operand_to(int bootstrap_specifier_index1, constantPoolHandle cp2,
+ int bootstrap_specifier_index2, TRAPS);
+ // Find a bootsrap specifier in the operands array
+ int find_matching_operand(int bootstrap_specifier_index, constantPoolHandle search_cp,
+ int operands_cur_len, TRAPS);
+ // Resize the operands array with delta_len and delta_size
+ void resize_operands(int delta_len, int delta_size, TRAPS);
+ // Extend the operands array with the length and size of the ext_cp operands
+ void extend_operands(constantPoolHandle ext_cp, TRAPS);
+ // Shrink the operands array to a smaller array with new_len length
+ void shrink_operands(int new_len, TRAPS);
+
+
int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
int op_base = invoke_dynamic_operand_base(which);
@@ -755,6 +796,7 @@
copy_cp_to_impl(h_this, start_i, end_i, to_cp, to_i, THREAD);
}
static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS);
+ static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS);
static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS);
int orig_length() const { return _orig_length; }
--- ./hotspot/src/share/vm/oops/instanceKlass.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/oops/instanceKlass.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -1901,6 +1901,17 @@
FreeHeap(jmeths);
}
+ // Deallocate MemberNameTable
+ {
+ Mutex* lock_or_null = SafepointSynchronize::is_at_safepoint() ? NULL : MemberNameTable_lock;
+ MutexLockerEx ml(lock_or_null, Mutex::_no_safepoint_check_flag);
+ MemberNameTable* mnt = member_names();
+ if (mnt != NULL) {
+ delete mnt;
+ set_member_names(NULL);
+ }
+ }
+
int* indices = methods_cached_itable_indices_acquire();
if (indices != (int*)NULL) {
release_set_methods_cached_itable_indices(NULL);
@@ -2333,6 +2344,30 @@
return NULL;
}
+void instanceKlass::add_member_name(int index, Handle mem_name) {
+ jweak mem_name_wref = JNIHandles::make_weak_global(mem_name);
+ MutexLocker ml(MemberNameTable_lock);
+ assert(0 <= index && index < idnum_allocated_count(), "index is out of bounds");
+ DEBUG_ONLY(No_Safepoint_Verifier nsv);
+
+ if (_member_names == NULL) {
+ _member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(idnum_allocated_count());
+ }
+ _member_names->add_member_name(index, mem_name_wref);
+}
+
+oop instanceKlass::get_member_name(int index) {
+ MutexLocker ml(MemberNameTable_lock);
+ assert(0 <= index && index < idnum_allocated_count(), "index is out of bounds");
+ DEBUG_ONLY(No_Safepoint_Verifier nsv);
+
+ if (_member_names == NULL) {
+ return NULL;
+ }
+ oop mem_name =_member_names->get_member_name(index);
+ return mem_name;
+}
+
// -----------------------------------------------------------------------------------------------------
#ifndef PRODUCT
--- ./hotspot/src/share/vm/oops/instanceKlass.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/oops/instanceKlass.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -94,6 +94,7 @@
class nmethodBucket;
class PreviousVersionNode;
class JvmtiCachedClassFieldMap;
+class MemberNameTable;
// This is used in iterators below.
class FieldClosure: public StackObj {
@@ -265,6 +266,7 @@
int _vtable_len; // length of Java vtable (in words)
int _itable_len; // length of Java itable (in words)
OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily)
+ MemberNameTable* _member_names; // Member names
JNIid* _jni_ids; // First JNI identifier for static fields in this class
jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none
int* _methods_cached_itable_indices; // itable_index cache for JNI invoke corresponding to methods idnum, or NULL
@@ -972,6 +974,12 @@
// jvm support
jint compute_modifier_flags(TRAPS) const;
+ // JSR-292 support
+ MemberNameTable* member_names() { return _member_names; }
+ void set_member_names(MemberNameTable* member_names) { _member_names = member_names; }
+ void add_member_name(int index, Handle member_name);
+ oop get_member_name(int index);
+
public:
// JVMTI support
jint jvmti_class_status() const;
--- ./hotspot/src/share/vm/opto/bytecodeInfo.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/bytecodeInfo.cpp Wed May 07 19:26:16 2014 -0700
@@ -103,7 +103,7 @@
// Allows targeted inlining
if(callee_method->should_inline()) {
*wci_result = *(WarmCallInfo::always_hot());
- if (PrintInlining && Verbose) {
+ if (C->print_inlining() && Verbose) {
CompileTask::print_inline_indent(inline_level());
tty->print_cr("Inlined method is hot: ");
}
@@ -117,7 +117,7 @@
if(callee_method->interpreter_throwout_count() > InlineThrowCount &&
size < InlineThrowMaxSize ) {
wci_result->set_profit(wci_result->profit() * 100);
- if (PrintInlining && Verbose) {
+ if (C->print_inlining() && Verbose) {
CompileTask::print_inline_indent(inline_level());
tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count());
}
@@ -468,7 +468,7 @@
C->log()->inline_fail(inline_msg);
}
}
- if (PrintInlining) {
+ if (C->print_inlining()) {
C->print_inlining(callee_method, inline_level(), caller_bci, inline_msg);
if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
if (Verbose && callee_method) {
@@ -517,7 +517,7 @@
#ifndef PRODUCT
if (UseOldInlining && InlineWarmCalls
- && (PrintOpto || PrintOptoInlining || PrintInlining)) {
+ && (PrintOpto || C->print_inlining())) {
bool cold = wci.is_cold();
bool hot = !cold && wci.is_hot();
bool old_cold = !success;
@@ -594,7 +594,7 @@
callee_method->is_compiled_lambda_form()) {
max_inline_level_adjust += 1; // don't count method handle calls from java.lang.invoke implem
}
- if (max_inline_level_adjust != 0 && PrintInlining && (Verbose || WizardMode)) {
+ if (max_inline_level_adjust != 0 && C->print_inlining() && (Verbose || WizardMode)) {
CompileTask::print_inline_indent(inline_level());
tty->print_cr(" \\-> discounting inline depth");
}
--- ./hotspot/src/share/vm/opto/c2_globals.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/c2_globals.hpp Wed May 07 19:26:16 2014 -0700
@@ -173,6 +173,9 @@
product_pd(intx, LoopUnrollLimit, \
"Unroll loop bodies with node count less than this") \
\
+ product(intx, LoopMaxUnroll, 16, \
+ "Maximum number of unrolls for main loop") \
+ \
product(intx, LoopUnrollMin, 4, \
"Minimum number of unroll loop bodies before checking progress" \
"of rounds of unroll,optimize,..") \
--- ./hotspot/src/share/vm/opto/callGenerator.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/callGenerator.hpp Wed May 07 19:26:16 2014 -0700
@@ -158,8 +158,9 @@
virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); }
static void print_inlining(Compile* C, ciMethod* callee, int inline_level, int bci, const char* msg) {
- if (PrintInlining)
+ if (C->print_inlining()) {
C->print_inlining(callee, inline_level, bci, msg);
+ }
}
};
--- ./hotspot/src/share/vm/opto/coalesce.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/coalesce.cpp Wed May 07 19:26:16 2014 -0700
@@ -135,20 +135,26 @@
// After cloning some rematerialized instruction, clone any MachProj's that
// follow it. Example: Intel zero is XOR, kills flags. Sparc FP constants
// use G3 as an address temp.
-int PhaseChaitin::clone_projs( Block *b, uint idx, Node *con, Node *copy, uint &maxlrg ) {
- Block *bcon = _cfg._bbs[con->_idx];
- uint cindex = bcon->find_node(con);
- Node *con_next = bcon->_nodes[cindex+1];
- if( con_next->in(0) != con || !con_next->is_MachProj() )
- return false; // No MachProj's follow
-
- // Copy kills after the cloned constant
- Node *kills = con_next->clone();
- kills->set_req( 0, copy );
- b->_nodes.insert( idx, kills );
- _cfg._bbs.map( kills->_idx, b );
- new_lrg( kills, maxlrg++ );
- return true;
+int PhaseChaitin::clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id) {
+ assert(b->find_node(copy) == (idx - 1), "incorrect insert index for copy kill projections");
+ DEBUG_ONLY( Block* borig = _cfg._bbs[orig->_idx]; )
+ int found_projs = 0;
+ uint cnt = orig->outcnt();
+ for (uint i = 0; i < cnt; i++) {
+ Node* proj = orig->raw_out(i);
+ if (proj->is_MachProj()) {
+ assert(proj->outcnt() == 0, "only kill projections are expected here");
+ assert(_cfg._bbs[proj->_idx] == borig, "incorrect block for kill projections");
+ found_projs++;
+ // Copy kill projections after the cloned node
+ Node* kills = proj->clone();
+ kills->set_req(0, copy);
+ b->_nodes.insert(idx++, kills);
+ _cfg._bbs.map(kills->_idx, b);
+ new_lrg(kills, max_lrg_id++);
+ }
+ }
+ return found_projs;
}
//------------------------------compact----------------------------------------
@@ -464,8 +470,7 @@
copy = m->clone();
// Insert the copy in the basic block, just before us
b->_nodes.insert( l++, copy );
- if( _phc.clone_projs( b, l, m, copy, _phc._maxlrg ) )
- l++;
+ l += _phc.clone_projs(b, l, m, copy, _phc._maxlrg);
} else {
const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
copy = new (C) MachSpillCopyNode( m, *rm, *rm );
--- ./hotspot/src/share/vm/opto/compile.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/compile.cpp Wed May 07 19:26:16 2014 -0700
@@ -642,7 +642,7 @@
_inlining_progress(false),
_inlining_incrementally(false),
_print_inlining_list(NULL),
- _print_inlining(0) {
+ _print_inlining_idx(0) {
C = this;
CompileWrapper cw(this);
@@ -667,6 +667,8 @@
set_print_assembly(print_opto_assembly);
set_parsed_irreducible_loop(false);
#endif
+ set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
+ set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
if (ProfileTraps) {
// Make sure the method being compiled gets its own MDO,
@@ -698,7 +700,7 @@
PhaseGVN gvn(node_arena(), estimated_size);
set_initial_gvn(&gvn);
- if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) {
+ if (print_inlining() || print_intrinsics()) {
_print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer());
}
{ // Scope for timing the parser
@@ -832,6 +834,7 @@
}
#endif
+ NOT_PRODUCT( verify_barriers(); )
// Now that we know the size of all the monitors we can add a fixed slot
// for the original deopt pc.
@@ -924,7 +927,7 @@
_inlining_progress(false),
_inlining_incrementally(false),
_print_inlining_list(NULL),
- _print_inlining(0) {
+ _print_inlining_idx(0) {
C = this;
#ifndef PRODUCT
@@ -3237,6 +3240,72 @@
}
}
}
+
+// Verify GC barriers consistency
+// Currently supported:
+// - G1 pre-barriers (see GraphKit::g1_write_barrier_pre())
+void Compile::verify_barriers() {
+ if (UseG1GC) {
+ // Verify G1 pre-barriers
+ const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active());
+
+ ResourceArea *area = Thread::current()->resource_area();
+ Unique_Node_List visited(area);
+ Node_List worklist(area);
+ // We're going to walk control flow backwards starting from the Root
+ worklist.push(_root);
+ while (worklist.size() > 0) {
+ Node* x = worklist.pop();
+ if (x == NULL || x == top()) continue;
+ if (visited.member(x)) {
+ continue;
+ } else {
+ visited.push(x);
+ }
+
+ if (x->is_Region()) {
+ for (uint i = 1; i < x->req(); i++) {
+ worklist.push(x->in(i));
+ }
+ } else {
+ worklist.push(x->in(0));
+ // We are looking for the pattern:
+ // /->ThreadLocal
+ // If->Bool->CmpI->LoadB->AddP->ConL(marking_offset)
+ // \->ConI(0)
+ // We want to verify that the If and the LoadB have the same control
+ // See GraphKit::g1_write_barrier_pre()
+ if (x->is_If()) {
+ IfNode *iff = x->as_If();
+ if (iff->in(1)->is_Bool() && iff->in(1)->in(1)->is_Cmp()) {
+ CmpNode *cmp = iff->in(1)->in(1)->as_Cmp();
+ if (cmp->Opcode() == Op_CmpI && cmp->in(2)->is_Con() && cmp->in(2)->bottom_type()->is_int()->get_con() == 0
+ && cmp->in(1)->is_Load()) {
+ LoadNode* load = cmp->in(1)->as_Load();
+ if (load->Opcode() == Op_LoadB && load->in(2)->is_AddP() && load->in(2)->in(2)->Opcode() == Op_ThreadLocal
+ && load->in(2)->in(3)->is_Con()
+ && load->in(2)->in(3)->bottom_type()->is_intptr_t()->get_con() == marking_offset) {
+
+ Node* if_ctrl = iff->in(0);
+ Node* load_ctrl = load->in(0);
+
+ if (if_ctrl != load_ctrl) {
+ // Skip possible CProj->NeverBranch in infinite loops
+ if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj)
+ && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) {
+ if_ctrl = if_ctrl->in(0)->in(0);
+ }
+ }
+ assert(load_ctrl != NULL && if_ctrl == load_ctrl, "controls must match");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
#endif
// The Compile object keeps track of failure reasons separately from the ciEnv.
@@ -3510,7 +3579,7 @@
}
void Compile::dump_inlining() {
- if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) {
+ if (print_inlining() || print_intrinsics()) {
// Print inlining message for candidates that we couldn't inline
// for lack of space or non constant receiver
for (int i = 0; i < _late_inlines.length(); i++) {
@@ -3534,7 +3603,7 @@
}
}
for (int i = 0; i < _print_inlining_list->length(); i++) {
- tty->print(_print_inlining_list->at(i).ss()->as_string());
+ tty->print(_print_inlining_list->adr_at(i)->ss()->as_string());
}
}
}
--- ./hotspot/src/share/vm/opto/compile.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/compile.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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,6 +42,7 @@
#include "runtime/deoptimization.hpp"
#include "runtime/vmThread.hpp"
#include "trace/tracing.hpp"
+#include "utilities/ticks.hpp"
class Block;
class Bundle;
@@ -284,6 +285,8 @@
bool _do_method_data_update; // True if we generate code to update methodDataOops
int _AliasLevel; // Locally-adjusted version of AliasLevel flag.
bool _print_assembly; // True if we should dump assembly code for this compilation
+ bool _print_inlining; // True if we should print inlining for this compilation
+ bool _print_intrinsics; // True if we should print intrinsics for this compilation
#ifndef PRODUCT
bool _trace_opto_output;
bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing
@@ -384,7 +387,7 @@
};
GrowableArray* _print_inlining_list;
- int _print_inlining;
+ int _print_inlining_idx;
// Only keep nodes in the expensive node list that need to be optimized
void cleanup_expensive_nodes(PhaseIterGVN &igvn);
@@ -396,24 +399,24 @@
public:
outputStream* print_inlining_stream() const {
- return _print_inlining_list->at(_print_inlining).ss();
+ return _print_inlining_list->adr_at(_print_inlining_idx)->ss();
}
void print_inlining_skip(CallGenerator* cg) {
- if (PrintInlining) {
- _print_inlining_list->at(_print_inlining).set_cg(cg);
- _print_inlining++;
- _print_inlining_list->insert_before(_print_inlining, PrintInliningBuffer());
+ if (_print_inlining) {
+ _print_inlining_list->adr_at(_print_inlining_idx)->set_cg(cg);
+ _print_inlining_idx++;
+ _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer());
}
}
void print_inlining_insert(CallGenerator* cg) {
- if (PrintInlining) {
+ if (_print_inlining) {
for (int i = 0; i < _print_inlining_list->length(); i++) {
- if (_print_inlining_list->at(i).cg() == cg) {
+ if (_print_inlining_list->adr_at(i)->cg() == cg) {
_print_inlining_list->insert_before(i+1, PrintInliningBuffer());
- _print_inlining = i+1;
- _print_inlining_list->at(i).set_cg(NULL);
+ _print_inlining_idx = i+1;
+ _print_inlining_list->adr_at(i)->set_cg(NULL);
return;
}
}
@@ -536,6 +539,10 @@
int AliasLevel() const { return _AliasLevel; }
bool print_assembly() const { return _print_assembly; }
void set_print_assembly(bool z) { _print_assembly = z; }
+ bool print_inlining() const { return _print_inlining; }
+ void set_print_inlining(bool z) { _print_inlining = z; }
+ bool print_intrinsics() const { return _print_intrinsics; }
+ void set_print_intrinsics(bool z) { _print_intrinsics = z; }
// check the CompilerOracle for special behaviours for this compile
bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option);
@@ -550,20 +557,19 @@
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
- jlong _latest_stage_start_counter;
+ Ticks _latest_stage_start_counter;
void begin_method() {
#ifndef PRODUCT
if (_printer) _printer->begin_method(this);
#endif
- C->_latest_stage_start_counter = os::elapsed_counter();
+ C->_latest_stage_start_counter.stamp();
}
void print_method(CompilerPhaseType cpt, int level = 1) {
- EventCompilerPhase event(UNTIMED);
+ EventCompilerPhase event;
if (event.should_commit()) {
event.set_starttime(C->_latest_stage_start_counter);
- event.set_endtime(os::elapsed_counter());
event.set_phase((u1) cpt);
event.set_compileID(C->_compile_id);
event.set_phaseLevel(level);
@@ -574,14 +580,13 @@
#ifndef PRODUCT
if (_printer) _printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level);
#endif
- C->_latest_stage_start_counter = os::elapsed_counter();
+ C->_latest_stage_start_counter.stamp();
}
void end_method(int level = 1) {
- EventCompilerPhase event(UNTIMED);
+ EventCompilerPhase event;
if (event.should_commit()) {
event.set_starttime(C->_latest_stage_start_counter);
- event.set_endtime(os::elapsed_counter());
event.set_phase((u1) PHASE_END);
event.set_compileID(C->_compile_id);
event.set_phaseLevel(level);
@@ -1091,6 +1096,9 @@
// Print bytecodes, including the scope inlining tree
void print_codes();
+ // Verify GC barrier patterns
+ void verify_barriers() PRODUCT_RETURN;
+
// End-of-run dumps.
static void print_statistics() PRODUCT_RETURN;
--- ./hotspot/src/share/vm/opto/doCall.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/doCall.cpp Wed May 07 19:26:16 2014 -0700
@@ -42,9 +42,9 @@
#include "runtime/sharedRuntime.hpp"
void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) {
- if (TraceTypeProfile || PrintInlining NOT_PRODUCT(|| PrintOptoInlining)) {
+ if (TraceTypeProfile || C->print_inlining()) {
outputStream* out = tty;
- if (!PrintInlining) {
+ if (!C->print_inlining()) {
if (NOT_PRODUCT(!PrintOpto &&) !PrintCompilation) {
method->print_short_name();
tty->cr();
--- ./hotspot/src/share/vm/opto/graphKit.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/graphKit.cpp Wed May 07 19:26:16 2014 -0700
@@ -3596,7 +3596,7 @@
Node* marking = __ load(__ ctrl(), marking_adr, TypeInt::INT, active_type, Compile::AliasIdxRaw);
// if (!marking)
- __ if_then(marking, BoolTest::ne, zero); {
+ __ if_then(marking, BoolTest::ne, zero, unlikely); {
BasicType index_bt = TypeX_X->basic_type();
assert(sizeof(size_t) == type2aelembytes(index_bt), "Loading G1 PtrQueue::_index with wrong size.");
Node* index = __ load(__ ctrl(), index_adr, TypeX_X, index_bt, Compile::AliasIdxRaw);
@@ -3604,7 +3604,7 @@
if (do_load) {
// load original value
// alias_idx correct??
- pre_val = __ load(no_ctrl, adr, val_type, bt, alias_idx);
+ pre_val = __ load(__ ctrl(), adr, val_type, bt, alias_idx);
}
// if (pre_val != NULL)
@@ -3701,7 +3701,8 @@
Node* no_base = __ top();
float likely = PROB_LIKELY(0.999);
float unlikely = PROB_UNLIKELY(0.999);
- Node* zero = __ ConI(0);
+ Node* young_card = __ ConI((jint)G1SATBCardTableModRefBS::g1_young_card_val());
+ Node* dirty_card = __ ConI((jint)CardTableModRefBS::dirty_card_val());
Node* zeroX = __ ConX(0);
// Get the alias_index for raw card-mark memory
@@ -3757,8 +3758,16 @@
// load the original value of the card
Node* card_val = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
- __ if_then(card_val, BoolTest::ne, zero); {
- g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
+ __ if_then(card_val, BoolTest::ne, young_card); {
+ sync_kit(ideal);
+ // Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier.
+ insert_mem_bar(Op_MemBarVolatile, oop_store);
+ __ sync_kit(this);
+
+ Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
+ __ if_then(card_val_reload, BoolTest::ne, dirty_card); {
+ g1_mark_card(ideal, card_adr, oop_store, alias_idx, index, index_adr, buffer, tf);
+ } __ end_if();
} __ end_if();
} __ end_if();
} __ end_if();
--- ./hotspot/src/share/vm/opto/library_call.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/library_call.cpp Wed May 07 19:26:16 2014 -0700
@@ -525,7 +525,7 @@
Compile* C = kit.C;
int nodes = C->unique();
#ifndef PRODUCT
- if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
char buf[1000];
const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
tty->print_cr("Intrinsic %s", str);
@@ -536,7 +536,7 @@
// Try to inline the intrinsic.
if (kit.try_to_inline()) {
- if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
+ if (C->print_intrinsics() || C->print_inlining()) {
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
}
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
@@ -552,7 +552,7 @@
}
// The intrinsic bailed out
- if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
+ if (C->print_intrinsics() || C->print_inlining()) {
if (jvms->has_method()) {
// Not a root compile.
const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
@@ -574,7 +574,7 @@
int nodes = C->unique();
#ifndef PRODUCT
assert(is_predicted(), "sanity");
- if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
char buf[1000];
const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
tty->print_cr("Predicate for intrinsic %s", str);
@@ -585,7 +585,7 @@
Node* slow_ctl = kit.try_to_predicate();
if (!kit.failing()) {
- if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
+ if (C->print_intrinsics() || C->print_inlining()) {
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
}
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
@@ -599,7 +599,7 @@
}
// The intrinsic bailed out
- if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
+ if (C->print_intrinsics() || C->print_inlining()) {
if (jvms->has_method()) {
// Not a root compile.
const char* msg = "failed to generate predicate for intrinsic";
@@ -2262,7 +2262,7 @@
const TypeOopPtr* tjp = TypeOopPtr::make_from_klass(sharpened_klass);
#ifndef PRODUCT
- if (PrintIntrinsics || PrintInlining || PrintOptoInlining) {
+ if (C->print_intrinsics() || C->print_inlining()) {
tty->print(" from base type: "); adr_type->dump();
tty->print(" sharpened value: "); tjp->dump();
}
@@ -3158,7 +3158,7 @@
if (mirror_con == NULL) return false; // cannot happen?
#ifndef PRODUCT
- if (PrintIntrinsics || PrintInlining || PrintOptoInlining) {
+ if (C->print_intrinsics() || C->print_inlining()) {
ciType* k = mirror_con->java_mirror_type();
if (k) {
tty->print("Inlining %s on constant Class ", vmIntrinsics::name_at(intrinsic_id()));
@@ -3846,7 +3846,7 @@
// Method.invoke() and auxiliary frames.
bool LibraryCallKit::inline_native_Reflection_getCallerClass() {
#ifndef PRODUCT
- if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
tty->print_cr("Attempting to inline sun.reflect.Reflection.getCallerClass");
}
#endif
@@ -3858,7 +3858,7 @@
const TypeInt* caller_depth_type = _gvn.type(caller_depth_node)->isa_int();
if (caller_depth_type == NULL || !caller_depth_type->is_con()) {
#ifndef PRODUCT
- if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
tty->print_cr(" Bailing out because caller depth was not a constant");
}
#endif
@@ -3873,7 +3873,7 @@
int caller_depth = caller_depth_type->get_con() - 1;
if (caller_depth < 0) {
#ifndef PRODUCT
- if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
tty->print_cr(" Bailing out because caller depth was %d", caller_depth);
}
#endif
@@ -3882,7 +3882,7 @@
if (!jvms()->has_method()) {
#ifndef PRODUCT
- if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
tty->print_cr(" Bailing out because intrinsic was inlined at top level");
}
#endif
@@ -3919,7 +3919,7 @@
if (inlining_depth == 0) {
#ifndef PRODUCT
- if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
tty->print_cr(" Bailing out because caller depth (%d) exceeded inlining depth (%d)", caller_depth_type->get_con(), _depth);
tty->print_cr(" JVM state at this point:");
for (int i = _depth; i >= 1; i--) {
@@ -3939,7 +3939,7 @@
set_result(makecon(TypeInstPtr::make(caller_mirror)));
#ifndef PRODUCT
- if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) {
+ if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
tty->print_cr(" Succeeded: caller = %s.%s, caller depth = %d, depth = %d", caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), caller_depth_type->get_con(), _depth);
tty->print_cr(" JVM state at this point:");
for (int i = _depth; i >= 1; i--) {
--- ./hotspot/src/share/vm/opto/loopTransform.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/loopTransform.cpp Wed May 07 19:26:16 2014 -0700
@@ -623,8 +623,6 @@
}
-#define MAX_UNROLL 16 // maximum number of unrolls for main loop
-
//------------------------------policy_unroll----------------------------------
// Return TRUE or FALSE if the loop should be unrolled or not. Unroll if
// the loop is a CountedLoop and the body is small enough.
@@ -641,7 +639,7 @@
if (cl->trip_count() <= (uint)(cl->is_normal_loop() ? 2 : 1)) return false;
int future_unroll_ct = cl->unrolled_count() * 2;
- if (future_unroll_ct > MAX_UNROLL) return false;
+ if (future_unroll_ct > LoopMaxUnroll) return false;
// Check for initial stride being a small enough constant
if (abs(cl->stride_con()) > (1<<2)*future_unroll_ct) return false;
@@ -1956,7 +1954,7 @@
// Find loads off the surviving projection; remove their control edge
for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
Node* cd = dp->fast_out(i); // Control-dependent node
- if( cd->is_Load() ) { // Loads can now float around in the loop
+ if (cd->is_Load() && cd->depends_only_on_test()) { // Loads can now float around in the loop
// Allow the load to float around in the loop, or before it
// but NOT before the pre-loop.
_igvn.replace_input_of(cd, 0, ctrl); // ctrl, not NULL
--- ./hotspot/src/share/vm/opto/memnode.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/memnode.cpp Wed May 07 19:26:16 2014 -0700
@@ -1957,6 +1957,11 @@
if (t != NULL) {
// constant oop => constant klass
if (offset == java_lang_Class::array_klass_offset_in_bytes()) {
+ if (t->is_void()) {
+ // We cannot create a void array. Since void is a primitive type return null
+ // klass. Users of this result need to do a null check on the returned klass.
+ return TypePtr::NULL_PTR;
+ }
return TypeKlassPtr::make(ciArrayKlass::make(t));
}
if (!t->is_klass()) {
--- ./hotspot/src/share/vm/opto/memnode.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/memnode.hpp Wed May 07 19:26:16 2014 -0700
@@ -204,6 +204,17 @@
protected:
const Type* load_array_final_field(const TypeKlassPtr *tkls,
ciKlass* klass) const;
+ // depends_only_on_test is almost always true, and needs to be almost always
+ // true to enable key hoisting & commoning optimizations. However, for the
+ // special case of RawPtr loads from TLS top & end, and other loads performed by
+ // GC barriers, the control edge carries the dependence preventing hoisting past
+ // a Safepoint instead of the memory edge. (An unfortunate consequence of having
+ // Safepoints not set Raw Memory; itself an unfortunate consequence of having Nodes
+ // which produce results (new raw memory state) inside of loops preventing all
+ // manner of other optimizations). Basically, it's ugly but so is the alternative.
+ // See comment in macro.cpp, around line 125 expand_allocate_common().
+ virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; }
+
};
//------------------------------LoadBNode--------------------------------------
@@ -370,16 +381,6 @@
virtual uint ideal_reg() const { return Op_RegP; }
virtual int store_Opcode() const { return Op_StoreP; }
virtual BasicType memory_type() const { return T_ADDRESS; }
- // depends_only_on_test is almost always true, and needs to be almost always
- // true to enable key hoisting & commoning optimizations. However, for the
- // special case of RawPtr loads from TLS top & end, the control edge carries
- // the dependence preventing hoisting past a Safepoint instead of the memory
- // edge. (An unfortunate consequence of having Safepoints not set Raw
- // Memory; itself an unfortunate consequence of having Nodes which produce
- // results (new raw memory state) inside of loops preventing all manner of
- // other optimizations). Basically, it's ugly but so is the alternative.
- // See comment in macro.cpp, around line 125 expand_allocate_common().
- virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; }
};
@@ -393,16 +394,6 @@
virtual uint ideal_reg() const { return Op_RegN; }
virtual int store_Opcode() const { return Op_StoreN; }
virtual BasicType memory_type() const { return T_NARROWOOP; }
- // depends_only_on_test is almost always true, and needs to be almost always
- // true to enable key hoisting & commoning optimizations. However, for the
- // special case of RawPtr loads from TLS top & end, the control edge carries
- // the dependence preventing hoisting past a Safepoint instead of the memory
- // edge. (An unfortunate consequence of having Safepoints not set Raw
- // Memory; itself an unfortunate consequence of having Nodes which produce
- // results (new raw memory state) inside of loops preventing all manner of
- // other optimizations). Basically, it's ugly but so is the alternative.
- // See comment in macro.cpp, around line 125 expand_allocate_common().
- virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; }
};
//------------------------------LoadKlassNode----------------------------------
--- ./hotspot/src/share/vm/opto/reg_split.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/opto/reg_split.cpp Wed May 07 19:26:16 2014 -0700
@@ -391,10 +391,15 @@
#endif
// See if the cloned def kills any flags, and copy those kills as well
uint i = insidx+1;
- if( clone_projs( b, i, def, spill, maxlrg ) ) {
+ int found_projs = clone_projs(b, i, def, spill, maxlrg);
+ if (found_projs > 0) {
// Adjust the point where we go hi-pressure
- if( i <= b->_ihrp_index ) b->_ihrp_index++;
- if( i <= b->_fhrp_index ) b->_fhrp_index++;
+ if (i <= b->_ihrp_index) {
+ b->_ihrp_index += found_projs;
+ }
+ if (i <= b->_fhrp_index) {
+ b->_fhrp_index += found_projs;
+ }
}
return spill;
--- ./hotspot/src/share/vm/prims/jni.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/prims/jni.cpp Wed May 07 19:26:16 2014 -0700
@@ -5042,14 +5042,22 @@
tty->print_cr("Running test: " #unit_test_function_call); \
unit_test_function_call
+// Forward declaration
+void TestReservedSpace_test();
+void TestReserveMemorySpecial_test();
+void TestOldFreeSpaceCalculation_test();
+
void execute_internal_vm_tests() {
if (ExecuteInternalVMTests) {
tty->print_cr("Running internal VM tests");
+ run_unit_test(TestReservedSpace_test());
+ run_unit_test(TestReserveMemorySpecial_test());
run_unit_test(GCTimerAllTest::all());
run_unit_test(arrayOopDesc::test_max_array_length());
run_unit_test(CollectedHeap::test_is_in());
run_unit_test(QuickSort::test_quick_sort());
run_unit_test(AltHashing::test_alt_hash());
+ run_unit_test(TestOldFreeSpaceCalculation_test());
tty->print_cr("All internal VM tests passed");
}
}
--- ./hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Wed May 07 19:26:16 2014 -0700
@@ -204,7 +204,7 @@
write_attribute_name_index("Code");
write_u4(size);
- write_u2(method->max_stack());
+ write_u2(method->verifier_max_stack());
write_u2(method->max_locals());
write_u4(code_size);
copy_bytecodes(method, (unsigned char*)writeable_address(code_size));
--- ./hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -35,6 +35,7 @@
#include "prims/jvmtiImpl.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "prims/methodComparator.hpp"
+#include "prims/methodHandles.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/relocator.hpp"
#include "utilities/bitMap.inline.hpp"
@@ -262,76 +263,23 @@
case JVM_CONSTANT_NameAndType:
{
int name_ref_i = scratch_cp->name_ref_index_at(scratch_i);
- int new_name_ref_i = 0;
- bool match = (name_ref_i < *merge_cp_length_p) &&
- scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i,
- THREAD);
- if (!match) {
- // forward reference in *merge_cp_p or not a direct match
-
- int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p,
- THREAD);
- if (found_i != 0) {
- guarantee(found_i != name_ref_i,
- "compare_entry_to() and find_matching_entry() do not agree");
-
- // Found a matching entry somewhere else in *merge_cp_p so
- // just need a mapping entry.
- new_name_ref_i = found_i;
- map_index(scratch_cp, name_ref_i, found_i);
- } else {
- // no match found so we have to append this entry to *merge_cp_p
- append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p,
- THREAD);
- // The above call to append_entry() can only append one entry
- // so the post call query of *merge_cp_length_p is only for
- // the sake of consistency.
- new_name_ref_i = *merge_cp_length_p - 1;
- }
- }
+ int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i);
- int new_signature_ref_i = 0;
- match = (signature_ref_i < *merge_cp_length_p) &&
- scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p,
- signature_ref_i, THREAD);
- if (!match) {
- // forward reference in *merge_cp_p or not a direct match
-
- int found_i = scratch_cp->find_matching_entry(signature_ref_i,
- *merge_cp_p, THREAD);
- if (found_i != 0) {
- guarantee(found_i != signature_ref_i,
- "compare_entry_to() and find_matching_entry() do not agree");
-
- // Found a matching entry somewhere else in *merge_cp_p so
- // just need a mapping entry.
- new_signature_ref_i = found_i;
- map_index(scratch_cp, signature_ref_i, found_i);
- } else {
- // no match found so we have to append this entry to *merge_cp_p
- append_entry(scratch_cp, signature_ref_i, merge_cp_p,
- merge_cp_length_p, THREAD);
- // The above call to append_entry() can only append one entry
- // so the post call query of *merge_cp_length_p is only for
- // the sake of consistency.
- new_signature_ref_i = *merge_cp_length_p - 1;
- }
- }
+ int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i,
+ merge_cp_p, merge_cp_length_p,
+ THREAD);
// If the referenced entries already exist in *merge_cp_p, then
// both new_name_ref_i and new_signature_ref_i will both be 0.
// In that case, all we are appending is the current entry.
- if (new_name_ref_i == 0) {
- new_name_ref_i = name_ref_i;
- } else {
+ if (new_name_ref_i != name_ref_i) {
RC_TRACE(0x00080000,
("NameAndType entry@%d name_ref_index change: %d to %d",
*merge_cp_length_p, name_ref_i, new_name_ref_i));
}
- if (new_signature_ref_i == 0) {
- new_signature_ref_i = signature_ref_i;
- } else {
+ if (new_signature_ref_i != signature_ref_i) {
RC_TRACE(0x00080000,
("NameAndType entry@%d signature_ref_index change: %d to %d",
*merge_cp_length_p, signature_ref_i, new_signature_ref_i));
@@ -353,76 +301,11 @@
case JVM_CONSTANT_Methodref:
{
int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i);
- int new_klass_ref_i = 0;
- bool match = (klass_ref_i < *merge_cp_length_p) &&
- scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i,
- THREAD);
- if (!match) {
- // forward reference in *merge_cp_p or not a direct match
-
- int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p,
- THREAD);
- if (found_i != 0) {
- guarantee(found_i != klass_ref_i,
- "compare_entry_to() and find_matching_entry() do not agree");
-
- // Found a matching entry somewhere else in *merge_cp_p so
- // just need a mapping entry.
- new_klass_ref_i = found_i;
- map_index(scratch_cp, klass_ref_i, found_i);
- } else {
- // no match found so we have to append this entry to *merge_cp_p
- append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p,
- THREAD);
- // The above call to append_entry() can only append one entry
- // so the post call query of *merge_cp_length_p is only for
- // the sake of consistency. Without the optimization where we
- // use JVM_CONSTANT_UnresolvedClass, then up to two entries
- // could be appended.
- new_klass_ref_i = *merge_cp_length_p - 1;
- }
- }
-
- int name_and_type_ref_i =
- scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
- int new_name_and_type_ref_i = 0;
- match = (name_and_type_ref_i < *merge_cp_length_p) &&
- scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p,
- name_and_type_ref_i, THREAD);
- if (!match) {
- // forward reference in *merge_cp_p or not a direct match
-
- int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i,
- *merge_cp_p, THREAD);
- if (found_i != 0) {
- guarantee(found_i != name_and_type_ref_i,
- "compare_entry_to() and find_matching_entry() do not agree");
-
- // Found a matching entry somewhere else in *merge_cp_p so
- // just need a mapping entry.
- new_name_and_type_ref_i = found_i;
- map_index(scratch_cp, name_and_type_ref_i, found_i);
- } else {
- // no match found so we have to append this entry to *merge_cp_p
- append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p,
- merge_cp_length_p, THREAD);
- // The above call to append_entry() can append more than
- // one entry so the post call query of *merge_cp_length_p
- // is required in order to get the right index for the
- // JVM_CONSTANT_NameAndType entry.
- new_name_and_type_ref_i = *merge_cp_length_p - 1;
- }
- }
-
- // If the referenced entries already exist in *merge_cp_p, then
- // both new_klass_ref_i and new_name_and_type_ref_i will both be
- // 0. In that case, all we are appending is the current entry.
- if (new_klass_ref_i == 0) {
- new_klass_ref_i = klass_ref_i;
- }
- if (new_name_and_type_ref_i == 0) {
- new_name_and_type_ref_i = name_and_type_ref_i;
- }
+ int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i,
+ merge_cp_p, merge_cp_length_p, THREAD);
+ int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
+ int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i,
+ merge_cp_p, merge_cp_length_p, THREAD);
const char *entry_name;
switch (scratch_cp->tag_at(scratch_i).value()) {
@@ -465,7 +348,79 @@
(*merge_cp_length_p)++;
} break;
- // At this stage, Class or UnresolvedClass could be here, but not
+ // this is an indirect CP entry so it needs special handling
+ case JVM_CONSTANT_MethodType:
+ {
+ int ref_i = scratch_cp->method_type_index_at(scratch_i);
+ int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
+ if (new_ref_i != ref_i) {
+ RC_TRACE(0x00080000,
+ ("MethodType entry@%d ref_index change: %d to %d",
+ *merge_cp_length_p, ref_i, new_ref_i));
+ }
+ (*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i);
+ if (scratch_i != *merge_cp_length_p) {
+ // The new entry in *merge_cp_p is at a different index than
+ // the new entry in scratch_cp so we need to map the index values.
+ map_index(scratch_cp, scratch_i, *merge_cp_length_p);
+ }
+ (*merge_cp_length_p)++;
+ } break;
+
+ // this is an indirect CP entry so it needs special handling
+ case JVM_CONSTANT_MethodHandle:
+ {
+ int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i);
+ int ref_i = scratch_cp->method_handle_index_at(scratch_i);
+ int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
+ if (new_ref_i != ref_i) {
+ RC_TRACE(0x00080000,
+ ("MethodHandle entry@%d ref_index change: %d to %d",
+ *merge_cp_length_p, ref_i, new_ref_i));
+ }
+ (*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i);
+ if (scratch_i != *merge_cp_length_p) {
+ // The new entry in *merge_cp_p is at a different index than
+ // the new entry in scratch_cp so we need to map the index values.
+ map_index(scratch_cp, scratch_i, *merge_cp_length_p);
+ }
+ (*merge_cp_length_p)++;
+ } break;
+
+ // this is an indirect CP entry so it needs special handling
+ case JVM_CONSTANT_InvokeDynamic:
+ {
+ // Index of the bootstrap specifier in the operands array
+ int old_bs_i = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i);
+ int new_bs_i = find_or_append_operand(scratch_cp, old_bs_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
+ // The bootstrap method NameAndType_info index
+ int old_ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i);
+ int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
+ if (new_bs_i != old_bs_i) {
+ RC_TRACE(0x00080000,
+ ("InvokeDynamic entry@%d bootstrap_method_attr_index change: %d to %d",
+ *merge_cp_length_p, old_bs_i, new_bs_i));
+ }
+ if (new_ref_i != old_ref_i) {
+ RC_TRACE(0x00080000,
+ ("InvokeDynamic entry@%d name_and_type_index change: %d to %d",
+ *merge_cp_length_p, old_ref_i, new_ref_i));
+ }
+
+ (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i);
+ if (scratch_i != *merge_cp_length_p) {
+ // The new entry in *merge_cp_p is at a different index than
+ // the new entry in scratch_cp so we need to map the index values.
+ map_index(scratch_cp, scratch_i, *merge_cp_length_p);
+ }
+ (*merge_cp_length_p)++;
+ } break;
+
+ // At this stage, Class or UnresolvedClass could be here, but not
// ClassIndex
case JVM_CONSTANT_ClassIndex: // fall through
@@ -492,6 +447,134 @@
} // end append_entry()
+int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp,
+ int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
+
+ int new_ref_i = ref_i;
+ bool match = (ref_i < *merge_cp_length_p) &&
+ scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD);
+
+ if (!match) {
+ // forward reference in *merge_cp_p or not a direct match
+ int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD);
+ if (found_i != 0) {
+ guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree");
+ // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry.
+ new_ref_i = found_i;
+ map_index(scratch_cp, ref_i, found_i);
+ } else {
+ // no match found so we have to append this entry to *merge_cp_p
+ append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD);
+ // The above call to append_entry() can only append one entry
+ // so the post call query of *merge_cp_length_p is only for
+ // the sake of consistency.
+ new_ref_i = *merge_cp_length_p - 1;
+ }
+ }
+
+ return new_ref_i;
+} // end find_or_append_indirect_entry()
+
+
+// Append a bootstrap specifier into the merge_cp operands that is semantically equal
+// to the scratch_cp operands bootstrap specifier passed by the old_bs_i index.
+// Recursively append new merge_cp entries referenced by the new bootstrap specifier.
+void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_bs_i,
+ constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
+
+ int old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i);
+ int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
+ if (new_ref_i != old_ref_i) {
+ RC_TRACE(0x00080000,
+ ("operands entry@%d bootstrap method ref_index change: %d to %d",
+ _operands_cur_length, old_ref_i, new_ref_i));
+ }
+
+ typeArrayOop merge_ops = (*merge_cp_p)->operands();
+ int new_bs_i = _operands_cur_length;
+ // We have _operands_cur_length == 0 when the merge_cp operands is empty yet.
+ // However, the operand_offset_at(0) was set in the extend_operands() call.
+ int new_base = (new_bs_i == 0) ? (*merge_cp_p)->operand_offset_at(0)
+ : (*merge_cp_p)->operand_next_offset_at(new_bs_i - 1);
+ int argc = scratch_cp->operand_argument_count_at(old_bs_i);
+
+ constantPoolOopDesc::operand_offset_at_put(merge_ops, _operands_cur_length, new_base);
+ merge_ops->short_at_put(new_base++, new_ref_i);
+ merge_ops->short_at_put(new_base++, argc);
+
+ for (int i = 0; i < argc; i++) {
+ int old_arg_ref_i = scratch_cp->operand_argument_index_at(old_bs_i, i);
+ int new_arg_ref_i = find_or_append_indirect_entry(scratch_cp, old_arg_ref_i, merge_cp_p,
+ merge_cp_length_p, THREAD);
+ merge_ops->short_at_put(new_base++, new_arg_ref_i);
+ if (new_arg_ref_i != old_arg_ref_i) {
+ RC_TRACE(0x00080000,
+ ("operands entry@%d bootstrap method argument ref_index change: %d to %d",
+ _operands_cur_length, old_arg_ref_i, new_arg_ref_i));
+ }
+ }
+ if (old_bs_i != _operands_cur_length) {
+ // The bootstrap specifier in *merge_cp_p is at a different index than
+ // that in scratch_cp so we need to map the index values.
+ map_operand_index(old_bs_i, new_bs_i);
+ }
+ _operands_cur_length++;
+} // end append_operand()
+
+
+int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp,
+ int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
+
+ int new_bs_i = old_bs_i; // bootstrap specifier index
+ bool match = (old_bs_i < _operands_cur_length) &&
+ scratch_cp->compare_operand_to(old_bs_i, *merge_cp_p, old_bs_i, THREAD);
+
+ if (!match) {
+ // forward reference in *merge_cp_p or not a direct match
+ int found_i = scratch_cp->find_matching_operand(old_bs_i, *merge_cp_p,
+ _operands_cur_length, THREAD);
+ if (found_i != -1) {
+ guarantee(found_i != old_bs_i, "compare_operand_to() and find_matching_operand() disagree");
+ // found a matching operand somewhere else in *merge_cp_p so just need a mapping
+ new_bs_i = found_i;
+ map_operand_index(old_bs_i, found_i);
+ } else {
+ // no match found so we have to append this bootstrap specifier to *merge_cp_p
+ append_operand(scratch_cp, old_bs_i, merge_cp_p, merge_cp_length_p, THREAD);
+ new_bs_i = _operands_cur_length - 1;
+ }
+ }
+ return new_bs_i;
+} // end find_or_append_operand()
+
+
+void VM_RedefineClasses::finalize_operands_merge(constantPoolHandle merge_cp, TRAPS) {
+ if (merge_cp->operands() == NULL) {
+ return;
+ }
+ // Shrink the merge_cp operands
+ merge_cp->shrink_operands(_operands_cur_length, CHECK);
+
+ if (RC_TRACE_ENABLED(0x00040000)) {
+ // don't want to loop unless we are tracing
+ int count = 0;
+ for (int i = 1; i < _operands_index_map_p->length(); i++) {
+ int value = _operands_index_map_p->at(i);
+ if (value != -1) {
+ RC_TRACE_WITH_THREAD(0x00040000, THREAD,
+ ("operands_index_map[%d]: old=%d new=%d", count, i, value));
+ count++;
+ }
+ }
+ }
+ // Clean-up
+ _operands_index_map_p = NULL;
+ _operands_cur_length = 0;
+ _operands_index_map_count = 0;
+} // end finalize_operands_merge()
+
+
void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class) {
typeArrayOop save;
@@ -777,6 +860,27 @@
} // end find_new_index()
+// Find new bootstrap specifier index value for old bootstrap specifier index
+// value by seaching the index map. Returns zero (-1) if there is no mapped
+// value for the old bootstrap specifier index.
+int VM_RedefineClasses::find_new_operand_index(int old_index) {
+ if (_operands_index_map_count == 0) {
+ // map is empty so nothing can be found
+ return -1;
+ }
+
+ if (old_index == -1 || old_index >= _operands_index_map_p->length()) {
+ // The old_index is out of range so it is not mapped.
+ // This should not happen in regular constant pool merging use.
+ return -1;
+ }
+
+ int value = _operands_index_map_p->at(old_index);
+
+ return value;
+} // end find_new_operand_index()
+
+
// Returns true if the current mismatch is due to a resolved/unresolved
// class pair. Otherwise, returns false.
bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1,
@@ -1042,6 +1146,25 @@
} // end map_index()
+// Map old_index to new_index as needed.
+void VM_RedefineClasses::map_operand_index(int old_index, int new_index) {
+ if (find_new_operand_index(old_index) != -1) {
+ // old_index is already mapped
+ return;
+ }
+
+ if (old_index == new_index) {
+ // no mapping is needed
+ return;
+ }
+
+ _operands_index_map_p->at_put(old_index, new_index);
+ _operands_index_map_count++;
+
+ RC_TRACE(0x00040000, ("mapped bootstrap specifier at index %d to %d", old_index, new_index));
+} // end map_index()
+
+
// Merge old_cp and scratch_cp and return the results of the merge via
// merge_cp_p. The number of entries in *merge_cp_p is returned via
// merge_cp_length_p. The entries in old_cp occupy the same locations
@@ -1113,6 +1236,9 @@
}
} // end for each old_cp entry
+ constantPoolOopDesc::copy_operands(old_cp, *merge_cp_p, CHECK_0);
+ (*merge_cp_p)->extend_operands(scratch_cp, CHECK_0);
+
// We don't need to sanity check that *merge_cp_length_p is within
// *merge_cp_p bounds since we have the minimum on-entry check above.
(*merge_cp_length_p) = old_i;
@@ -1235,6 +1361,7 @@
("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d",
*merge_cp_length_p, scratch_i, _index_map_count));
}
+ finalize_operands_merge(*merge_cp_p, THREAD);
return true;
} // end merge_constant_pools()
@@ -1282,8 +1409,17 @@
_index_map_count = 0;
_index_map_p = new intArray(scratch_cp->length(), -1);
+ _operands_cur_length = constantPoolOopDesc::operand_array_length(old_cp->operands());
+ _operands_index_map_count = 0;
+ _operands_index_map_p = new intArray(
+ constantPoolOopDesc::operand_array_length(scratch_cp->operands()), -1);
+
+ // reference to the cp holder is needed for copy_operands()
+ merge_cp->set_pool_holder(scratch_class());
bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
&merge_cp_length, THREAD);
+ merge_cp->set_pool_holder(NULL);
+
if (!result) {
// The merge can fail due to memory allocation failure or due
// to robustness checks.
@@ -1326,7 +1462,7 @@
// Replace the new constant pool with a shrunken copy of the
// merged constant pool; the previous new constant pool will
// get GCed.
- set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true,
+ set_new_constant_pool(scratch_class, merge_cp, merge_cp_length,
THREAD);
// drop local ref to the merged constant pool
merge_cp()->set_is_conc_safe(true);
@@ -1357,7 +1493,7 @@
// merged constant pool so now the rewritten bytecodes have
// valid references; the previous new constant pool will get
// GCed.
- set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true,
+ set_new_constant_pool(scratch_class, merge_cp, merge_cp_length,
THREAD);
merge_cp()->set_is_conc_safe(true);
}
@@ -1540,6 +1676,7 @@
case Bytecodes::_getfield : // fall through
case Bytecodes::_getstatic : // fall through
case Bytecodes::_instanceof : // fall through
+ case Bytecodes::_invokedynamic : // fall through
case Bytecodes::_invokeinterface: // fall through
case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through
@@ -2343,30 +2480,30 @@
// smaller constant pool is associated with scratch_class.
void VM_RedefineClasses::set_new_constant_pool(
instanceKlassHandle scratch_class, constantPoolHandle scratch_cp,
- int scratch_cp_length, bool shrink, TRAPS) {
- assert(!shrink || scratch_cp->length() >= scratch_cp_length, "sanity check");
-
- if (shrink) {
- // scratch_cp is a merged constant pool and has enough space for a
- // worst case merge situation. We want to associate the minimum
- // sized constant pool with the klass to save space.
- constantPoolHandle smaller_cp(THREAD,
- oopFactory::new_constantPool(scratch_cp_length,
- oopDesc::IsUnsafeConc,
- THREAD));
- // preserve orig_length() value in the smaller copy
- int orig_length = scratch_cp->orig_length();
- assert(orig_length != 0, "sanity check");
- smaller_cp->set_orig_length(orig_length);
- scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
- scratch_cp = smaller_cp;
- smaller_cp()->set_is_conc_safe(true);
- }
+ int scratch_cp_length, TRAPS) {
+ assert(scratch_cp->length() >= scratch_cp_length, "sanity check");
+
+ // scratch_cp is a merged constant pool and has enough space for a
+ // worst case merge situation. We want to associate the minimum
+ // sized constant pool with the klass to save space.
+ constantPoolHandle smaller_cp(THREAD,
+ oopFactory::new_constantPool(scratch_cp_length,
+ oopDesc::IsUnsafeConc,
+ THREAD));
+ // preserve orig_length() value in the smaller copy
+ int orig_length = scratch_cp->orig_length();
+ assert(orig_length != 0, "sanity check");
+ smaller_cp->set_orig_length(orig_length);
+
+ // attach klass to new constant pool
+ // reference to the cp holder is needed for copy_operands()
+ smaller_cp->set_pool_holder(scratch_class());
+
+ scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
+ scratch_cp = smaller_cp;
+ smaller_cp()->set_is_conc_safe(true);
// attach new constant pool to klass
- scratch_cp->set_pool_holder(scratch_class());
-
- // attach klass to new constant pool
scratch_class->set_constants(scratch_cp());
int i; // for portability
@@ -3310,6 +3447,16 @@
// that reference methods of the evolved class.
SystemDictionary::classes_do(adjust_cpool_cache_and_vtable, THREAD);
+ // JSR-292 support
+ MemberNameTable* mnt = the_class->member_names();
+ if (mnt != NULL) {
+ bool trace_name_printed = false;
+ mnt->adjust_method_entries(_matching_old_methods,
+ _matching_new_methods,
+ _matching_methods_length,
+ &trace_name_printed);
+ }
+
if (the_class->oop_map_cache() != NULL) {
// Flush references to any obsolete methods from the oop map cache
// so that obsolete methods are not pinned.
--- ./hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Wed May 07 19:26:16 2014 -0700
@@ -370,6 +370,13 @@
// _index_map_p contains any entries.
int _index_map_count;
intArray * _index_map_p;
+
+ // _operands_index_map_count is just an optimization for knowing if
+ // _operands_index_map_p contains any entries.
+ int _operands_cur_length;
+ int _operands_index_map_count;
+ intArray * _operands_index_map_p;
+
// ptr to _class_count scratch_classes
instanceKlassHandle * _scratch_classes;
jvmtiError _res;
@@ -431,16 +438,24 @@
// and in all direct and indirect subclasses.
void increment_class_counter(instanceKlass *ik, TRAPS);
- // Support for constant pool merging (these routines are in alpha
- // order):
+ // Support for constant pool merging (these routines are in alpha order):
void append_entry(constantPoolHandle scratch_cp, int scratch_i,
constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
+ void append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index,
+ constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
+ void finalize_operands_merge(constantPoolHandle merge_cp, TRAPS);
+ int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i,
+ constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
+ int find_or_append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index,
+ constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
int find_new_index(int old_index);
+ int find_new_operand_index(int old_bootstrap_spec_index);
bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1,
constantPoolHandle cp2, int index2);
bool is_unresolved_string_mismatch(constantPoolHandle cp1, int index1,
constantPoolHandle cp2, int index2);
void map_index(constantPoolHandle scratch_cp, int old_index, int new_index);
+ void map_operand_index(int old_bootstrap_spec_index, int new_bootstrap_spec_index);
bool merge_constant_pools(constantPoolHandle old_cp,
constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p,
int *merge_cp_length_p, TRAPS);
@@ -474,7 +489,7 @@
address& stackmap_addr_ref, address stackmap_end, u2 frame_i,
u1 frame_size, TRAPS);
void set_new_constant_pool(instanceKlassHandle scratch_class,
- constantPoolHandle scratch_cp, int scratch_cp_length, bool shrink, TRAPS);
+ constantPoolHandle scratch_cp, int scratch_cp_length, TRAPS);
void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
--- ./hotspot/src/share/vm/prims/methodHandles.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/prims/methodHandles.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2014, 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
@@ -29,6 +29,7 @@
#include "interpreter/oopMapCache.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
+#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/javaCalls.hpp"
@@ -123,7 +124,9 @@
return Handle(THREAD, k->allocate_instance(THREAD));
}
-oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
+oop MethodHandles::init_MemberName(Handle mname, Handle target) {
+ Thread* thread = Thread::current();
+ oop target_oop = target();
klassOop target_klass = target_oop->klass();
if (target_klass == SystemDictionary::reflect_Field_klass()) {
oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
@@ -131,24 +134,24 @@
int mods = java_lang_reflect_Field::modifiers(target_oop);
oop type = java_lang_reflect_Field::type(target_oop);
oop name = java_lang_reflect_Field::name(target_oop);
- klassOop k = java_lang_Class::as_klassOop(clazz);
- intptr_t offset = instanceKlass::cast(k)->field_offset(slot);
- return init_field_MemberName(mname_oop, k, accessFlags_from(mods), type, name, offset);
+ KlassHandle k(thread, java_lang_Class::as_klassOop(clazz));
+ intptr_t offset = instanceKlass::cast(k())->field_offset(slot);
+ return init_field_MemberName(mname, k, accessFlags_from(mods), type, name, offset);
} else if (target_klass == SystemDictionary::reflect_Method_klass()) {
oop clazz = java_lang_reflect_Method::clazz(target_oop);
int slot = java_lang_reflect_Method::slot(target_oop);
- klassOop k = java_lang_Class::as_klassOop(clazz);
- if (k != NULL && Klass::cast(k)->oop_is_instance()) {
- methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
- return init_method_MemberName(mname_oop, m, true, k);
+ KlassHandle k(thread, java_lang_Class::as_klassOop(clazz));
+ if (!k.is_null() && k->oop_is_instance()) {
+ methodOop m = instanceKlass::cast(k())->method_with_idnum(slot);
+ return init_method_MemberName(mname, m, true, k);
}
} else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
oop clazz = java_lang_reflect_Constructor::clazz(target_oop);
int slot = java_lang_reflect_Constructor::slot(target_oop);
- klassOop k = java_lang_Class::as_klassOop(clazz);
- if (k != NULL && Klass::cast(k)->oop_is_instance()) {
- methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
- return init_method_MemberName(mname_oop, m, false, k);
+ KlassHandle k(thread, java_lang_Class::as_klassOop(clazz));
+ if (!k.is_null() && k->oop_is_instance()) {
+ methodOop m = instanceKlass::cast(k())->method_with_idnum(slot);
+ return init_method_MemberName(mname, m, false, k);
}
} else if (target_klass == SystemDictionary::MemberName_klass()) {
// Note: This only works if the MemberName has already been resolved.
@@ -156,17 +159,18 @@
int flags = java_lang_invoke_MemberName::flags(target_oop);
oop vmtarget = java_lang_invoke_MemberName::vmtarget(target_oop);
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop);
- klassOop k = java_lang_Class::as_klassOop(clazz);
+ KlassHandle k(thread, java_lang_Class::as_klassOop(clazz));
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
if (vmtarget == NULL) return NULL; // not resolved
if ((flags & IS_FIELD) != 0) {
assert(vmtarget->is_klass(), "field vmtarget is klassOop");
int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0);
// FIXME: how does k (receiver_limit) contribute?
- return init_field_MemberName(mname_oop, klassOop(vmtarget), accessFlags_from(basic_mods), NULL, NULL, vmindex);
+ KlassHandle k_vmtarget(thread, klassOop(vmtarget));
+ return init_field_MemberName(mname, k_vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex);
} else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) {
assert(vmtarget->is_method(), "method or constructor vmtarget is methodOop");
- return init_method_MemberName(mname_oop, methodOop(vmtarget), ref_kind_does_dispatch(ref_kind), k);
+ return init_method_MemberName(mname, methodOop(vmtarget), ref_kind_does_dispatch(ref_kind), k);
} else {
return NULL;
}
@@ -174,8 +178,9 @@
return NULL;
}
-oop MethodHandles::init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch,
- klassOop resolved_klass) {
+oop MethodHandles::init_method_MemberName(Handle mname, methodOop m, bool do_dispatch,
+ KlassHandle resolved_klass_h) {
+ klassOop resolved_klass = resolved_klass_h();
AccessFlags mods = m->access_flags();
int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
int vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch
@@ -235,6 +240,7 @@
}
}
+ oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags(mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, m);
java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); // vtable/itable index
@@ -246,11 +252,12 @@
// If relevant, the vtable or itable value is stored as vmindex.
// This is done eagerly, since it is readily available without
// constructing any new objects.
- // TO DO: maybe intern mname_oop
- return mname_oop;
+ instanceKlass::cast(m->method_holder())->add_member_name(m->method_idnum(), mname);
+
+ return mname();
}
-Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS) {
+Handle MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) {
Handle empty;
if (info.resolved_appendix().not_null()) {
// The resolved MemberName must not be accompanied by an appendix argument,
@@ -270,23 +277,24 @@
} else {
vmindex = info.vtable_index();
}
- oop res = init_method_MemberName(mname_oop, m(), (vmindex >= 0), defc());
+ oop res = init_method_MemberName(mname, m(), (vmindex >= 0), defc());
assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), "");
return Handle(THREAD, res);
}
-oop MethodHandles::init_field_MemberName(oop mname_oop, klassOop field_holder,
+oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder,
AccessFlags mods, oop type, oop name,
intptr_t offset, bool is_setter) {
int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
- oop vmtarget = field_holder;
+ oop vmtarget = field_holder();
int vmindex = offset; // determines the field uniquely when combined with static bit
+ oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags(mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex);
- java_lang_invoke_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror());
+ java_lang_invoke_MemberName::set_clazz(mname_oop, field_holder()->java_mirror());
if (name != NULL)
java_lang_invoke_MemberName::set_name(mname_oop, name);
if (type != NULL)
@@ -298,11 +306,10 @@
// because they unambiguously identify the field.
// Although the fieldDescriptor::_index would also identify the field,
// we do not use it, because it is harder to decode.
- // TO DO: maybe intern mname_oop
- return mname_oop;
+ return mname();
}
-Handle MethodHandles::init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS) {
+Handle MethodHandles::init_field_MemberName(Handle mname, FieldAccessInfo& info, TRAPS) {
return Handle();
#if 0
KlassHandle field_holder = info.klass();
@@ -728,7 +735,7 @@
return empty;
}
}
- return init_method_MemberName(mname(), result, THREAD);
+ return init_method_MemberName(mname, result, THREAD);
}
case IS_CONSTRUCTOR:
{
@@ -746,7 +753,7 @@
}
}
assert(result.is_statically_bound(), "");
- return init_method_MemberName(mname(), result, THREAD);
+ return init_method_MemberName(mname, result, THREAD);
}
case IS_FIELD:
{
@@ -759,7 +766,7 @@
oop name = field_name_or_null(fd.name());
bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind));
mname = Handle(THREAD,
- init_field_MemberName(mname(), sel_klass->as_klassOop(),
+ init_field_MemberName(mname, sel_klass,
fd.access_flags(), type, name, fd.offset(), is_setter));
return mname;
}
@@ -851,16 +858,16 @@
THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format");
}
-int MethodHandles::find_MemberNames(klassOop k,
+int MethodHandles::find_MemberNames(KlassHandle k,
Symbol* name, Symbol* sig,
- int mflags, klassOop caller,
- int skip, objArrayOop results) {
- DEBUG_ONLY(No_Safepoint_Verifier nsv);
- // this code contains no safepoints!
+ int mflags, KlassHandle caller,
+ int skip, objArrayHandle results) {
// %%% take caller into account!
- if (k == NULL || !Klass::cast(k)->oop_is_instance()) return -1;
+ Thread* thread = Thread::current();
+
+ if (k.is_null() || !k->oop_is_instance()) return -1;
int rfill = 0, rlimit = results->length(), rskip = skip;
// overflow measurement:
@@ -888,7 +895,7 @@
}
if ((match_flags & IS_FIELD) != 0) {
- for (FieldStream st(k, local_only, !search_intfc); !st.eos(); st.next()) {
+ for (FieldStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) {
if (name != NULL && st.name() != name)
continue;
if (sig != NULL && st.signature() != sig)
@@ -897,15 +904,15 @@
if (rskip > 0) {
--rskip;
} else if (rfill < rlimit) {
- oop result = results->obj_at(rfill++);
- if (!java_lang_invoke_MemberName::is_instance(result))
+ Handle result(thread, results->obj_at(rfill++));
+ if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug!
oop type = field_signature_type_or_null(st.signature());
oop name = field_name_or_null(st.name());
- oop saved = MethodHandles::init_field_MemberName(result, st.klass()->as_klassOop(),
+ oop saved = MethodHandles::init_field_MemberName(result, st.klass(),
st.access_flags(), type, name,
st.offset());
- if (saved != result)
+ if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
@@ -938,7 +945,7 @@
} else {
// caller will accept either sort; no need to adjust name
}
- for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) {
+ for (MethodStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) {
methodOop m = st.method();
Symbol* m_name = m->name();
if (m_name == clinit_name)
@@ -951,11 +958,11 @@
if (rskip > 0) {
--rskip;
} else if (rfill < rlimit) {
- oop result = results->obj_at(rfill++);
- if (!java_lang_invoke_MemberName::is_instance(result))
+ Handle result(thread, results->obj_at(rfill++));
+ if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug!
- oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL);
- if (saved != result)
+ oop saved = MethodHandles::init_method_MemberName(result, m, true, KlassHandle());
+ if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
@@ -967,6 +974,85 @@
return rfill + overflow;
}
+//------------------------------------------------------------------------------
+// MemberNameTable
+//
+
+MemberNameTable::MemberNameTable(int methods_cnt)
+ : GrowableArray(methods_cnt, true) {
+ assert_locked_or_safepoint(MemberNameTable_lock);
+}
+
+MemberNameTable::~MemberNameTable() {
+ assert_locked_or_safepoint(MemberNameTable_lock);
+ int len = this->length();
+
+ for (int idx = 0; idx < len; idx++) {
+ jweak ref = this->at(idx);
+ JNIHandles::destroy_weak_global(ref);
+ }
+}
+
+void MemberNameTable::add_member_name(int index, jweak mem_name_wref) {
+ assert_locked_or_safepoint(MemberNameTable_lock);
+ this->at_put_grow(index, mem_name_wref);
+}
+
+// Return a member name oop or NULL.
+oop MemberNameTable::get_member_name(int index) {
+ assert_locked_or_safepoint(MemberNameTable_lock);
+ jweak ref = this->at(index);
+ oop mem_name = JNIHandles::resolve(ref);
+ return mem_name;
+}
+
+oop MemberNameTable::find_member_name_by_method(methodOop old_method) {
+ assert_locked_or_safepoint(MemberNameTable_lock);
+ oop found = NULL;
+ int len = this->length();
+
+ for (int idx = 0; idx < len; idx++) {
+ oop mem_name = JNIHandles::resolve(this->at(idx));
+ if (mem_name == NULL) {
+ continue;
+ }
+ methodOop method = (methodOop)java_lang_invoke_MemberName::vmtarget(mem_name);
+ if (method == old_method) {
+ found = mem_name;
+ break;
+ }
+ }
+ return found;
+}
+
+// It is called at safepoint only
+void MemberNameTable::adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
+ int methods_length, bool *trace_name_printed) {
+ assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
+ // search the MemberNameTable for uses of either obsolete or EMCP methods
+ for (int j = 0; j < methods_length; j++) {
+ methodOop old_method = old_methods[j];
+ methodOop new_method = new_methods[j];
+ oop mem_name = find_member_name_by_method(old_method);
+ if (mem_name != NULL) {
+ java_lang_invoke_MemberName::adjust_vmtarget(mem_name, new_method);
+
+ if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
+ if (!(*trace_name_printed)) {
+ // RC_TRACE_MESG macro has an embedded ResourceMark
+ RC_TRACE_MESG(("adjust: name=%s",
+ Klass::cast(old_method->method_holder())->external_name()));
+ *trace_name_printed = true;
+ }
+ // RC_TRACE macro has an embedded ResourceMark
+ RC_TRACE(0x00400000, ("MemberName method update: %s(%s)",
+ new_method->name()->as_C_string(),
+ new_method->signature()->as_C_string()));
+ }
+ }
+ }
+}
+
//
// Here are the native methods in java.lang.invoke.MethodHandleNatives
// They are the private interface between this JVM and the HotSpot-specific
@@ -1058,8 +1144,8 @@
if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
- oop target_oop = JNIHandles::resolve_non_null(target_jh);
- MethodHandles::init_MemberName(mname(), target_oop);
+ Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
+ MethodHandles::init_MemberName(mname, target);
}
JVM_END
@@ -1174,11 +1260,12 @@
} else if (vmtarget->is_klass()) {
x = Klass::cast((klassOop) vmtarget())->java_mirror();
} else {
- Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
- if (vmtarget->is_method())
- x = MethodHandles::init_method_MemberName(mname2(), methodOop(vmtarget()), false, NULL);
- else
+ if (vmtarget->is_method()) {
+ x = mname();
+ } else {
+ Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
x = MethodHandles::init_MemberName(mname2(), vmtarget());
+ }
}
result->obj_at_put(1, x);
return JNIHandles::make_local(env, result());
@@ -1221,8 +1308,8 @@
// %%% TO DO
}
- int res = MethodHandles::find_MemberNames(k(), name, sig, mflags,
- caller(), skip, results());
+ int res = MethodHandles::find_MemberNames(k, name, sig, mflags,
+ caller, skip, results);
// TO DO: expand at least some of the MemberNames, to avoid massive callbacks
return res;
}
--- ./hotspot/src/share/vm/prims/methodHandles.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/prims/methodHandles.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2014, 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
@@ -39,7 +39,6 @@
// in java.lang.invoke and sun.invoke.
// See also javaClasses for layouts java_lang_invoke_Method{Handle,Type,Type::Form}.
public:
- public:
static bool enabled() { return _enabled; }
static void set_enabled(bool z);
@@ -54,18 +53,18 @@
static Handle resolve_MemberName(Handle mname, KlassHandle caller, TRAPS); // compute vmtarget/vmindex from name/type
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
static Handle new_MemberName(TRAPS); // must be followed by init_MemberName
- static oop init_MemberName(oop mname_oop, oop target_oop); // compute vmtarget/vmindex from target
- static oop init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch,
- klassOop resolved_klass);
- static oop init_field_MemberName(oop mname_oop, klassOop field_holder,
+ static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target
+ static oop init_method_MemberName(Handle mname_h, methodOop m, bool do_dispatch,
+ KlassHandle resolved_klass_h);
+ static oop init_field_MemberName(Handle mname_h, KlassHandle field_holder_h,
AccessFlags mods, oop type, oop name,
intptr_t offset, bool is_setter = false);
- static Handle init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS);
- static Handle init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS);
+ static Handle init_method_MemberName(Handle mname_h, CallInfo& info, TRAPS);
+ static Handle init_field_MemberName(Handle mname_h, FieldAccessInfo& info, TRAPS);
static int method_ref_kind(methodOop m, bool do_dispatch_if_possible = true);
- static int find_MemberNames(klassOop k, Symbol* name, Symbol* sig,
- int mflags, klassOop caller,
- int skip, objArrayOop results);
+ static int find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig,
+ int mflags, KlassHandle caller,
+ int skip, objArrayHandle results);
// bit values for suppress argument to expand_MemberName:
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
@@ -230,4 +229,26 @@
void generate();
};
+//------------------------------------------------------------------------------
+// MemberNameTable
+//
+
+class MemberNameTable : public GrowableArray {
+ public:
+ MemberNameTable(int methods_cnt);
+ ~MemberNameTable();
+
+ void add_member_name(int index, jweak mem_name_ref);
+ oop get_member_name(int index);
+
+ public:
+ // RedefineClasses() API support:
+ // If a MemberName refers to old_method then update it
+ // to refer to new_method.
+ void adjust_method_entries(methodOop* old_methods, methodOop* new_methods,
+ int methods_length, bool *trace_name_printed);
+ private:
+ oop find_member_name_by_method(methodOop old_method);
+};
+
#endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
--- ./hotspot/src/share/vm/prims/whitebox.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/prims/whitebox.cpp Wed May 07 19:26:16 2014 -0700
@@ -27,6 +27,8 @@
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
+#include "code/codeCache.hpp"
+
#include "classfile/symbolTable.hpp"
#include "prims/whitebox.hpp"
@@ -131,6 +133,13 @@
return MemTracker::wbtest_wait_for_data_merge();
WB_END
+WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
+ MutexLockerEx mu(Compile_lock);
+ CodeCache::mark_all_nmethods_for_deoptimization();
+ VM_Deoptimize op;
+ VMThread::execute(&op);
+WB_END
+
//Some convenience methods to deal with objects from java
int WhiteBox::offset_for_field(const char* field_name, oop object,
Symbol* signature_symbol) {
@@ -204,6 +213,7 @@
{CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory },
{CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory },
{CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge},
+ {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
};
#undef CC
--- ./hotspot/src/share/vm/runtime/arguments.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/arguments.cpp Wed May 07 19:26:16 2014 -0700
@@ -1447,6 +1447,17 @@
}
FLAG_SET_DEFAULT(UseParallelGC, true);
+ if (UseAdaptiveSizePolicy) {
+ // We don't want to limit adaptive heap sizing's freedom to adjust the heap
+ // unless the user actually sets these flags.
+ if (FLAG_IS_DEFAULT(MinHeapFreeRatio)) {
+ FLAG_SET_DEFAULT(MinHeapFreeRatio, 0);
+ }
+ if (FLAG_IS_DEFAULT(MaxHeapFreeRatio)) {
+ FLAG_SET_DEFAULT(MaxHeapFreeRatio, 100);
+ }
+ }
+
// If no heap maximum was requested explicitly, use some reasonable fraction
// of the physical memory, up to a maximum of 1GB.
if (UseParallelGC) {
@@ -1719,7 +1730,7 @@
}
bool Arguments::verify_percentage(uintx value, const char* name) {
- if (value <= 100) {
+ if (is_percentage(value)) {
return true;
}
jio_fprintf(defaultStream::error_stream(),
@@ -1768,6 +1779,34 @@
}
}
+bool Arguments::verify_MinHeapFreeRatio(FormatBuffer<80>& err_msg, uintx min_heap_free_ratio) {
+ if (!is_percentage(min_heap_free_ratio)) {
+ err_msg.print("MinHeapFreeRatio must have a value between 0 and 100");
+ return false;
+ }
+ if (min_heap_free_ratio > MaxHeapFreeRatio) {
+ err_msg.print("MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
+ "equal to MaxHeapFreeRatio (" UINTX_FORMAT ")", min_heap_free_ratio,
+ MaxHeapFreeRatio);
+ return false;
+ }
+ return true;
+}
+
+bool Arguments::verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio) {
+ if (!is_percentage(max_heap_free_ratio)) {
+ err_msg.print("MaxHeapFreeRatio must have a value between 0 and 100");
+ return false;
+ }
+ if (max_heap_free_ratio < MinHeapFreeRatio) {
+ err_msg.print("MaxHeapFreeRatio (" UINTX_FORMAT ") must be greater than or "
+ "equal to MinHeapFreeRatio (" UINTX_FORMAT ")", max_heap_free_ratio,
+ MinHeapFreeRatio);
+ return false;
+ }
+ return true;
+}
+
// Check consistency of GC selection
bool Arguments::check_gc_consistency() {
check_gclog_consistency();
@@ -1852,15 +1891,19 @@
"AdaptiveSizePolicyWeight");
status = status && verify_percentage(AdaptivePermSizeWeight, "AdaptivePermSizeWeight");
status = status && verify_percentage(ThresholdTolerance, "ThresholdTolerance");
- status = status && verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio");
- status = status && verify_percentage(MaxHeapFreeRatio, "MaxHeapFreeRatio");
-
- if (MinHeapFreeRatio > MaxHeapFreeRatio) {
- jio_fprintf(defaultStream::error_stream(),
- "MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or "
- "equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
- MinHeapFreeRatio, MaxHeapFreeRatio);
- status = false;
+
+ {
+ // Using "else if" below to avoid printing two error messages if min > max.
+ // This will also prevent us from reporting both min>100 and max>100 at the
+ // same time, but that is less annoying than printing two identical errors IMHO.
+ FormatBuffer<80> err_msg("");
+ if (!verify_MinHeapFreeRatio(err_msg, MinHeapFreeRatio)) {
+ jio_fprintf(defaultStream::error_stream(), "%s\n", err_msg.buffer());
+ status = false;
+ } else if (!verify_MaxHeapFreeRatio(err_msg, MaxHeapFreeRatio)) {
+ jio_fprintf(defaultStream::error_stream(), "%s\n", err_msg.buffer());
+ status = false;
+ }
}
// Keeping the heap 100% free is hard ;-) so limit it to 99%.
MinHeapFreeRatio = MIN2(MinHeapFreeRatio, (uintx) 99);
@@ -1943,11 +1986,12 @@
// than just disable the lock verification. This will be fixed under
// bug 4788986.
if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) {
- if (VerifyGCStartAt == 0) {
+ if (VerifyDuringStartup) {
warning("Heap verification at start-up disabled "
"(due to current incompatibility with FLSVerifyAllHeapReferences)");
- VerifyGCStartAt = 1; // Disable verification at start-up
+ VerifyDuringStartup = false; // Disable verification at start-up
}
+
if (VerifyBeforeExit) {
warning("Heap verification at shutdown disabled "
"(due to current incompatibility with FLSVerifyAllHeapReferences)");
@@ -2549,7 +2593,9 @@
FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize);
}
+#ifndef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD.
FLAG_SET_DEFAULT(UseLargePages, true);
+#endif
// Increase some data structure sizes for efficiency
FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize);
@@ -3111,6 +3157,10 @@
UNSUPPORTED_OPTION(UseG1GC, "G1 GC");
#endif
+#ifdef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD.
+ UNSUPPORTED_OPTION(UseLargePages, "-XX:+UseLargePages");
+#endif
+
#ifndef PRODUCT
if (TraceBytecodesAt != 0) {
TraceBytecodes = true;
--- ./hotspot/src/share/vm/runtime/arguments.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/arguments.hpp Wed May 07 19:26:16 2014 -0700
@@ -27,6 +27,7 @@
#include "runtime/java.hpp"
#include "runtime/perfData.hpp"
+#include "utilities/debug.hpp"
#include "utilities/top.hpp"
// Arguments parses the command line and recognizes options
@@ -350,6 +351,9 @@
static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
return is_bad_option(option, ignore, NULL);
}
+ static bool is_percentage(uintx val) {
+ return val <= 100;
+ }
static bool verify_interval(uintx val, uintx min,
uintx max, const char* name);
static bool verify_min_value(intx val, intx min, const char* name);
@@ -411,6 +415,12 @@
public:
// Parses the arguments
static jint parse(const JavaVMInitArgs* args);
+ // Verifies that the given value will fit as a MinHeapFreeRatio. If not, an error
+ // message is returned in the provided buffer.
+ static bool verify_MinHeapFreeRatio(FormatBuffer<80>& err_msg, uintx min_heap_free_ratio);
+ // Verifies that the given value will fit as a MaxHeapFreeRatio. If not, an error
+ // message is returned in the provided buffer.
+ static bool verify_MaxHeapFreeRatio(FormatBuffer<80>& err_msg, uintx max_heap_free_ratio);
// Check for consistency in the selection of the garbage collector.
static bool check_gc_consistency();
// Check consistecy or otherwise of VM argument settings
--- ./hotspot/src/share/vm/runtime/frame.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/frame.cpp Wed May 07 19:26:16 2014 -0700
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "compiler/abstractCompiler.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
@@ -559,7 +560,7 @@
st->print("%s frame (sp=" INTPTR_FORMAT " unextended sp=" INTPTR_FORMAT, print_name(), sp(), unextended_sp());
if (sp() != NULL)
- st->print(", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), pc());
+ st->print(", fp=" INTPTR_FORMAT ", real_fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), real_fp(), pc());
if (StubRoutines::contains(pc())) {
st->print_cr(")");
@@ -720,10 +721,14 @@
} else if (_cb->is_buffer_blob()) {
st->print("v ~BufferBlob::%s", ((BufferBlob *)_cb)->name());
} else if (_cb->is_nmethod()) {
- methodOop m = ((nmethod *)_cb)->method();
+ nmethod* nm = (nmethod*)_cb;
+ methodOop m = nm->method();
if (m != NULL) {
m->name_and_sig_as_C_string(buf, buflen);
- st->print("J %s", buf);
+ st->print("J %d%s %s %s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+0x%x]",
+ nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
+ ((nm->compiler() != NULL) ? nm->compiler()->name() : ""),
+ buf, m->code_size(), _pc, _cb->code_begin(), _pc - _cb->code_begin());
} else {
st->print("J " PTR_FORMAT, pc());
}
--- ./hotspot/src/share/vm/runtime/globals.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/globals.hpp Wed May 07 19:26:16 2014 -0700
@@ -1697,6 +1697,9 @@
product(bool, CMSAbortSemantics, false, \
"Whether abort-on-overflow semantics is implemented") \
\
+ product(bool, CMSParallelInitialMarkEnabled, false, \
+ "Use the parallel initial mark.") \
+ \
product(bool, CMSParallelRemarkEnabled, true, \
"Whether parallel remark enabled (only if ParNewGC)") \
\
@@ -1708,6 +1711,14 @@
"Whether to always record survivor space PLAB bdries" \
" (effective only if CMSParallelSurvivorRemarkEnabled)") \
\
+ product(bool, CMSEdenChunksRecordAlways, false, \
+ "Whether to always record eden chunks used for " \
+ "the parallel initial mark or remark of eden" ) \
+ \
+ product(bool, CMSPrintEdenSurvivorChunks, false, \
+ "Print the eden and the survivor chunks used for the parallel " \
+ "initial mark or remark of the eden/survivor spaces") \
+ \
product(bool, CMSConcurrentMTEnabled, true, \
"Whether multi-threaded concurrent work enabled (if ParNewGC)") \
\
@@ -1917,6 +1928,9 @@
notproduct(bool, ExecuteInternalVMTests, false, \
"Enable execution of internal VM tests.") \
\
+ notproduct(bool, VerboseInternalVMTests, false, \
+ "Turn on logging for internal VM tests.") \
+ \
product_pd(bool, UseTLAB, "Use thread-local object allocation") \
\
product_pd(bool, ResizeTLAB, \
@@ -2126,6 +2140,13 @@
product(intx, PrefetchFieldsAhead, -1, \
"How many fields ahead to prefetch in oop scan (<= 0 means off)") \
\
+ diagnostic(bool, VerifySilently, false, \
+ "Don't print print the verification progress") \
+ \
+ diagnostic(bool, VerifyDuringStartup, false, \
+ "Verify memory system before executing any Java code " \
+ "during VM initialization") \
+ \
diagnostic(bool, VerifyBeforeExit, trueInDebug, \
"Verify system before exiting") \
\
@@ -3010,10 +3031,10 @@
product_pd(uintx, MaxPermSize, \
"Maximum size of permanent generation (in bytes)") \
\
- product(uintx, MinHeapFreeRatio, 40, \
+ manageable(uintx, MinHeapFreeRatio, 40, \
"Min percentage of heap free after GC to avoid expansion") \
\
- product(uintx, MaxHeapFreeRatio, 70, \
+ manageable(uintx, MaxHeapFreeRatio, 70, \
"Max percentage of heap free after GC to avoid shrinking") \
\
product(intx, SoftRefLRUPolicyMSPerMB, 1000, \
--- ./hotspot/src/share/vm/runtime/mutexLocker.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/mutexLocker.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -57,6 +57,7 @@
Mutex* JNIGlobalHandle_lock = NULL;
Mutex* JNIHandleBlockFreeList_lock = NULL;
Mutex* JNICachedItableIndex_lock = NULL;
+Mutex* MemberNameTable_lock = NULL;
Mutex* JmethodIdCreation_lock = NULL;
Mutex* JfieldIdCreation_lock = NULL;
Monitor* JNICritical_lock = NULL;
@@ -263,6 +264,7 @@
def(Heap_lock , Monitor, nonleaf+1, false);
def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation
def(JNICachedItableIndex_lock , Mutex , nonleaf+1, false); // Used to cache an itable index during JNI invoke
+ def(MemberNameTable_lock , Mutex , nonleaf+1, false); // Used to protect MemberNameTable
def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock
def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true );
--- ./hotspot/src/share/vm/runtime/mutexLocker.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/mutexLocker.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -51,6 +51,7 @@
extern Mutex* JNIGlobalHandle_lock; // a lock on creating JNI global handles
extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list
extern Mutex* JNICachedItableIndex_lock; // a lock on caching an itable index during JNI invoke
+extern Mutex* MemberNameTable_lock; // a lock on the MemberNameTable updates
extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers
extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers
extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in
--- ./hotspot/src/share/vm/runtime/os.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/os.hpp Wed May 07 19:26:16 2014 -0700
@@ -330,8 +330,8 @@
static char* non_memory_address_word();
// reserve, commit and pin the entire memory region
- static char* reserve_memory_special(size_t size, char* addr = NULL,
- bool executable = false);
+ static char* reserve_memory_special(size_t size, size_t alignment,
+ char* addr, bool executable);
static bool release_memory_special(char* addr, size_t bytes);
static void large_page_init();
static size_t large_page_size();
--- ./hotspot/src/share/vm/runtime/sweeper.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/sweeper.cpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -36,6 +36,7 @@
#include "runtime/vm_operations.hpp"
#include "trace/tracing.hpp"
#include "utilities/events.hpp"
+#include "utilities/ticks.inline.hpp"
#include "utilities/xmlstream.hpp"
#ifdef ASSERT
@@ -148,12 +149,12 @@
int NMethodSweeper::_number_of_flushes = 0; // Total of full traversals caused by full cache
int NMethodSweeper::_total_nof_methods_reclaimed = 0;
-jlong NMethodSweeper::_total_time_sweeping = 0;
-jlong NMethodSweeper::_total_time_this_sweep = 0;
-jlong NMethodSweeper::_peak_sweep_time = 0;
-jlong NMethodSweeper::_peak_sweep_fraction_time = 0;
-jlong NMethodSweeper::_total_disconnect_time = 0;
-jlong NMethodSweeper::_peak_disconnect_time = 0;
+Tickspan NMethodSweeper::_total_time_sweeping;
+Tickspan NMethodSweeper::_total_time_this_sweep;
+Tickspan NMethodSweeper::_peak_sweep_time;
+Tickspan NMethodSweeper::_peak_sweep_fraction_time;
+Tickspan NMethodSweeper::_total_disconnect_time;
+Tickspan NMethodSweeper::_peak_disconnect_time;
class MarkActivationClosure: public CodeBlobClosure {
public:
@@ -192,7 +193,7 @@
_invocations = NmethodSweepFraction;
_current = CodeCache::first_nmethod();
_traversals += 1;
- _total_time_this_sweep = 0;
+ _total_time_this_sweep = Tickspan();
if (PrintMethodFlushing) {
tty->print_cr("### Sweep: stack traversal %d", _traversals);
@@ -256,8 +257,7 @@
}
void NMethodSweeper::sweep_code_cache() {
-
- jlong sweep_start_counter = os::elapsed_counter();
+ Ticks sweep_start_counter = Ticks::now();
_flushed_count = 0;
_zombified_count = 0;
@@ -322,8 +322,8 @@
}
}
- jlong sweep_end_counter = os::elapsed_counter();
- jlong sweep_time = sweep_end_counter - sweep_start_counter;
+ const Ticks sweep_end_counter = Ticks::now();
+ const Tickspan sweep_time = sweep_end_counter - sweep_start_counter;
_total_time_sweeping += sweep_time;
_total_time_this_sweep += sweep_time;
_peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time);
@@ -344,7 +344,7 @@
#ifdef ASSERT
if(PrintMethodFlushing) {
- tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, (jlong)sweep_time);
+ tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, (jlong)sweep_time.value());
}
#endif
@@ -529,7 +529,7 @@
}
}
- jlong disconnect_start_counter = os::elapsed_counter();
+ Ticks disconnect_start_counter = Ticks::now();
// Traverse the code cache trying to dump the oldest nmethods
uint curr_max_comp_id = CompileBroker::get_compilation_id();
@@ -577,8 +577,8 @@
CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation);
}
- jlong disconnect_end_counter = os::elapsed_counter();
- jlong disconnect_time = disconnect_end_counter - disconnect_start_counter;
+ const Ticks disconnect_end_counter = Ticks::now();
+ const Tickspan disconnect_time = disconnect_end_counter - disconnect_start_counter;
_total_disconnect_time += disconnect_time;
_peak_disconnect_time = MAX2(disconnect_time, _peak_disconnect_time);
@@ -597,7 +597,7 @@
#ifdef ASSERT
if(PrintMethodFlushing && Verbose) {
- tty->print_cr("### sweeper: unload time: " INT64_FORMAT, (jlong)disconnect_time);
+ tty->print_cr("### sweeper: unload time: " INT64_FORMAT, (jlong)disconnect_time.value());
}
#endif
}
--- ./hotspot/src/share/vm/runtime/sweeper.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/sweeper.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_RUNTIME_SWEEPER_HPP
#define SHARE_VM_RUNTIME_SWEEPER_HPP
+#include "utilities/ticks.hpp"
// An NmethodSweeper is an incremental cleaner for:
// - cleanup inline caches
// - reclamation of unreferences zombie nmethods
@@ -56,12 +57,12 @@
// Stat counters
static int _number_of_flushes; // Total of full traversals caused by full cache
static int _total_nof_methods_reclaimed; // Accumulated nof methods flushed
- static jlong _total_time_sweeping; // Accumulated time sweeping
- static jlong _total_time_this_sweep; // Total time this sweep
- static jlong _peak_sweep_time; // Peak time for a full sweep
- static jlong _peak_sweep_fraction_time; // Peak time sweeping one fraction
- static jlong _total_disconnect_time; // Total time cleaning code mem
- static jlong _peak_disconnect_time; // Peak time cleaning code mem
+ static Tickspan _total_time_sweeping; // Accumulated time sweeping
+ static Tickspan _total_time_this_sweep; // Total time this sweep
+ static Tickspan _peak_sweep_time; // Peak time for a full sweep
+ static Tickspan _peak_sweep_fraction_time; // Peak time sweeping one fraction
+ static Tickspan _total_disconnect_time; // Total time cleaning code mem
+ static Tickspan _peak_disconnect_time; // Peak time cleaning code mem
static void process_nmethod(nmethod *nm);
@@ -71,13 +72,14 @@
static long traversal_count() { return _traversals; }
static int number_of_flushes() { return _number_of_flushes; }
static int total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; }
- static jlong total_time_sweeping() { return _total_time_sweeping; }
- static jlong peak_sweep_time() { return _peak_sweep_time; }
- static jlong peak_sweep_fraction_time() { return _peak_sweep_fraction_time; }
- static jlong total_disconnect_time() { return _total_disconnect_time; }
- static jlong peak_disconnect_time() { return _peak_disconnect_time; }
+ static const Tickspan total_time_sweeping() { return _total_time_sweeping; }
+ static const Tickspan peak_sweep_time() { return _peak_sweep_time; }
+ static const Tickspan peak_sweep_fraction_time() { return _peak_sweep_fraction_time; }
+ static const Tickspan total_disconnect_time() { return _total_disconnect_time; }
+ static const Tickspan peak_disconnect_time() { return _peak_disconnect_time; }
#ifdef ASSERT
+ static bool is_sweeping(nmethod* which) { return _current == which; }
// Keep track of sweeper activity in the ring buffer
static void record_sweep(nmethod* nm, int line);
static void report_events(int id, address entry);
--- ./hotspot/src/share/vm/runtime/thread.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/thread.cpp Wed May 07 19:26:16 2014 -0700
@@ -3416,9 +3416,10 @@
}
assert (Universe::is_fully_initialized(), "not initialized");
- if (VerifyBeforeGC && VerifyGCStartAt == 0) {
- Universe::heap()->prepare_for_verify();
- Universe::verify(); // make sure we're starting with a clean slate
+ if (VerifyDuringStartup) {
+ // Make sure we're starting with a clean slate.
+ VM_Verify verify_op;
+ VMThread::execute(&verify_op);
}
EXCEPTION_MARK;
@@ -3504,11 +3505,12 @@
java_lang_Thread::set_thread_status(thread_object,
java_lang_Thread::RUNNABLE);
- // The VM preresolve methods to these classes. Make sure that get initialized
+ // The VM creates & returns objects of this class. Make sure it's initialized.
+ initialize_class(vmSymbols::java_lang_Class(), CHECK_0);
+
+ // The VM preresolves methods to these classes. Make sure that they get initialized
initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0);
initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0);
- // The VM creates & returns objects of this class. Make sure it's initialized.
- initialize_class(vmSymbols::java_lang_Class(), CHECK_0);
call_initializeSystemClass(CHECK_0);
// get the Java runtime name after java.lang.System is initialized
--- ./hotspot/src/share/vm/runtime/virtualspace.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/virtualspace.cpp Wed May 07 19:26:16 2014 -0700
@@ -42,8 +42,19 @@
// ReservedSpace
+
+// Dummy constructor
+ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
+ _alignment(0), _special(false), _executable(false) {
+}
+
ReservedSpace::ReservedSpace(size_t size) {
- initialize(size, 0, false, NULL, 0, false);
+ size_t page_size = os::page_size_for_region(size, size, 1);
+ bool large_pages = page_size != (size_t)os::vm_page_size();
+ // Don't force the alignment to be large page aligned,
+ // since that will waste memory.
+ size_t alignment = os::vm_allocation_granularity();
+ initialize(size, alignment, large_pages, NULL, 0, false);
}
ReservedSpace::ReservedSpace(size_t size, size_t alignment,
@@ -323,16 +334,18 @@
if (special) {
- base = os::reserve_memory_special(size, requested_address, executable);
+ base = os::reserve_memory_special(size, alignment, requested_address, executable);
if (base != NULL) {
if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
// OS ignored requested address. Try different address.
return;
}
- // Check alignment constraints
+ // Check alignment constraints.
assert((uintptr_t) base % alignment == 0,
- "Large pages returned a non-aligned address");
+ err_msg("Large pages returned a non-aligned address, base: "
+ PTR_FORMAT " alignment: " PTR_FORMAT,
+ base, (void*)(uintptr_t)alignment));
_special = true;
} else {
// failed; try to reserve regular memory below
@@ -928,4 +941,188 @@
tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary());
}
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+#define test_log(...) \
+ do {\
+ if (VerboseInternalVMTests) { \
+ tty->print_cr(__VA_ARGS__); \
+ tty->flush(); \
+ }\
+ } while (false)
+
+class TestReservedSpace : AllStatic {
+ public:
+ static void small_page_write(void* addr, size_t size) {
+ size_t page_size = os::vm_page_size();
+
+ char* end = (char*)addr + size;
+ for (char* p = (char*)addr; p < end; p += page_size) {
+ *p = 1;
+ }
+ }
+
+ static void release_memory_for_test(ReservedSpace rs) {
+ if (rs.special()) {
+ guarantee(os::release_memory_special(rs.base(), rs.size()), "Shouldn't fail");
+ } else {
+ guarantee(os::release_memory(rs.base(), rs.size()), "Shouldn't fail");
+ }
+ }
+
+ static void test_reserved_space1(size_t size, size_t alignment) {
+ test_log("test_reserved_space1(%p)", (void*) (uintptr_t) size);
+
+ assert(is_size_aligned(size, alignment), "Incorrect input parameters");
+
+ ReservedSpace rs(size, // size
+ alignment, // alignment
+ UseLargePages, // large
+ NULL, // requested_address
+ 0); // noacces_prefix
+
+ test_log(" rs.special() == %d", rs.special());
+
+ assert(rs.base() != NULL, "Must be");
+ assert(rs.size() == size, "Must be");
+
+ assert(is_ptr_aligned(rs.base(), alignment), "aligned sizes should always give aligned addresses");
+ assert(is_size_aligned(rs.size(), alignment), "aligned sizes should always give aligned addresses");
+
+ if (rs.special()) {
+ small_page_write(rs.base(), size);
+ }
+
+ release_memory_for_test(rs);
+ }
+
+ static void test_reserved_space2(size_t size) {
+ test_log("test_reserved_space2(%p)", (void*)(uintptr_t)size);
+
+ assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
+
+ ReservedSpace rs(size);
+
+ test_log(" rs.special() == %d", rs.special());
+
+ assert(rs.base() != NULL, "Must be");
+ assert(rs.size() == size, "Must be");
+
+ if (rs.special()) {
+ small_page_write(rs.base(), size);
+ }
+
+ release_memory_for_test(rs);
+ }
+
+ static void test_reserved_space3(size_t size, size_t alignment, bool maybe_large) {
+ test_log("test_reserved_space3(%p, %p, %d)",
+ (void*)(uintptr_t)size, (void*)(uintptr_t)alignment, maybe_large);
+
+ assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
+ assert(is_size_aligned(size, alignment), "Must be at least aligned against alignment");
+
+ bool large = maybe_large && UseLargePages && size >= os::large_page_size();
+
+ ReservedSpace rs(size, alignment, large, false);
+
+ test_log(" rs.special() == %d", rs.special());
+
+ assert(rs.base() != NULL, "Must be");
+ assert(rs.size() == size, "Must be");
+
+ if (rs.special()) {
+ small_page_write(rs.base(), size);
+ }
+
+ release_memory_for_test(rs);
+ }
+
+
+ static void test_reserved_space1() {
+ size_t size = 2 * 1024 * 1024;
+ size_t ag = os::vm_allocation_granularity();
+
+ test_reserved_space1(size, ag);
+ test_reserved_space1(size * 2, ag);
+ test_reserved_space1(size * 10, ag);
+ }
+
+ static void test_reserved_space2() {
+ size_t size = 2 * 1024 * 1024;
+ size_t ag = os::vm_allocation_granularity();
+
+ test_reserved_space2(size * 1);
+ test_reserved_space2(size * 2);
+ test_reserved_space2(size * 10);
+ test_reserved_space2(ag);
+ test_reserved_space2(size - ag);
+ test_reserved_space2(size);
+ test_reserved_space2(size + ag);
+ test_reserved_space2(size * 2);
+ test_reserved_space2(size * 2 - ag);
+ test_reserved_space2(size * 2 + ag);
+ test_reserved_space2(size * 3);
+ test_reserved_space2(size * 3 - ag);
+ test_reserved_space2(size * 3 + ag);
+ test_reserved_space2(size * 10);
+ test_reserved_space2(size * 10 + size / 2);
+ }
+
+ static void test_reserved_space3() {
+ size_t ag = os::vm_allocation_granularity();
+
+ test_reserved_space3(ag, ag , false);
+ test_reserved_space3(ag * 2, ag , false);
+ test_reserved_space3(ag * 3, ag , false);
+ test_reserved_space3(ag * 2, ag * 2, false);
+ test_reserved_space3(ag * 4, ag * 2, false);
+ test_reserved_space3(ag * 8, ag * 2, false);
+ test_reserved_space3(ag * 4, ag * 4, false);
+ test_reserved_space3(ag * 8, ag * 4, false);
+ test_reserved_space3(ag * 16, ag * 4, false);
+
+ if (UseLargePages) {
+ size_t lp = os::large_page_size();
+
+ // Without large pages
+ test_reserved_space3(lp, ag * 4, false);
+ test_reserved_space3(lp * 2, ag * 4, false);
+ test_reserved_space3(lp * 4, ag * 4, false);
+ test_reserved_space3(lp, lp , false);
+ test_reserved_space3(lp * 2, lp , false);
+ test_reserved_space3(lp * 3, lp , false);
+ test_reserved_space3(lp * 2, lp * 2, false);
+ test_reserved_space3(lp * 4, lp * 2, false);
+ test_reserved_space3(lp * 8, lp * 2, false);
+
+ // With large pages
+ test_reserved_space3(lp, ag * 4 , true);
+ test_reserved_space3(lp * 2, ag * 4, true);
+ test_reserved_space3(lp * 4, ag * 4, true);
+ test_reserved_space3(lp, lp , true);
+ test_reserved_space3(lp * 2, lp , true);
+ test_reserved_space3(lp * 3, lp , true);
+ test_reserved_space3(lp * 2, lp * 2, true);
+ test_reserved_space3(lp * 4, lp * 2, true);
+ test_reserved_space3(lp * 8, lp * 2, true);
+ }
+ }
+
+ static void test_reserved_space() {
+ test_reserved_space1();
+ test_reserved_space2();
+ test_reserved_space3();
+ }
+};
+
+void TestReservedSpace_test() {
+ TestReservedSpace::test_reserved_space();
+}
+
+#endif // PRODUCT
+
#endif
--- ./hotspot/src/share/vm/runtime/virtualspace.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/virtualspace.hpp Wed May 07 19:26:16 2014 -0700
@@ -90,6 +90,7 @@
public:
// Constructor
+ ReservedSpace();
ReservedSpace(size_t size);
ReservedSpace(size_t size, size_t alignment, bool large,
char* requested_address = NULL,
--- ./hotspot/src/share/vm/runtime/vmThread.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/vmThread.cpp Wed May 07 19:26:16 2014 -0700
@@ -305,7 +305,7 @@
os::check_heap();
// Silent verification so as not to pollute normal output,
// unless we really asked for it.
- Universe::verify(!(PrintGCDetails || Verbose));
+ Universe::verify(!(PrintGCDetails || Verbose) || VerifySilently);
}
CompileBroker::set_should_block();
--- ./hotspot/src/share/vm/runtime/vm_operations.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/vm_operations.cpp Wed May 07 19:26:16 2014 -0700
@@ -189,7 +189,8 @@
}
void VM_Verify::doit() {
- Universe::verify();
+ Universe::heap()->prepare_for_verify();
+ Universe::verify(_silent);
}
bool VM_PrintThreads::doit_prologue() {
--- ./hotspot/src/share/vm/runtime/vm_operations.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/runtime/vm_operations.hpp Wed May 07 19:26:16 2014 -0700
@@ -303,9 +303,9 @@
class VM_Verify: public VM_Operation {
private:
- KlassHandle _dependee;
+ bool _silent;
public:
- VM_Verify() {}
+ VM_Verify(bool silent = VerifySilently) : _silent(silent) {}
VMOp_Type type() const { return VMOp_Verify; }
void doit();
};
--- ./hotspot/src/share/vm/services/attachListener.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/services/attachListener.cpp Wed May 07 19:26:16 2014 -0700
@@ -282,6 +282,20 @@
return JNI_ERR;
}
}
+
+ if (strncmp(name, "MaxHeapFreeRatio", 17) == 0) {
+ FormatBuffer<80> err_msg("");
+ if (!Arguments::verify_MaxHeapFreeRatio(err_msg, value)) {
+ out->print_cr(err_msg.buffer());
+ return JNI_ERR;
+ }
+ } else if (strncmp(name, "MinHeapFreeRatio", 17) == 0) {
+ FormatBuffer<80> err_msg("");
+ if (!Arguments::verify_MinHeapFreeRatio(err_msg, value)) {
+ out->print_cr(err_msg.buffer());
+ return JNI_ERR;
+ }
+ }
bool res = CommandLineFlags::uintxAtPut((char*)name, &value, ATTACH_ON_DEMAND);
if (! res) {
out->print_cr("setting flag %s failed", name);
@@ -470,7 +484,17 @@
vmSymbols::threadgroup_string_void_signature(),
thread_group,
string,
- CHECK);
+ THREAD);
+
+ if (HAS_PENDING_EXCEPTION) {
+ tty->print_cr("Exception in VM (AttachListener::init) : ");
+ java_lang_Throwable::print(PENDING_EXCEPTION, tty);
+ tty->cr();
+
+ CLEAR_PENDING_EXCEPTION;
+
+ return;
+ }
KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass());
JavaCalls::call_special(&result,
@@ -479,7 +503,17 @@
vmSymbols::add_method_name(),
vmSymbols::thread_void_signature(),
thread_oop, // ARG 1
- CHECK);
+ THREAD);
+
+ if (HAS_PENDING_EXCEPTION) {
+ tty->print_cr("Exception in VM (AttachListener::init) : ");
+ java_lang_Throwable::print(PENDING_EXCEPTION, tty);
+ tty->cr();
+
+ CLEAR_PENDING_EXCEPTION;
+
+ return;
+ }
{ MutexLocker mu(Threads_lock);
JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry);
--- ./hotspot/src/share/vm/services/management.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/services/management.cpp Wed May 07 19:26:16 2014 -0700
@@ -851,8 +851,6 @@
total_used += u.used();
total_committed += u.committed();
- // if any one of the memory pool has undefined init_size or max_size,
- // set it to -1
if (u.init_size() == (size_t)-1) {
has_undefined_init_size = true;
}
@@ -869,6 +867,15 @@
}
}
+ // if any one of the memory pool has undefined init_size or max_size,
+ // set it to -1
+ if (has_undefined_init_size) {
+ total_init = (size_t)-1;
+ }
+ if (has_undefined_max_size) {
+ total_max = (size_t)-1;
+ }
+
// In our current implementation, we make sure that all non-heap
// pools have defined init and max sizes. Heap pools do not matter,
// as we never use total_init and total_max for them.
@@ -1793,6 +1800,18 @@
succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT);
} else if (flag->is_uintx()) {
uintx uvalue = (uintx)new_value.j;
+
+ if (strncmp(name, "MaxHeapFreeRatio", 17) == 0) {
+ FormatBuffer<80> err_msg("");
+ if (!Arguments::verify_MaxHeapFreeRatio(err_msg, uvalue)) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), err_msg.buffer());
+ }
+ } else if (strncmp(name, "MinHeapFreeRatio", 17) == 0) {
+ FormatBuffer<80> err_msg("");
+ if (!Arguments::verify_MinHeapFreeRatio(err_msg, uvalue)) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), err_msg.buffer());
+ }
+ }
succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT);
} else if (flag->is_uint64_t()) {
uint64_t uvalue = (uint64_t)new_value.j;
--- ./hotspot/src/share/vm/services/memTracker.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/services/memTracker.hpp Wed May 07 19:26:16 2014 -0700
@@ -302,6 +302,13 @@
}
}
+ static inline void record_virtual_memory_release(address addr, size_t size,
+ Thread* thread = NULL) {
+ if (is_on()) {
+ Tracker tkr(Tracker::Release, thread);
+ tkr.record(addr, size);
+ }
+ }
// record memory type on virtual memory base address
static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
--- ./hotspot/src/share/vm/trace/noTraceBackend.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/noTraceBackend.hpp Wed May 07 19:26:16 2014 -0700
@@ -25,9 +25,7 @@
#define SHARE_VM_TRACE_NOTRACEBACKEND_HPP
#include "prims/jni.h"
-
-typedef jlong TracingTime;
-typedef jlong RelativeTracingTime;
+#include "trace/traceTime.hpp"
class NoTraceBackend {
public:
@@ -44,5 +42,3 @@
typedef NoTraceBackend Tracing;
#endif
-
-
--- ./hotspot/src/share/vm/trace/trace.xml Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/trace.xml Wed May 07 19:26:16 2014 -0700
@@ -169,8 +169,8 @@
-
-
+
+
class TraceEvent : public StackObj {
- protected:
- jlong _startTime;
- jlong _endTime;
-
private:
bool _started;
#ifdef ASSERT
@@ -52,6 +49,18 @@
bool _ignore_check;
#endif
+ protected:
+ jlong _startTime;
+ jlong _endTime;
+
+ void set_starttime(const TracingTime& time) {
+ _startTime = time;
+ }
+
+ void set_endtime(const TracingTime& time) {
+ _endTime = time;
+ }
+
public:
TraceEvent(EventStartTime timing=TIMED) :
_startTime(0),
@@ -90,7 +99,7 @@
return;
}
if (_endTime == 0) {
- static_cast(this)->set_endtime(Tracing::time());
+ static_cast(this)->set_endtime(Tracing::time());
}
if (static_cast(this)->should_write()) {
static_cast(this)->writeEvent();
@@ -98,12 +107,12 @@
set_commited();
}
- void set_starttime(jlong time) {
- _startTime = time;
+ void set_starttime(const Ticks& time) {
+ _startTime = time.value();
}
- void set_endtime(jlong time) {
- _endTime = time;
+ void set_endtime(const Ticks& time) {
+ _endTime = time.value();
}
TraceEventId id() const {
--- ./hotspot/src/share/vm/trace/traceEventClasses.xsl Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/traceEventClasses.xsl Wed May 07 19:26:16 2014 -0700
@@ -1,6 +1,6 @@
+
-
@@ -40,6 +40,7 @@
#include "runtime/handles.inline.hpp"
#include "tracefiles/traceTypes.hpp"
#include "trace/traceEvent.hpp"
+#include "utilities/ticks.hpp"
#if INCLUDE_TRACE
@@ -54,8 +55,8 @@
class TraceEvent {
public:
TraceEvent() {}
- void set_starttime(jlong time) const {}
- void set_endtime(jlong time) const {}
+ void set_starttime(const Ticks& time) {}
+ void set_endtime(const Ticks& time) {}
bool should_commit() const { return false; }
void commit() const {}
};
@@ -174,20 +175,21 @@
#if INCLUDE_TRACE
-
+
#else
-
+
#endif
-
+
#if INCLUDE_TRACE
-
+
#else
-
+
#endif
+
@@ -227,7 +229,17 @@
-
+
+
+
+
+
+
+
+
+
+
+
ts.print(", ");
--- ./hotspot/src/share/vm/trace/traceEventIds.xsl Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/traceEventIds.xsl Wed May 07 19:26:16 2014 -0700
@@ -1,6 +1,6 @@
+
-
--- ./hotspot/src/share/vm/trace/traceMacros.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/traceMacros.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, 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
--- ./hotspot/src/share/vm/trace/traceTime.hpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/traceTime.hpp Wed May 07 19:26:16 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, 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
@@ -28,6 +28,5 @@
#include "prims/jni.h"
typedef jlong TracingTime;
-typedef jlong RelativeTracingTime;
-#endif
+#endif // SHARE_VM_TRACE_TRACETIME_HPP
--- ./hotspot/src/share/vm/trace/traceTypes.xsl Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/traceTypes.xsl Wed May 07 19:26:16 2014 -0700
@@ -1,6 +1,6 @@
+
-
@@ -32,11 +32,13 @@
#ifndef TRACEFILES_JFRTYPES_HPP
#define TRACEFILES_JFRTYPES_HPP
+
+#include "oops/klassOop.hpp"
+#include "oops/methodOop.hpp"
+#include "oops/symbol.hpp"
#include "trace/traceDataTypes.hpp"
#include "utilities/globalDefinitions.hpp"
-#include "oops/symbol.hpp"
-#include "oops/klassOop.hpp"
-#include "oops/methodOop.hpp"
+#include "utilities/ticks.hpp"
enum JVMContentType {
_not_a_content_type = (JVM_CONTENT_TYPES_START - 1),
--- ./hotspot/src/share/vm/trace/tracetypes.xml Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/trace/tracetypes.xml Wed May 07 19:26:16 2014 -0700
@@ -249,13 +249,13 @@
-
+
+ type="Ticks" sizeop="sizeof(s8)"/>
-
-
+
+
= 0; i--) {
+ if (_data[i] == elem) return i;
+ }
+ return -1;
+ }
+
int find(void* token, bool f(void*, E)) const {
for (int i = 0; i < _len; i++) {
if (f(token, _data[i])) return i;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/src/share/vm/utilities/ticks.cpp Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "utilities/ticks.inline.hpp"
+
+#ifdef ASSERT
+ const jlong Ticks::invalid_time_stamp = -2; // 0xFFFF FFFF`FFFF FFFE
+#endif
+
+void Ticks::stamp() {
+ _stamp_ticks = os::elapsed_counter();
+}
+
+const Ticks Ticks::now() {
+ Ticks t;
+ t.stamp();
+ return t;
+}
+
+Tickspan::Tickspan(const Ticks& end, const Ticks& start) {
+ assert(end.value() != Ticks::invalid_time_stamp, "end is unstamped!");
+ assert(start.value() != Ticks::invalid_time_stamp, "start is unstamped!");
+
+ assert(end >= start, "negative time!");
+
+ _span_ticks = end.value() - start.value();
+}
+
+template
+static ReturnType time_conversion(const Tickspan& span, TicksToTimeHelper::Unit unit) {
+ assert(TicksToTimeHelper::SECONDS == unit ||
+ TicksToTimeHelper::MILLISECONDS == unit, "invalid unit!");
+
+ ReturnType frequency_per_unit = (ReturnType)os::elapsed_frequency() / (ReturnType)unit;
+
+ return (ReturnType) ((ReturnType)span.value() / frequency_per_unit);
+}
+
+double TicksToTimeHelper::seconds(const Tickspan& span) {
+ return time_conversion(span, SECONDS);
+}
+
+jlong TicksToTimeHelper::milliseconds(const Tickspan& span) {
+ return time_conversion(span, MILLISECONDS);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/src/share/vm/utilities/ticks.hpp Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_TICKS_HPP
+#define SHARE_VM_UTILITIES_TICKS_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class Ticks;
+
+class Tickspan VALUE_OBJ_CLASS_SPEC {
+ friend class Ticks;
+ friend Tickspan operator-(const Ticks& end, const Ticks& start);
+
+ private:
+ jlong _span_ticks;
+
+ Tickspan(const Ticks& end, const Ticks& start);
+
+ public:
+ Tickspan() : _span_ticks(0) {}
+
+ Tickspan& operator+=(const Tickspan& rhs) {
+ _span_ticks += rhs._span_ticks;
+ return *this;
+ }
+
+ jlong value() const {
+ return _span_ticks;
+ }
+
+};
+
+class Ticks VALUE_OBJ_CLASS_SPEC {
+ private:
+ jlong _stamp_ticks;
+
+ public:
+ Ticks() : _stamp_ticks(0) {
+ assert((_stamp_ticks = invalid_time_stamp) == invalid_time_stamp,
+ "initial unstamped time value assignment");
+ }
+
+ Ticks& operator+=(const Tickspan& span) {
+ _stamp_ticks += span.value();
+ return *this;
+ }
+
+ Ticks& operator-=(const Tickspan& span) {
+ _stamp_ticks -= span.value();
+ return *this;
+ }
+
+ void stamp();
+
+ jlong value() const {
+ return _stamp_ticks;
+ }
+
+ static const Ticks now();
+
+#ifdef ASSERT
+ static const jlong invalid_time_stamp;
+#endif
+
+#ifndef PRODUCT
+ // only for internal use by GC VM tests
+ friend class TimePartitionPhasesIteratorTest;
+ friend class GCTimerTest;
+
+ private:
+ // implicit type conversion
+ Ticks(int ticks) : _stamp_ticks(ticks) {}
+
+#endif // !PRODUCT
+
+};
+
+class TicksToTimeHelper : public AllStatic {
+ public:
+ enum Unit {
+ SECONDS = 1,
+ MILLISECONDS = 1000
+ };
+ static double seconds(const Tickspan& span);
+ static jlong milliseconds(const Tickspan& span);
+};
+
+#endif // SHARE_VM_UTILITIES_TICKS_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/src/share/vm/utilities/ticks.inline.hpp Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_TICKS_INLINE_HPP
+#define SHARE_VM_UTILITIES_TICKS_INLINE_HPP
+
+#include "utilities/ticks.hpp"
+
+inline Tickspan operator+(Tickspan lhs, const Tickspan& rhs) {
+ lhs += rhs;
+ return lhs;
+}
+
+inline bool operator==(const Tickspan& lhs, const Tickspan& rhs) {
+ return lhs.value() == rhs.value();
+}
+
+inline bool operator!=(const Tickspan& lhs, const Tickspan& rhs) {
+ return !operator==(lhs,rhs);
+}
+
+inline bool operator<(const Tickspan& lhs, const Tickspan& rhs) {
+ return lhs.value() < rhs.value();
+}
+
+inline bool operator>(const Tickspan& lhs, const Tickspan& rhs) {
+ return operator<(rhs,lhs);
+}
+
+inline bool operator<=(const Tickspan& lhs, const Tickspan& rhs) {
+ return !operator>(lhs,rhs);
+}
+
+inline bool operator>=(const Tickspan& lhs, const Tickspan& rhs) {
+ return !operator<(lhs,rhs);
+}
+
+inline Ticks operator+(Ticks lhs, const Tickspan& span) {
+ lhs += span;
+ return lhs;
+}
+
+inline Ticks operator-(Ticks lhs, const Tickspan& span) {
+ lhs -= span;
+ return lhs;
+}
+
+inline Tickspan operator-(const Ticks& end, const Ticks& start) {
+ return Tickspan(end, start);
+}
+
+inline bool operator==(const Ticks& lhs, const Ticks& rhs) {
+ return lhs.value() == rhs.value();
+}
+
+inline bool operator!=(const Ticks& lhs, const Ticks& rhs) {
+ return !operator==(lhs,rhs);
+}
+
+inline bool operator<(const Ticks& lhs, const Ticks& rhs) {
+ return lhs.value() < rhs.value();
+}
+
+inline bool operator>(const Ticks& lhs, const Ticks& rhs) {
+ return operator<(rhs,lhs);
+}
+
+inline bool operator<=(const Ticks& lhs, const Ticks& rhs) {
+ return !operator>(lhs,rhs);
+}
+
+inline bool operator>=(const Ticks& lhs, const Ticks& rhs) {
+ return !operator<(lhs,rhs);
+}
+
+#endif // SHARE_VM_UTILITIES_TICKS_INLINE_HPP
--- ./hotspot/src/share/vm/utilities/vmError.cpp Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/src/share/vm/utilities/vmError.cpp Wed May 07 19:26:16 2014 -0700
@@ -583,6 +583,13 @@
while (count++ < StackPrintLimit) {
fr.print_on_error(st, buf, sizeof(buf));
st->cr();
+ // Compiled code may use EBP register on x86 so it looks like
+ // non-walkable C frame. Use frame.sender() for java frames.
+ if (_thread && _thread->is_Java_thread() && fr.is_java_frame()) {
+ RegisterMap map((JavaThread*)_thread, false); // No update
+ fr = fr.sender(&map);
+ continue;
+ }
if (os::is_first_C_frame(&fr)) break;
fr = os::get_sender_for_C_frame(&fr);
}
@@ -698,18 +705,6 @@
st->cr();
}
-#ifdef LINUX
- STEP(193, "(printing large pages allocation errors)")
-
- if (_verbose) {
- jint largepage_failures = os::Linux::num_largepage_commit_fails;
- if (largepage_failures > 0) {
- st->print_cr("Large page allocation failures have occurred " INT32_FORMAT " times", largepage_failures);
- st->cr();
- }
- }
-#endif
-
STEP(195, "(printing code cache information)" )
if (_verbose && Universe::is_fully_initialized()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/compiler/8004051/Test8004051.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8004051
+ * @bug 8005722
+ * @summary assert(_oprs_len[mode] < maxNumberOfOperands) failed: array overflow
+ *
+ * @run main/othervm -Xcomp -client Test8004051
+ */
+
+public class Test8004051 {
+ public static void main(String[] argv) {
+ Object o = new Object();
+ fillPrimRect(1.1f, 1.2f, 1.3f, 1.4f,
+ o, o,
+ 1.5f, 1.6f, 1.7f, 1.8f,
+ 2.0f, 2.1f, 2.2f, 2.3f,
+ 2.4f, 2.5f, 2.6f, 2.7f,
+ 100, 101);
+ System.out.println("Test passed, test did not assert");
+ }
+
+ static boolean fillPrimRect(float x, float y, float w, float h,
+ Object rectTex, Object wrapTex,
+ float bx, float by, float bw, float bh,
+ float f1, float f2, float f3, float f4,
+ float f5, float f6, float f7, float f8,
+ int i1, int i2 ) {
+ System.out.println(x + " " + y + " " + w + " " + h + " " +
+ bx + " " + by + " " + bw + " " + bh);
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/compiler/codegen/LoadWithMask.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8032207
+ * @summary Invalid node sizing for loadUS2L_immI16 and loadI2L_immI
+ * @run main/othervm -server -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,LoadWithMask.foo LoadWithMask
+ *
+ */
+public class LoadWithMask {
+ static int x[] = new int[1];
+ static long foo() {
+ return x[0] & 0xfff0ffff;
+ }
+
+ public static void main(String[] args) {
+ x[0] = -1;
+ long l = 0;
+ for (int i = 0; i < 100000; ++i) {
+ l = foo();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/compiler/codegen/LoadWithMask2.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8031743
+ * @summary loadI2L_immI broken for negative memory values
+ * @run main/othervm -server -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,*.foo* LoadWithMask2
+ *
+ */
+public class LoadWithMask2 {
+ static int x;
+ static long foo1() {
+ return x & 0xfffffffe;
+ }
+ static long foo2() {
+ return x & 0xff000000;
+ }
+ static long foo3() {
+ return x & 0x8abcdef1;
+ }
+
+ public static void main(String[] args) {
+ x = -1;
+ long l = 0;
+ for (int i = 0; i < 100000; ++i) {
+ l = foo1() & foo2() & foo3();
+ }
+ if (l > 0) {
+ System.out.println("FAILED");
+ System.exit(97);
+ }
+ System.out.println("PASSED");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/compiler/gcbarriers/G1CrashTest.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8023472
+ * @summary C2 optimization breaks with G1
+ *
+ * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -Dcount=100000 G1CrashTest
+ *
+ * @author pbiswal@palantir.com
+ */
+
+public class G1CrashTest {
+ static Object[] set = new Object[11];
+
+ public static void main(String[] args) throws InterruptedException {
+ for (int j = 0; j < Integer.getInteger("count"); j++) {
+ Object key = new Object();
+ insertKey(key);
+ if (j > set.length / 2) {
+ Object[] oldKeys = set;
+ set = new Object[2 * set.length - 1];
+ for (Object o : oldKeys) {
+ if (o != null)
+ insertKey(o);
+ }
+ }
+ }
+ }
+
+ static void insertKey(Object key) {
+ int hash = key.hashCode() & 0x7fffffff;
+ int index = hash % set.length;
+ Object cur = set[index];
+ if (cur == null)
+ set[index] = key;
+ else
+ insertKeyRehash(key, index, hash, cur);
+ }
+
+ static void insertKeyRehash(Object key, int index, int hash, Object cur) {
+ int loopIndex = index;
+ int firstRemoved = -1;
+ do {
+ if (cur == "dead")
+ firstRemoved = 1;
+ index--;
+ if (index < 0)
+ index += set.length;
+ cur = set[index];
+ if (cur == null) {
+ if (firstRemoved != -1)
+ set[firstRemoved] = "dead";
+ else
+ set[index] = key;
+ return;
+ }
+ } while (index != loopIndex);
+ if (firstRemoved != -1)
+ set[firstRemoved] = null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/compiler/print/PrintInlining.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8022585
+ * @summary VM crashes when ran with -XX:+PrintInlining
+ * @run main/othervm -Xcomp -XX:+PrintInlining PrintInlining
+ *
+ */
+
+public class PrintInlining {
+ public static void main(String[] args) {
+ System.out.println("Passed");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/compiler/reflection/ArrayNewInstanceOfVoid.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8029366
+ * @summary ShouldNotReachHere error when creating an array with component type of void
+ */
+
+public class ArrayNewInstanceOfVoid {
+ public static void main(String[] args) {
+ for (int i = 0; i < 100_000; i++) {
+ test();
+ }
+ }
+
+ private static void test() {
+ try {
+ java.lang.reflect.Array.newInstance(void.class, 2);
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/compiler/regalloc/C1ObjectSpillInLogicOp.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8027751
+ * @summary C1 crashes generating G1 post-barrier in Unsafe.getAndSetObject() intrinsic because of the new value spill
+ * @run main/othervm -XX:+UseG1GC C1ObjectSpillInLogicOp
+ *
+ * G1 barriers use logical operators (xor) on T_OBJECT mixed with T_LONG or T_INT.
+ * The current implementation of logical operations on x86 in C1 doesn't allow for long operands to be on stack.
+ * There is a special code in the register allocator that forces long arguments in registers on x86. However T_OBJECT
+ * can be spilled just fine, and in that case the xor emission will fail.
+ */
+
+import java.util.concurrent.atomic.*;
+public class C1ObjectSpillInLogicOp {
+ static public void main(String[] args) {
+ AtomicReferenceArray x = new AtomicReferenceArray(128);
+ Integer y = new Integer(0);
+ for (int i = 0; i < 50000; i++) {
+ x.getAndSet(i % x.length(), y);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/8000311/Test8000311.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test Test8000311
+ * @key gc
+ * @bug 8000311
+ * @summary G1: ParallelGCThreads==0 broken
+ * @run main/othervm -XX:+UseG1GC -XX:ParallelGCThreads=0 -XX:+ResizePLAB -XX:+ExplicitGCInvokesConcurrent Test8000311
+ * @author filipp.zhinkin@oracle.com
+ */
+
+import java.util.*;
+
+public class Test8000311 {
+ public static void main(String args[]) {
+ for(int i = 0; i<100; i++) {
+ byte[] garbage = new byte[1000];
+ System.gc();
+ }
+ }
+}
--- ./hotspot/test/gc/TestVerifyBeforeGCDuringStartup.java Tue Mar 18 12:31:20 2014 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test TestVerifyBeforeGCDuringStartup.java
- * @key gc
- * @bug 8010463
- * @summary Simple test run with -XX:+VerifyBeforeGC -XX:-UseTLAB to verify 8010463
- * @library /testlibrary
- */
-
-import com.oracle.java.testlibrary.OutputAnalyzer;
-import com.oracle.java.testlibrary.ProcessTools;
-
-public class TestVerifyBeforeGCDuringStartup {
- public static void main(String args[]) throws Exception {
- ProcessBuilder pb =
- ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"),
- "-XX:-UseTLAB",
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:+VerifyBeforeGC", "-version");
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("[Verifying");
- output.shouldHaveExitValue(0);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/TestVerifyDuringStartup.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test TestVerifyDuringStartup.java
+ * @key gc
+ * @bug 8010463
+ * @summary Simple test run with -XX:+VerifyDuringStartup -XX:-UseTLAB to verify 8010463
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestVerifyDuringStartup {
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb =
+ ProcessTools.createJavaProcessBuilder(System.getProperty("test.vm.opts"),
+ "-XX:-UseTLAB",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+VerifyDuringStartup", "-version");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("[Verifying");
+ output.shouldHaveExitValue(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/TestVerifySilently.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test TestVerifySilently.java
+ * @key gc
+ * @bug 8032771
+ * @summary Test silent verification.
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+import java.util.ArrayList;
+import java.util.Collections;
+
+class RunSystemGC {
+ public static void main(String args[]) throws Exception {
+ System.gc();
+ }
+}
+
+
+public class TestVerifySilently {
+ private static String[] getTestJavaOpts() {
+ String testVmOptsStr = System.getProperty("test.java.opts");
+ if (!testVmOptsStr.isEmpty()) {
+ return testVmOptsStr.split(" ");
+ } else {
+ return new String[] {};
+ }
+ }
+
+ private static OutputAnalyzer runTest(boolean verifySilently) throws Exception {
+ ArrayList vmOpts = new ArrayList();
+
+ Collections.addAll(vmOpts, getTestJavaOpts());
+ Collections.addAll(vmOpts, new String[] {"-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+VerifyDuringStartup",
+ "-XX:+VerifyBeforeGC",
+ "-XX:+VerifyAfterGC",
+ "-XX:" + (verifySilently ? "+":"-") + "VerifySilently",
+ RunSystemGC.class.getName()});
+ ProcessBuilder pb =
+ ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ System.out.println("Output:\n" + output.getOutput());
+ return output;
+ }
+
+
+ public static void main(String args[]) throws Exception {
+
+ OutputAnalyzer output;
+
+ output = runTest(false);
+ output.shouldContain("[Verifying");
+ output.shouldHaveExitValue(0);
+
+ output = runTest(true);
+ output.shouldNotContain("[Verifying");
+ output.shouldHaveExitValue(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test TestDynMaxHeapFreeRatio
+ * @bug 8028391
+ * @summary Verify that MaxHeapFreeRatio flag is manageable
+ * @library /testlibrary
+ * @run main TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 -XX:-UseAdaptiveSizePolicy TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMaxHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMaxHeapFreeRatio
+ */
+import com.oracle.java.testlibrary.TestDynamicVMOption;
+import com.oracle.java.testlibrary.DynamicVMOptionChecker;
+
+public class TestDynMaxHeapFreeRatio extends TestDynamicVMOption {
+
+ public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
+ public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
+
+ public TestDynMaxHeapFreeRatio() {
+ super(MaxFreeRatioFlagName);
+ }
+
+ public void test() {
+
+ int minHeapFreeValue = DynamicVMOptionChecker.getIntValue(MinFreeRatioFlagName);
+ System.out.println(MinFreeRatioFlagName + " = " + minHeapFreeValue);
+
+ testPercentageValues();
+
+ checkInvalidValue(Integer.toString(minHeapFreeValue - 1));
+ checkValidValue(Integer.toString(minHeapFreeValue));
+ checkValidValue("100");
+ }
+
+ public static void main(String args[]) throws Exception {
+ new TestDynMaxHeapFreeRatio().test();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test TestDynMinHeapFreeRatio
+ * @bug 8028391
+ * @summary Verify that MinHeapFreeRatio flag is manageable
+ * @library /testlibrary
+ * @run main TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 -XX:-UseAdaptiveSizePolicy TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=50 TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMinHeapFreeRatio
+ * @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMinHeapFreeRatio
+ */
+import com.oracle.java.testlibrary.TestDynamicVMOption;
+import com.oracle.java.testlibrary.DynamicVMOptionChecker;
+
+public class TestDynMinHeapFreeRatio extends TestDynamicVMOption {
+
+ public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
+ public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
+
+ public TestDynMinHeapFreeRatio() {
+ super(MinFreeRatioFlagName);
+ }
+
+ public void test() {
+ int maxHeapFreeValue = DynamicVMOptionChecker.getIntValue(MaxFreeRatioFlagName);
+ System.out.println(MaxFreeRatioFlagName + " = " + maxHeapFreeValue);
+
+ testPercentageValues();
+
+ checkInvalidValue(Integer.toString(maxHeapFreeValue + 1));
+ checkValidValue(Integer.toString(maxHeapFreeValue));
+ checkValidValue("0");
+ }
+
+ public static void main(String args[]) throws Exception {
+ new TestDynMinHeapFreeRatio().test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @key regression
+ * @key gc
+ * @bug 8027756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestHumongousCodeCacheRoots
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @summary Humongous objects may have references from the code cache
+ * @run main TestHumongousCodeCacheRoots
+*/
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class TestHumongousCodeCacheRootsHelper {
+
+ static final int n = 1000000;
+ static final int[] AA = new int[n];
+ static final int[] BB = new int[n];
+
+ public static void main(String args[]) throws Exception {
+ // do some work so that the compiler compiles this method, inlining the
+ // reference to the integer array (which is a humonguous object) into
+ // the code cache.
+ for(int i = 0; i < n; i++) {
+ AA[i] = 0;
+ BB[i] = 0;
+ }
+ // trigger a GC that checks that the verification code allows humongous
+ // objects with code cache roots; objects should be all live here.
+ System.gc();
+
+ // deoptimize everyhing: this should make all compiled code zombies.
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ wb.deoptimizeAll();
+
+ // trigger a GC that checks that the verification code allows humongous
+ // objects with code cache roots; objects should be all live here.
+ System.gc();
+
+ // wait a little for the code cache sweeper to try to clean up zombie nmethods
+ // and unregister the code roots.
+ try { Thread.sleep(5000); } catch (InterruptedException ex) { }
+
+ // do some work on the arrays to make sure that they need to be live after the GCs
+ for(int i = 0; i < n; i++) {
+ AA[i] = 1;
+ BB[i] = 10;
+ }
+
+ System.out.println();
+ }
+}
+
+public class TestHumongousCodeCacheRoots {
+
+ /**
+ * Executes a class in a new VM process with the given parameters.
+ * @param vmargs Arguments to the VM to run
+ * @param classname Name of the class to run
+ * @param arguments Arguments to the class
+ * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string
+ * @return The OutputAnalyzer with the results for the invocation.
+ */
+ public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception {
+ ArrayList finalargs = new ArrayList();
+
+ String[] whiteboxOpts = new String[] {
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
+ "-cp", System.getProperty("java.class.path"),
+ };
+
+ if (useTestDotJavaDotOpts) {
+ // System.getProperty("test.java.opts") is '' if no options is set,
+ // we need to skip such a result
+ String[] externalVMOpts = new String[0];
+ if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) {
+ externalVMOpts = System.getProperty("test.java.opts").split(" ");
+ }
+ finalargs.addAll(Arrays.asList(externalVMOpts));
+ }
+
+ finalargs.addAll(Arrays.asList(vmargs));
+ finalargs.addAll(Arrays.asList(whiteboxOpts));
+ finalargs.add(classname);
+ finalargs.addAll(Arrays.asList(arguments));
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ return output;
+ }
+
+ public static void runTest(String compiler, String[] other) throws Exception {
+ ArrayList joined = new ArrayList();
+ joined.add(compiler);
+ joined.addAll(Arrays.asList(other));
+ runWhiteBoxTest(joined.toArray(new String[0]), TestHumongousCodeCacheRootsHelper.class.getName(),
+ new String[] {}, false);
+ }
+
+ public static void main(String[] args) throws Exception {
+ final String[] baseArguments = new String[] {
+ "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1M", "-Xmx100M", // make sure we get a humongous region
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:InitiatingHeapOccupancyPercent=1", // strong code root marking
+ "-XX:+G1VerifyHeapRegionCodeRoots", "-XX:+VerifyAfterGC", // make sure that verification is run
+ "-XX:NmethodSweepFraction=1", "-XX:NmethodSweepCheckInterval=1", // make the code cache sweep more predictable
+ };
+ runTest("-client", baseArguments);
+ runTest("-server", baseArguments);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/g1/TestPrintRegionRememberedSetInfo.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test TestPrintRegionRememberedSetInfo
+ * @key gc
+ * @bug 8014240
+ * @summary Test output of G1PrintRegionRememberedSetInfo
+ * @library /testlibrary
+ * @run main TestPrintRegionRememberedSetInfo
+ * @author thomas.schatzl@oracle.com
+ */
+
+import com.oracle.java.testlibrary.*;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class RunAndWaitForMarking {
+ public static void main(String[] args) {
+ System.gc();
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ }
+ }
+}
+
+public class TestPrintRegionRememberedSetInfo {
+
+ public static String runTest(String arg) throws Exception {
+ ArrayList finalargs = new ArrayList();
+ String[] defaultArgs = new String[] {
+ "-XX:+UseG1GC",
+ "-Xmx10m",
+ "-XX:+ExplicitGCInvokesConcurrent",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+G1PrintRegionLivenessInfo",
+ "-XX:G1HeapRegionSize=1M",
+ "-XX:InitiatingHeapOccupancyPercent=0",
+ };
+
+ finalargs.addAll(Arrays.asList(defaultArgs));
+ finalargs.add(arg);
+
+ finalargs.add(RunAndWaitForMarking.class.getName());
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ String result = output.getStdout();
+ return result;
+ }
+
+ public static void main(String[] args) throws Exception {
+ String result;
+
+ result = runTest("-XX:+G1PrintRegionLivenessInfo");
+ // check that we got region statistics output
+ if (result.indexOf("PHASE") == -1) {
+ throw new RuntimeException("Unexpected output from -XX:+PrintRegionLivenessInfo found.");
+ }
+
+ result = runTest("-XX:-G1PrintRegionLivenessInfo");
+ if (result.indexOf("remset") != -1) {
+ throw new RuntimeException("Should find remembered set information in output.");
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/g1/TestSummarizeRSetStats.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestSummarizeRSetStats.java
+ * @bug 8013895
+ * @library /testlibrary
+ * @build TestSummarizeRSetStatsTools TestSummarizeRSetStats
+ * @summary Verify output of -XX:+G1SummarizeRSetStats
+ * @run main TestSummarizeRSetStats
+ *
+ * Test the output of G1SummarizeRSetStats in conjunction with G1SummarizeRSetStatsPeriod.
+ */
+
+public class TestSummarizeRSetStats {
+
+ public static void main(String[] args) throws Exception {
+ String result;
+
+ if (!TestSummarizeRSetStatsTools.testingG1GC()) {
+ return;
+ }
+
+ // no remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(null, 0);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0);
+
+ // no remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(null, 2);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0);
+
+ // no remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:G1SummarizeRSetStatsPeriod=1" }, 3);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0);
+
+ // single remembered set summary output at the end
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0);
+
+ // single remembered set summary output at the end
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 2);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0);
+
+ // single remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 0);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0);
+
+ // two times remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2);
+
+ // four times remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 3);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 6);
+
+ // three times remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=2" }, 3);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 4);
+
+ // single remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=100" }, 3);
+ TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/g1/TestSummarizeRSetStatsPerRegion.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestSummarizeRSetStatsPerRegion.java
+ * @bug 8014078
+ * @library /testlibrary
+ * @build TestSummarizeRSetStatsTools TestSummarizeRSetStatsPerRegion
+ * @summary Verify output of -XX:+G1SummarizeRSetStats in regards to per-region type output
+ * @run main TestSummarizeRSetStatsPerRegion
+ */
+
+import com.oracle.java.testlibrary.*;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class TestSummarizeRSetStatsPerRegion {
+
+ public static void main(String[] args) throws Exception {
+ String result;
+
+ if (!TestSummarizeRSetStatsTools.testingG1GC()) {
+ return;
+ }
+
+ // single remembered set summary output at the end
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0);
+ TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 0);
+
+ // two times remembered set summary output
+ result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1);
+ TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 2);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/g1/TestSummarizeRSetStatsThreads.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestSummarizeRSetStatsThreads
+ * @bug 8025441
+ * @summary Ensure that various values of worker threads/concurrent
+ * refinement threads do not crash the VM.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class TestSummarizeRSetStatsThreads {
+
+ private static void runTest(int refinementThreads, int workerThreads) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+G1SummarizeRSetStats",
+ "-XX:G1ConcRefinementThreads=" + refinementThreads,
+ "-XX:ParallelGCThreads=" + workerThreads,
+ "-version");
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ // check output to contain the string "Concurrent RS threads times (s)" followed by
+ // the correct number of values in the next line.
+
+ // a zero in refinement thread numbers indicates that the value in ParallelGCThreads should be used.
+ // Additionally use at least one thread.
+ int expectedNumRefinementThreads = refinementThreads == 0 ? workerThreads : refinementThreads;
+ expectedNumRefinementThreads = Math.max(1, expectedNumRefinementThreads);
+ // create the pattern made up of n copies of a floating point number pattern
+ String numberPattern = String.format("%0" + expectedNumRefinementThreads + "d", 0)
+ .replace("0", "\\s+\\d+\\.\\d+");
+ String pattern = "Concurrent RS threads times \\(s\\)$" + numberPattern + "$";
+ Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(output.getStdout());
+
+ if (!m.find()) {
+ throw new Exception("Could not find correct output for concurrent RS threads times in stdout," +
+ " should match the pattern \"" + pattern + "\", but stdout is \n" + output.getStdout());
+ }
+ output.shouldHaveExitValue(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (!TestSummarizeRSetStatsTools.testingG1GC()) {
+ return;
+ }
+ // different valid combinations of number of refinement and gc worker threads
+ runTest(0, 0);
+ runTest(0, 5);
+ runTest(5, 0);
+ runTest(10, 10);
+ runTest(1, 2);
+ runTest(4, 3);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Common helpers for TestSummarizeRSetStats* tests
+ */
+
+import sun.management.ManagementFactoryHelper;
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+
+import com.oracle.java.testlibrary.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.lang.Thread;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+class VerifySummaryOutput {
+ // 4M size, both are directly allocated into the old gen
+ static Object[] largeObject1 = new Object[1024 * 1024];
+ static Object[] largeObject2 = new Object[1024 * 1024];
+
+ static int[] temp;
+
+ public static void main(String[] args) {
+ // create some cross-references between these objects
+ for (int i = 0; i < largeObject1.length; i++) {
+ largeObject1[i] = largeObject2;
+ }
+
+ for (int i = 0; i < largeObject2.length; i++) {
+ largeObject2[i] = largeObject1;
+ }
+
+ int numGCs = Integer.parseInt(args[0]);
+
+ if (numGCs > 0) {
+ // try to force a minor collection: the young gen is 4M, the
+ // amount of data allocated below is roughly that (4*1024*1024 +
+ // some header data)
+ for (int i = 0; i < 1024 ; i++) {
+ temp = new int[1024];
+ }
+ }
+
+ for (int i = 0; i < numGCs - 1; i++) {
+ System.gc();
+ }
+ }
+}
+
+public class TestSummarizeRSetStatsTools {
+
+ // the VM is currently run using G1GC, i.e. trying to test G1 functionality.
+ public static boolean testingG1GC() {
+ HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
+
+ VMOption option = diagnostic.getVMOption("UseG1GC");
+ if (option.getValue().equals("false")) {
+ System.out.println("Skipping this test. It is only a G1 test.");
+ return false;
+ }
+ return true;
+ }
+
+ public static String runTest(String[] additionalArgs, int numGCs) throws Exception {
+ ArrayList finalargs = new ArrayList();
+ String[] defaultArgs = new String[] {
+ "-XX:+UseG1GC",
+ "-XX:+UseCompressedOops",
+ "-Xmn4m",
+ "-Xmx20m",
+ "-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking
+ "-XX:+PrintGC",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:G1HeapRegionSize=1M",
+ };
+
+ finalargs.addAll(Arrays.asList(defaultArgs));
+
+ if (additionalArgs != null) {
+ finalargs.addAll(Arrays.asList(additionalArgs));
+ }
+
+ finalargs.add(VerifySummaryOutput.class.getName());
+ finalargs.add(String.valueOf(numGCs));
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ output.shouldHaveExitValue(0);
+
+ String result = output.getStdout();
+ return result;
+ }
+
+ private static void checkCounts(int expected, int actual, String which) throws Exception {
+ if (expected != actual) {
+ throw new Exception("RSet summaries mention " + which + " regions an incorrect number of times. Expected " + expected + ", got " + actual);
+ }
+ }
+
+ public static void expectPerRegionRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception {
+ expectRSetSummaries(result, expectedCumulative, expectedPeriodic);
+ int actualYoung = result.split("Young regions").length - 1;
+ int actualHumonguous = result.split("Humonguous regions").length - 1;
+ int actualFree = result.split("Free regions").length - 1;
+ int actualOther = result.split("Old regions").length - 1;
+
+ // the strings we check for above are printed four times per summary
+ int expectedPerRegionTypeInfo = (expectedCumulative + expectedPeriodic) * 4;
+
+ checkCounts(expectedPerRegionTypeInfo, actualYoung, "Young");
+ checkCounts(expectedPerRegionTypeInfo, actualHumonguous, "Humonguous");
+ checkCounts(expectedPerRegionTypeInfo, actualFree, "Free");
+ checkCounts(expectedPerRegionTypeInfo, actualOther, "Old");
+ }
+
+ public static void expectRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception {
+ int actualTotal = result.split("concurrent refinement").length - 1;
+ int actualCumulative = result.split("Cumulative RS summary").length - 1;
+
+ if (expectedCumulative != actualCumulative) {
+ throw new Exception("Incorrect amount of RSet summaries at the end. Expected " + expectedCumulative + ", got " + actualCumulative);
+ }
+
+ if (expectedPeriodic != (actualTotal - actualCumulative)) {
+ throw new Exception("Incorrect amount of per-period RSet summaries at the end. Expected " + expectedPeriodic + ", got " + (actualTotal - actualCumulative));
+ }
+ }
+}
+
--- ./hotspot/test/runtime/6929067/Test6929067.sh Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/test/runtime/6929067/Test6929067.sh Wed May 07 19:26:16 2014 -0700
@@ -3,6 +3,7 @@
##
## @test Test6929067.sh
## @bug 6929067
+## @bug 8021296
## @summary Stack guard pages should be removed when thread is detached
## @compile T.java
## @run shell Test6929067.sh
@@ -21,6 +22,11 @@
OS=`uname -s`
case "$OS" in
Linux)
+ gcc_cmd=`which gcc`
+ if [ "x$gcc_cmd" == "x" ]; then
+ echo "WARNING: gcc not found. Cannot execute test." 2>&1
+ exit 0;
+ fi
NULL=/dev/null
PS=":"
FS="/"
@@ -119,10 +125,10 @@
# Check to ensure you have a /usr/lib/libpthread.so if you don't please look
# for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation.
-gcc -DLINUX ${COMP_FLAG} -o invoke \
- -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \
- -L${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE} \
- -ljvm -lpthread invoke.c
+$gcc_cmd -DLINUX ${COMP_FLAG} -o invoke \
+ -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \
+ -L${COMPILEJAVA}/jre/lib/${ARCH}/${VMTYPE} \
+ -ljvm -lpthread invoke.c
./invoke
exit $?
--- ./hotspot/test/runtime/7107135/Test7107135.sh Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/test/runtime/7107135/Test7107135.sh Wed May 07 19:26:16 2014 -0700
@@ -27,6 +27,7 @@
##
## @test Test7107135.sh
## @bug 7107135
+## @bug 8021296
## @summary Stack guard pages lost after loading library with executable stack.
## @run shell Test7107135.sh
##
@@ -45,6 +46,11 @@
case "$OS" in
Linux)
echo "Testing on Linux"
+ gcc_cmd=`which gcc`
+ if [ "x$gcc_cmd" == "x" ]; then
+ echo "WARNING: gcc not found. Cannot execute test." 2>&1
+ exit 0;
+ fi
;;
*)
NULL=NUL
@@ -62,7 +68,10 @@
cp ${TESTSRC}${FS}*.java ${THIS_DIR}
${TESTJAVA}${FS}bin${FS}javac *.java
-gcc -fPIC -shared -c -o test.o -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux ${TESTSRC}${FS}test.c
+$gcc_cmd -fPIC -shared -c -o test.o \
+ -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux \
+ ${TESTSRC}${FS}test.c
+
ld -shared -z execstack -o libtest-rwx.so test.o
ld -shared -z noexecstack -o libtest-rw.so test.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/runtime/jsig/Test8017498.sh Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+##
+## @test Test8017498.sh
+## @bug 8017498
+## @bug 8020791
+## @bug 8021296
+## @summary sigaction(sig) results in process hang/timed-out if sig is much greater than SIGRTMAX
+## @run shell/timeout=30 Test8017498.sh
+##
+
+if [ "${TESTSRC}" = "" ]
+then
+ TESTSRC=${PWD}
+ echo "TESTSRC not set. Using "${TESTSRC}" as default"
+fi
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../test_env.sh
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ Linux)
+ echo "Testing on Linux"
+ gcc_cmd=`which gcc`
+ if [ "x$gcc_cmd" == "x" ]; then
+ echo "WARNING: gcc not found. Cannot execute test." 2>&1
+ exit 0;
+ fi
+ if [ "$VM_BITS" = "64" ]
+ then
+ MY_LD_PRELOAD=${TESTJAVA}${FS}jre${FS}lib${FS}amd64${FS}libjsig.so
+ else
+ MY_LD_PRELOAD=${TESTJAVA}${FS}jre${FS}lib${FS}i386${FS}libjsig.so
+ fi
+ echo MY_LD_PRELOAD = ${MY_LD_PRELOAD}
+ ;;
+ *)
+ echo "Test passed; only valid for Linux"
+ exit 0;
+ ;;
+esac
+
+THIS_DIR=.
+
+cp ${TESTSRC}${FS}*.java ${THIS_DIR}
+${TESTJAVA}${FS}bin${FS}javac *.java
+
+$gcc_cmd -DLINUX -fPIC -shared \
+ -o ${TESTSRC}${FS}libTestJNI.so \
+ -I${TESTJAVA}${FS}include \
+ -I${TESTJAVA}${FS}include${FS}linux \
+ ${TESTSRC}${FS}TestJNI.c
+
+# run the java test in the background
+cmd="LD_PRELOAD=$MY_LD_PRELOAD \
+ ${TESTJAVA}${FS}bin${FS}java \
+ -Djava.library.path=${TESTSRC}${FS} -server TestJNI 100"
+echo "$cmd > test.out 2>&1"
+eval $cmd > test.out 2>&1
+
+grep "old handler" test.out > ${NULL}
+if [ $? = 0 ]
+then
+ echo "Test Passed"
+ exit 0
+fi
+
+echo "Test Failed"
+exit 1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/runtime/jsig/TestJNI.c Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void sig_handler(int sig, siginfo_t *info, ucontext_t *context) {
+
+ printf( " HANDLER (1) " );
+}
+
+JNIEXPORT void JNICALL Java_TestJNI_doSomething(JNIEnv *env, jclass klass, jint val) {
+ struct sigaction act;
+ struct sigaction oact;
+
+ act.sa_flags = SA_ONSTACK|SA_RESTART|SA_SIGINFO;
+ sigfillset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+ act.sa_sigaction = (void (*)())sig_handler;
+ sigaction(0x20+val, &act, &oact);
+
+ printf( " doSomething(%d) " , val);
+ printf( " old handler = %p " , oact.sa_handler);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/runtime/jsig/TestJNI.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class TestJNI {
+ static {
+ System.loadLibrary("TestJNI");
+ }
+ public static native void doSomething(int val);
+ public static void main(String[] args) {
+ int intArg = 43;
+ if (args.length > 0) {
+ try {
+ intArg = Integer.parseInt(args[0]);
+ } catch (NumberFormatException e) {
+ System.err.println("arg " + args[0] + " must be an integer");
+ System.exit(1);
+ }
+ }
+ TestJNI.doSomething(intArg);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/runtime/memory/LargePages/TestLargePagesFlags.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test TestLargePagesFlags
+ * @summary Tests how large pages are choosen depending on the given large pages flag combinations.
+ * @library /testlibrary
+ * @run main TestLargePagesFlags
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.Platform;
+import com.oracle.java.testlibrary.ProcessTools;
+import java.util.ArrayList;
+
+public class TestLargePagesFlags {
+
+ public static void main(String [] args) throws Exception {
+ if (!Platform.isLinux()) {
+ System.out.println("Skipping. TestLargePagesFlags has only been implemented for Linux.");
+ return;
+ }
+
+ testUseTransparentHugePages();
+ testUseHugeTLBFS();
+ testUseSHM();
+ testCombinations();
+ }
+
+ public static void testUseTransparentHugePages() throws Exception {
+ if (!canUse(UseTransparentHugePages(true))) {
+ System.out.println("Skipping testUseTransparentHugePages");
+ return;
+ }
+
+ // -XX:-UseLargePages overrides all other flags.
+ new FlagTester()
+ .use(UseLargePages(false),
+ UseTransparentHugePages(true))
+ .expect(
+ UseLargePages(false),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ // Explicitly turn on UseTransparentHugePages.
+ new FlagTester()
+ .use(UseTransparentHugePages(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(true),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseTransparentHugePages(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(true),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ // Setting a specific large pages flag will turn
+ // off heuristics to choose large pages type.
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseTransparentHugePages(false))
+ .expect(
+ UseLargePages(false),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ // Don't turn on UseTransparentHugePages
+ // unless the user explicitly asks for them.
+ new FlagTester()
+ .use(UseLargePages(true))
+ .expect(
+ UseTransparentHugePages(false));
+ }
+
+ public static void testUseHugeTLBFS() throws Exception {
+ if (!canUse(UseHugeTLBFS(true))) {
+ System.out.println("Skipping testUseHugeTLBFS");
+ return;
+ }
+
+ // -XX:-UseLargePages overrides all other flags.
+ new FlagTester()
+ .use(UseLargePages(false),
+ UseHugeTLBFS(true))
+ .expect(
+ UseLargePages(false),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ // Explicitly turn on UseHugeTLBFS.
+ new FlagTester()
+ .use(UseHugeTLBFS(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(true),
+ UseSHM(false));
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseHugeTLBFS(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(true),
+ UseSHM(false));
+
+ // Setting a specific large pages flag will turn
+ // off heuristics to choose large pages type.
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseHugeTLBFS(false))
+ .expect(
+ UseLargePages(false),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ // Using UseLargePages will default to UseHugeTLBFS large pages.
+ new FlagTester()
+ .use(UseLargePages(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(true),
+ UseSHM(false));
+ }
+
+ public static void testUseSHM() throws Exception {
+ if (!canUse(UseSHM(true))) {
+ System.out.println("Skipping testUseSHM");
+ return;
+ }
+
+ // -XX:-UseLargePages overrides all other flags.
+ new FlagTester()
+ .use(UseLargePages(false),
+ UseSHM(true))
+ .expect(
+ UseLargePages(false),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ // Explicitly turn on UseSHM.
+ new FlagTester()
+ .use(UseSHM(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(true)) ;
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseSHM(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(true)) ;
+
+ // Setting a specific large pages flag will turn
+ // off heuristics to choose large pages type.
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseSHM(false))
+ .expect(
+ UseLargePages(false),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ // Setting UseLargePages can allow the system to choose
+ // UseHugeTLBFS instead of UseSHM, but never UseTransparentHugePages.
+ new FlagTester()
+ .use(UseLargePages(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false));
+ }
+
+ public static void testCombinations() throws Exception {
+ if (!canUse(UseSHM(true)) || !canUse(UseHugeTLBFS(true))) {
+ System.out.println("Skipping testUseHugeTLBFSAndUseSHMCombination");
+ return;
+ }
+
+ // UseHugeTLBFS takes precedence over SHM.
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseHugeTLBFS(true),
+ UseSHM(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(true),
+ UseSHM(false));
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseHugeTLBFS(false),
+ UseSHM(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(true));
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseHugeTLBFS(true),
+ UseSHM(false))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(true),
+ UseSHM(false));
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseHugeTLBFS(false),
+ UseSHM(false))
+ .expect(
+ UseLargePages(false),
+ UseTransparentHugePages(false),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+
+ if (!canUse(UseTransparentHugePages(true))) {
+ return;
+ }
+
+ // UseTransparentHugePages takes precedence.
+
+ new FlagTester()
+ .use(UseLargePages(true),
+ UseTransparentHugePages(true),
+ UseHugeTLBFS(true),
+ UseSHM(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(true),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+
+ new FlagTester()
+ .use(UseTransparentHugePages(true),
+ UseHugeTLBFS(true),
+ UseSHM(true))
+ .expect(
+ UseLargePages(true),
+ UseTransparentHugePages(true),
+ UseHugeTLBFS(false),
+ UseSHM(false));
+ }
+
+ private static class FlagTester {
+ private Flag [] useFlags;
+
+ public FlagTester use(Flag... useFlags) {
+ this.useFlags = useFlags;
+ return this;
+ }
+
+ public void expect(Flag... expectedFlags) throws Exception {
+ if (useFlags == null) {
+ throw new IllegalStateException("Must run use() before expect()");
+ }
+
+ OutputAnalyzer output = executeNewJVM(useFlags);
+
+ for (Flag flag : expectedFlags) {
+ System.out.println("Looking for: " + flag.flagString());
+ String strValue = output.firstMatch(".* " + flag.name() + " .* :?= (\\S+).*", 1);
+
+ if (strValue == null) {
+ throw new RuntimeException("Flag " + flag.name() + " couldn't be found");
+ }
+
+ if (!flag.value().equals(strValue)) {
+ throw new RuntimeException("Wrong value for: " + flag.name()
+ + " expected: " + flag.value()
+ + " got: " + strValue);
+ }
+ }
+
+ output.shouldHaveExitValue(0);
+ }
+ }
+
+ private static OutputAnalyzer executeNewJVM(Flag... flags) throws Exception {
+ ArrayList args = new ArrayList<>();
+ for (Flag flag : flags) {
+ args.add(flag.flagString());
+ }
+ args.add("-XX:+PrintFlagsFinal");
+ args.add("-version");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ return output;
+ }
+
+ private static boolean canUse(Flag flag) {
+ try {
+ new FlagTester().use(flag).expect(flag);
+ } catch (Exception e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static Flag UseLargePages(boolean value) {
+ return new BooleanFlag("UseLargePages", value);
+ }
+
+ private static Flag UseTransparentHugePages(boolean value) {
+ return new BooleanFlag("UseTransparentHugePages", value);
+ }
+
+ private static Flag UseHugeTLBFS(boolean value) {
+ return new BooleanFlag("UseHugeTLBFS", value);
+ }
+
+ private static Flag UseSHM(boolean value) {
+ return new BooleanFlag("UseSHM", value);
+ }
+
+ private static class BooleanFlag implements Flag {
+ private String name;
+ private boolean value;
+
+ BooleanFlag(String name, boolean value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String flagString() {
+ return "-XX:" + (value ? "+" : "-") + name;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public String value() {
+ return Boolean.toString(value);
+ }
+ }
+
+ private static interface Flag {
+ public String flagString();
+ public String name();
+ public String value();
+ }
+}
--- ./hotspot/test/testlibrary/OutputAnalyzerTest.java Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/test/testlibrary/OutputAnalyzerTest.java Wed May 07 19:26:16 2014 -0700
@@ -172,5 +172,22 @@
} catch (RuntimeException e) {
// expected
}
+
+ {
+ String aaaa = "aaaa";
+ String result = output.firstMatch(aaaa);
+ if (!aaaa.equals(result)) {
+ throw new Exception("firstMatch(String) faild to match. Expected: " + aaaa + " got: " + result);
+ }
+ }
+
+ {
+ String aa = "aa";
+ String aa_grouped_aa = aa + "(" + aa + ")";
+ String result = output.firstMatch(aa_grouped_aa, 1);
+ if (!aa.equals(result)) {
+ throw new Exception("firstMatch(String, int) failed to match. Expected: " + aa + " got: " + result);
+ }
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOptionChecker.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.java.testlibrary;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import java.lang.management.ManagementFactory;
+
+/**
+ * Simple class to check writeability, invalid and valid values for VMOption
+ */
+public class DynamicVMOptionChecker {
+
+ /**
+ * Reads VM option from PlatformMXBean and parse it to integer value
+ *
+ * @param name of option
+ * @return parsed value
+ */
+ public static int getIntValue(String name) {
+
+ VMOption option = ManagementFactory.
+ getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+ getVMOption(name);
+
+ return Integer.parseInt(option.getValue());
+ }
+
+ /**
+ * Checks that VM option is dynamically writable
+ *
+ * @param name
+ * @throws RuntimeException if option if not writable
+ * @return always true
+ */
+ public static boolean checkIsWritable(String name) {
+ VMOption option = ManagementFactory.
+ getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+ getVMOption(name);
+
+ if (!option.isWriteable()) {
+ throw new RuntimeException(name + " is not writable");
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks that value cannot be set
+ *
+ * @param name of flag
+ * @param value string representation of value to set
+ * @throws RuntimeException on error - when expected exception hasn't been thrown
+ */
+ public static void checkInvalidValue(String name, String value) {
+ // should throw
+ try {
+ ManagementFactory.
+ getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+ setVMOption(name, value);
+
+ } catch (IllegalArgumentException e) {
+ return;
+ }
+
+ throw new RuntimeException("Expected IllegalArgumentException was not thrown, " + name + "= " + value);
+ }
+
+ /**
+ * Checks that value can be set
+ *
+ * @param name of flag to set
+ * @param value string representation of value to set
+ * @throws RuntimeException on error - when value in VM is not equal to origin
+ */
+ public static void checkValidValue(String name, String value) {
+ ManagementFactory.
+ getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+ setVMOption(name, value);
+
+ VMOption option = ManagementFactory.
+ getPlatformMXBean(HotSpotDiagnosticMXBean.class).
+ getVMOption(name);
+
+ if (!option.getValue().equals(value)) {
+ throw new RuntimeException("Actual value of " + name + " \"" + option.getValue()
+ + "\" not equal origin \"" + value + "\"");
+ }
+ }
+
+}
--- ./hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Wed May 07 19:26:16 2014 -0700
@@ -241,7 +241,38 @@
}
/**
- * Verifiy the exit value of the process
+ * Get the captured group of the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @param group The group to capture
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern, int group) {
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (stderrMatcher.find()) {
+ return stderrMatcher.group(group);
+ }
+ if (stdoutMatcher.find()) {
+ return stdoutMatcher.group(group);
+ }
+ return null;
+ }
+
+ /**
+ * Get the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern) {
+ return firstMatch(pattern, 0);
+ }
+
+ /**
+ * Verify the exit value of the process
*
* @param expectedExitValue Expected exit value from process
* @throws RuntimeException If the exit value from the process did not match the expected value
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./hotspot/test/testlibrary/com/oracle/java/testlibrary/TestDynamicVMOption.java Wed May 07 19:26:16 2014 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.java.testlibrary;
+
+/**
+ * Simple class to check writeability, invalid and valid values for concrete VMOption
+ */
+public class TestDynamicVMOption {
+
+ private final String name;
+ private final int value;
+
+ /**
+ * Constructor
+ *
+ * @param name of VM option to test
+ */
+ public TestDynamicVMOption(String name) {
+ this.name = name;
+ this.value = DynamicVMOptionChecker.getIntValue(name);
+ System.out.println(this.name + " = " + this.value);
+ }
+
+ /**
+ * Checks that this value can accept valid percentage values and cannot accept invalid percentage values
+ *
+ * @throws RuntimeException
+ */
+ public void testPercentageValues() {
+ checkInvalidValue(Integer.toString(Integer.MIN_VALUE));
+ checkInvalidValue(Integer.toString(Integer.MAX_VALUE));
+ checkInvalidValue("-10");
+ checkInvalidValue("190");
+ }
+
+ /**
+ * Reads VM option from PlatformMXBean and parse it to integer value
+ *
+ * @return value
+ */
+ public int getIntValue() {
+ return DynamicVMOptionChecker.getIntValue(this.name);
+ }
+
+ /**
+ * Checks that this VM option is dynamically writable
+ *
+ * @throws RuntimeException if option if not writable
+ * @return true
+ */
+ public boolean checkIsWritable() throws RuntimeException {
+ return DynamicVMOptionChecker.checkIsWritable(this.name);
+ }
+
+ /**
+ * Checks that value for this VM option cannot be set
+ *
+ * @param value to check
+ * @throws RuntimeException on error - when expected exception hasn't been thrown
+ */
+ public void checkInvalidValue(String value) {
+ DynamicVMOptionChecker.checkInvalidValue(this.name, value);
+ }
+
+ /**
+ * Checks that value for this VM option can be set
+ *
+ * @param value to check
+ * @throws RuntimeException on error - when value in VM is not equal to origin
+ */
+ public void checkValidValue(String value) {
+ DynamicVMOptionChecker.checkValidValue(this.name, value);
+ }
+
+}
--- ./hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Mar 18 12:31:20 2014 -0700
+++ ./hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed May 07 19:26:16 2014 -0700
@@ -78,4 +78,7 @@
public native void NMTUncommitMemory(long addr, long size);
public native void NMTReleaseMemory(long addr, long size);
public native boolean NMTWaitForDataMerge();
+
+ // Compiler
+ public native void deoptimizeAll();
}
--- ./jaxp/.hgtags Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/.hgtags Wed May 07 19:26:26 2014 -0700
@@ -359,6 +359,7 @@
66363323f14d85d4ab28e883a3323b9d72dea5fd jdk7u40-b42
c0bd71414ea513f54f23965936a837fca093ac91 jdk7u40-b43
91bc4534851265291bb3b16452a0968d6909979f jdk7u40-b60
+d9b92749a0f4c8e6c6f4fe11210c2a02d70bae74 jdk7u60-b00
c500d4ec41ff2117eabfa33e640b6df2f21deb3d jdk7u40-b61
9e3f8ab9d17be6b1a4a097fcc5bc5412013d3e86 jdk7u40-b62
1a7e2024963d3a8d6cde209de0967ac43418b82a jdk7u45-b01
@@ -417,3 +418,26 @@
f3f02e67d867ae25cd4f3b9bc39a4fd17f593126 jdk7u55-b11
708a1872f5bb8ba58ecc9fcbf4e12e6fa4783998 jdk7u55-b12
14719f73596f5c90e3f46c0f4312f32e5b105edd jdk7u55-b13
+01f26830f88cf4f10897416fe1f4f372efcdecf5 jdk7u55-b30
+26187a65c765b3177f1b7ff0638259bf66f9ec47 jdk7u55-b14
+5be97f6c25d9eb3ef0a05fc860964cb3d27134b0 jdk7u55-b31
+d9b92749a0f4c8e6c6f4fe11210c2a02d70bae74 jdk7u60-b00
+ad39e88c503948fc4fc01e97c75b6e3c24599d23 jdk7u60-b01
+050986fd54e3ec4515032ee938bc59e86772b6c0 jdk7u60-b02
+359b79d99538d17eeb90927a1e4883fcec31661f jdk7u60-b03
+7215972c2c30d0fa469a459a3e4fcee6bc93991d jdk7u60-b04
+673ea3822e59de18ae5771de7a280c6ae435ef86 jdk7u60-b05
+fd1cb0040a1d05086ca3bf32f10e1efd43f05116 jdk7u60-b06
+cd7c8fa7a057e62e094cdde78dd632de54cedb8c jdk7u60-b07
+b19c0f18b5a508be894aead53617688342690b01 jdk7u60-b08
+4bfece8a5148947d268611cc1b4485e92960064e jdk7u60-b09
+28a6c0b3b22580101bf750383c2e48d34dea2124 jdk7u60-b10
+e57490e0b99917ea8e1da1bb4d0c57fd5b7705f9 jdk7u60-b11
+a9574b35f0af409fa1665aadd9b2997a0f9878dc jdk7u60-b12
+92cf0b5c1c3e9b61d36671d8fb5070716e0f016b jdk7u60-b13
+2814f43a6c73414dcb2b799e1a52d5b44688590d jdk7u60-b14
+10eed57b66336660f71f7524f2283478bdf373dc jdk7u60-b15
+fefd2d5c524b0be78876d9b98d926abda2828e79 jdk7u60-b16
+ba6b0b5dfe5a0f50fac95c488c8a5400ea07d4f8 jdk7u60-b18
+ba6b0b5dfe5a0f50fac95c488c8a5400ea07d4f8 jdk7u60-b17
+581752d32aebea959fec84e8ae692e1f63d2c4a8 jdk7u60-b19
--- ./jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/XalanConstants.java Wed May 07 19:26:26 2014 -0700
@@ -188,6 +188,19 @@
ORACLE_JAXP_PROPERTY_PREFIX + "xmlSecurityPropertyManager";
/**
+ * Feature enableExtensionFunctions
+ */
+ public static final String ORACLE_ENABLE_EXTENSION_FUNCTION =
+ ORACLE_JAXP_PROPERTY_PREFIX + "enableExtensionFunctions";
+ public static final String SP_ORACLE_ENABLE_EXTENSION_FUNCTION = "javax.xml.enableExtensionFunctions";
+
+ /**
+ * Values for a feature
+ */
+ public static final String FEATURE_TRUE = "true";
+ public static final String FEATURE_FALSE = "false";
+
+ /**
* Check if we're in jdk8 or above
*/
public static final boolean IS_JDK8_OR_ABOVE = isJavaVersionAtLeast(8);
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_es.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_es.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_fr.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_fr.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_it.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_it.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ja.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ja.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ko.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ko.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_pt_BR.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_pt_BR.java Wed May 07 19:26:26 2014 -0700
@@ -472,7 +472,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1413,13 +1419,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_sv.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_sv.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_CN.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_CN.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_TW.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_TW.java Wed May 07 19:26:26 2014 -0700
@@ -471,7 +471,13 @@
// Error messages...
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/** Error message ID that has a null message, but takes in a single object. */
{"ER0000" , "{0}" },
@@ -1412,13 +1418,6 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The int to message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
// ================= INFRASTRUCTURE ======================
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/utils/FeatureManager.java Wed May 07 19:26:26 2014 -0700
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xalan.internal.utils;
+
+
+import com.sun.org.apache.xalan.internal.XalanConstants;
+
+/**
+ * This class manages security related properties
+ *
+ */
+public final class FeatureManager extends FeaturePropertyBase {
+
+ /**
+ * States of the settings of a property, in the order: default value, value
+ * set by FEATURE_SECURE_PROCESSING, jaxp.properties file, jaxp system
+ * properties, and jaxp api properties
+ */
+ public static enum State {
+ //this order reflects the overriding order
+ DEFAULT, FSP, JAXPDOTPROPERTIES, SYSTEMPROPERTY, APIPROPERTY
+ }
+
+ /**
+ * Xalan Features
+ */
+ public static enum Feature {
+ ORACLE_ENABLE_EXTENSION_FUNCTION(XalanConstants.ORACLE_ENABLE_EXTENSION_FUNCTION,
+ "true");
+
+ final String name;
+ final String defaultValue;
+
+ Feature(String name, String value) {
+ this.name = name;
+ this.defaultValue = value;
+ }
+
+ public boolean equalsName(String propertyName) {
+ return (propertyName == null) ? false : name.equals(propertyName);
+ }
+
+ String defaultValue() {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Default constructor. Establishes default values
+ */
+ public FeatureManager() {
+ values = new String[Feature.values().length];
+ for (Feature feature : Feature.values()) {
+ values[feature.ordinal()] = feature.defaultValue();
+ }
+ //read system properties or jaxp.properties
+ readSystemProperties();
+ }
+
+
+ /**
+ * Check if the feature is enabled
+ * @param feature name of the feature
+ * @return true if enabled, false otherwise
+ */
+ public boolean isFeatureEnabled(Feature feature) {
+ return Boolean.parseBoolean(values[feature.ordinal()]);
+ }
+
+ /**
+ * Check if the feature is enabled
+ * @param propertyName name of the feature
+ * @return true if enabled, false otherwise
+ */
+ public boolean isFeatureEnabled(String propertyName) {
+ return Boolean.parseBoolean(values[getIndex(propertyName)]);
+ }
+
+ /**
+ * Get the index by property name
+ * @param propertyName property name
+ * @return the index of the property if found; return -1 if not
+ */
+ public int getIndex(String propertyName){
+ for (Feature feature : Feature.values()) {
+ if (feature.equalsName(propertyName)) {
+ return feature.ordinal();
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Read from system properties, or those in jaxp.properties
+ */
+ private void readSystemProperties() {
+ getSystemProperty(Feature.ORACLE_ENABLE_EXTENSION_FUNCTION,
+ XalanConstants.SP_ORACLE_ENABLE_EXTENSION_FUNCTION);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/utils/FeaturePropertyBase.java Wed May 07 19:26:26 2014 -0700
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xalan.internal.utils;
+
+import com.sun.org.apache.xalan.internal.XalanConstants;
+
+/**
+ * This is the base class for features and properties
+ *
+ */
+public abstract class FeaturePropertyBase {
+
+ /**
+ * States of the settings of a property, in the order: default value, value
+ * set by FEATURE_SECURE_PROCESSING, jaxp.properties file, jaxp system
+ * properties, and jaxp api properties
+ */
+ public static enum State {
+ //this order reflects the overriding order
+ DEFAULT, FSP, JAXPDOTPROPERTIES, SYSTEMPROPERTY, APIPROPERTY
+ }
+
+
+ /**
+ * Values of the properties as defined in enum Properties
+ */
+ String[] values = null;
+ /**
+ * States of the settings for each property in Properties above
+ */
+ State[] states = {State.DEFAULT, State.DEFAULT};
+
+
+ /**
+ * Set the value for a specific property.
+ *
+ * @param property the property
+ * @param state the state of the property
+ * @param value the value of the property
+ */
+ public void setValue(Enum property, State state, String value) {
+ //only update if it shall override
+ if (state.compareTo(states[property.ordinal()]) >= 0) {
+ values[property.ordinal()] = value;
+ states[property.ordinal()] = state;
+ }
+ }
+
+ /**
+ * Set the value of a property by its index
+ * @param index the index of the property
+ * @param state the state of the property
+ * @param value the value of the property
+ */
+ public void setValue(int index, State state, String value) {
+ //only update if it shall override
+ if (state.compareTo(states[index]) >= 0) {
+ values[index] = value;
+ states[index] = state;
+ }
+ }
+
+ /**
+ * Set value by property name and state
+ * @param propertyName property name
+ * @param state the state of the property
+ * @param value the value of the property
+ * @return true if the property is managed by the security property manager;
+ * false if otherwise.
+ */
+ public boolean setValue(String propertyName, State state, Object value) {
+ int index = getIndex(propertyName);
+ if (index > -1) {
+ setValue(index, state, (String)value);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set value by property name and state
+ * @param propertyName property name
+ * @param state the state of the property
+ * @param value the value of the property
+ * @return true if the property is managed by the security property manager;
+ * false if otherwise.
+ */
+ public boolean setValue(String propertyName, State state, boolean value) {
+ int index = getIndex(propertyName);
+ if (index > -1) {
+ if (value) {
+ setValue(index, state, XalanConstants.FEATURE_TRUE);
+ } else {
+ setValue(index, state, XalanConstants.FEATURE_FALSE);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return the value of the specified property
+ *
+ * @param property the property
+ * @return the value of the property
+ */
+ public String getValue(Enum property) {
+ return values[property.ordinal()];
+ }
+
+ /**
+ * Return the value of the specified property
+ *
+ * @param property the property
+ * @return the value of the property
+ */
+ public String getValue(String property) {
+ int index = getIndex(property);
+ if (index > -1) {
+ return getValueByIndex(index);
+ }
+ return null;
+ }
+
+ /**
+ * Return the value of the specified property.
+ *
+ * @param propertyName the property name
+ * @return the value of the property as a string. If a property is managed
+ * by this manager, its value shall not be null.
+ */
+ public String getValueAsString(String propertyName) {
+ int index = getIndex(propertyName);
+ if (index > -1) {
+ return getValueByIndex(index);
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the value of a property by its ordinal
+ * @param index the index of a property
+ * @return value of a property
+ */
+ public String getValueByIndex(int index) {
+ return values[index];
+ }
+
+ /**
+ * Get the index by property name
+ * @param propertyName property name
+ * @return the index of the property if found; return -1 if not
+ */
+ public abstract int getIndex(String propertyName);
+
+ public > int getIndex(Class property, String propertyName) {
+ for (Enum enumItem : property.getEnumConstants()) {
+ if (enumItem.toString().equals(propertyName)) {
+ //internally, ordinal is used as index
+ return enumItem.ordinal();
+ }
+ }
+ return -1;
+ };
+
+
+ /**
+ * Read from system properties, or those in jaxp.properties
+ *
+ * @param property the property
+ * @param systemProperty the name of the system property
+ */
+ void getSystemProperty(Enum property, String systemProperty) {
+ try {
+ String value = SecuritySupport.getSystemProperty(systemProperty);
+ if (value != null) {
+ values[property.ordinal()] = value;
+ states[property.ordinal()] = State.SYSTEMPROPERTY;
+ return;
+ }
+
+ value = SecuritySupport.readJAXPProperty(systemProperty);
+ if (value != null) {
+ values[property.ordinal()] = value;
+ states[property.ordinal()] = State.JAXPDOTPROPERTIES;
+ }
+ } catch (NumberFormatException e) {
+ //invalid setting ignored
+ }
+ }
+}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java Wed May 07 19:26:26 2014 -0700
@@ -1,42 +1,28 @@
/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ * 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.
*
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
+ * 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).
*
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
+ * 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.
*
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
*/
+
package com.sun.org.apache.xalan.internal.utils;
import com.sun.org.apache.xalan.internal.XalanConstants;
--- ./jaxp/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityPropertyManager.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityPropertyManager.java Wed May 07 19:26:26 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -33,20 +33,10 @@
* This class manages security related properties
*
*/
-public final class XMLSecurityPropertyManager {
+public final class XMLSecurityPropertyManager extends FeaturePropertyBase {
/**
- * States of the settings of a property, in the order: default value, value
- * set by FEATURE_SECURE_PROCESSING, jaxp.properties file, jaxp system
- * properties, and jaxp api properties
- */
- public static enum State {
- //this order reflects the overriding order
- DEFAULT, FSP, JAXPDOTPROPERTIES, SYSTEMPROPERTY, APIPROPERTY
- }
-
- /**
- * Limits managed by the security manager
+ * Properties managed by the security property manager
*/
public static enum Property {
ACCESS_EXTERNAL_DTD(XMLConstants.ACCESS_EXTERNAL_DTD,
@@ -73,15 +63,6 @@
/**
- * Values of the properties as defined in enum Properties
- */
- private final String[] values;
- /**
- * States of the settings for each property in Properties above
- */
- private State[] states = {State.DEFAULT, State.DEFAULT};
-
- /**
* Default constructor. Establishes default values
*/
public XMLSecurityPropertyManager() {
@@ -94,86 +75,6 @@
}
/**
- * Set limit by property name and state
- * @param propertyName property name
- * @param state the state of the property
- * @param value the value of the property
- * @return true if the property is managed by the security property manager;
- * false if otherwise.
- */
- public boolean setValue(String propertyName, State state, Object value) {
- int index = getIndex(propertyName);
- if (index > -1) {
- setValue(index, state, (String)value);
- return true;
- }
- return false;
- }
-
- /**
- * Set the value for a specific property.
- *
- * @param property the property
- * @param state the state of the property
- * @param value the value of the property
- */
- public void setValue(Property property, State state, String value) {
- //only update if it shall override
- if (state.compareTo(states[property.ordinal()]) >= 0) {
- values[property.ordinal()] = value;
- states[property.ordinal()] = state;
- }
- }
-
- /**
- * Set the value of a property by its index
- * @param index the index of the property
- * @param state the state of the property
- * @param value the value of the property
- */
- public void setValue(int index, State state, String value) {
- //only update if it shall override
- if (state.compareTo(states[index]) >= 0) {
- values[index] = value;
- states[index] = state;
- }
- }
-
- /**
- * Return the value of the specified property
- *
- * @param propertyName the property name
- * @return the value of the property as a string
- */
- public String getValue(String propertyName) {
- int index = getIndex(propertyName);
- if (index > -1) {
- return getValueByIndex(index);
- }
-
- return null;
- }
-
- /**
- * Return the value of the specified property
- *
- * @param property the property
- * @return the value of the property
- */
- public String getValue(Property property) {
- return values[property.ordinal()];
- }
-
- /**
- * Return the value of a property by its ordinal
- * @param index the index of a property
- * @return value of a property
- */
- public String getValueByIndex(int index) {
- return values[index];
- }
-
- /**
* Get the index by property name
* @param propertyName property name
* @return the index of the property if found; return -1 if not
@@ -198,28 +99,4 @@
XalanConstants.SP_ACCESS_EXTERNAL_STYLESHEET);
}
- /**
- * Read from system properties, or those in jaxp.properties
- *
- * @param property the property
- * @param systemProperty the name of the system property
- */
- private void getSystemProperty(Property property, String systemProperty) {
- try {
- String value = SecuritySupport.getSystemProperty(systemProperty);
- if (value != null) {
- values[property.ordinal()] = value;
- states[property.ordinal()] = State.SYSTEMPROPERTY;
- return;
- }
-
- value = SecuritySupport.readJAXPProperty(systemProperty);
- if (value != null) {
- values[property.ordinal()] = value;
- states[property.ordinal()] = State.JAXPDOTPROPERTIES;
- }
- } catch (NumberFormatException e) {
- //invalid setting ignored
- }
- }
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/Compile.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/cmdline/Compile.java Wed May 07 19:26:26 2014 -0700
@@ -23,6 +23,7 @@
package com.sun.org.apache.xalan.internal.xsltc.cmdline;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import java.io.File;
import java.net.URL;
import java.util.Vector;
@@ -77,7 +78,7 @@
final GetOpt getopt = new GetOpt(args, "o:d:j:p:uxhsinv");
if (args.length < 1) printUsage();
- final XSLTC xsltc = new XSLTC(true);
+ final XSLTC xsltc = new XSLTC(true, new FeatureManager());
xsltc.init();
int c;
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java Wed May 07 19:26:26 2014 -0700
@@ -42,6 +42,7 @@
import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
import com.sun.org.apache.bcel.internal.generic.NEW;
import com.sun.org.apache.bcel.internal.generic.PUSH;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.BooleanType;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
@@ -717,6 +718,8 @@
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
final boolean isSecureProcessing = classGen.getParser().getXSLTC().isSecureProcessing();
+ final boolean isExtensionFunctionEnabled = classGen.getParser().getXSLTC()
+ .getFeature(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION);
int index;
// Translate calls to methods in the BasisLibrary
@@ -760,7 +763,7 @@
il.append(new INVOKESTATIC(index));
}
else if (_isExtConstructor) {
- if (isSecureProcessing)
+ if (isSecureProcessing && !isExtensionFunctionEnabled)
translateUnallowedExtension(cpg, il);
final String clazz =
@@ -822,7 +825,7 @@
}
// Invoke function calls that are handled in separate classes
else {
- if (isSecureProcessing)
+ if (isSecureProcessing && !isExtensionFunctionEnabled)
translateUnallowedExtension(cpg, il);
final String clazz = _chosenMethod.getDeclaringClass().getName();
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java Wed May 07 19:26:26 2014 -0700
@@ -43,6 +43,8 @@
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.xalan.internal.XalanConstants;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager.Feature;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
@@ -148,11 +150,14 @@
private XMLSecurityManager _xmlSecurityManager;
+ private final FeatureManager _featureManager;
+
/**
* XSLTC compiler constructor
*/
- public XSLTC(boolean useServicesMechanism) {
+ public XSLTC(boolean useServicesMechanism, FeatureManager featureManager) {
_parser = new Parser(this, useServicesMechanism);
+ _featureManager = featureManager;
}
/**
@@ -182,6 +187,15 @@
_useServicesMechanism = flag;
}
+ /**
+ * Return the value of the specified feature
+ * @param name name of the feature
+ * @return true if the feature is enabled, false otherwise
+ */
+ public boolean getFeature(Feature name) {
+ return _featureManager.isFeatureEnabled(name);
+ }
+
/**
* Return allowed protocols for accessing external stylesheet.
*/
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"More than one stylesheet defined in the same file."},
@@ -1012,12 +1018,5 @@
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ca.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ca.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"S'ha definit m\u00e9s d'un full d'estils en el mateix fitxer."},
@@ -853,12 +859,5 @@
"FEATURE_SECURE_PROCESSING: Cannot set the feature to false when security manager is present."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_cs.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_cs.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"V\u00edce ne\u017e jedna p\u0159edloha stylu je definov\u00e1na ve stejn\u00e9m souboru."},
@@ -853,12 +859,5 @@
"FEATURE_SECURE_PROCESSING: Cannot set the feature to false when security manager is present."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"Mehrere Stylesheets in derselben Datei definiert."},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: Feature kann nicht auf \"false\" gesetzt werden, wenn Security Manager vorhanden ist."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_es.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_es.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"Se ha definido m\u00E1s de una hoja de estilo en el mismo archivo."},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: no se puede definir la funci\u00F3n en false cuando est\u00E1 presente el gestor de seguridad."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_fr.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_fr.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"Plusieurs feuilles de style d\u00E9finies dans le m\u00EAme fichier."},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING : impossible de d\u00E9finir la fonctionnalit\u00E9 sur False en pr\u00E9sence du gestionnaire de s\u00E9curit\u00E9."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_it.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_it.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"Sono stati definiti pi\u00F9 fogli di stile nello stesso file."},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: impossibile impostare la funzione su false se \u00E8 presente Security Manager."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"\u540C\u3058\u30D5\u30A1\u30A4\u30EB\u306B\u8907\u6570\u306E\u30B9\u30BF\u30A4\u30EB\u30B7\u30FC\u30C8\u304C\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u307E\u3059\u3002"},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: \u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30DE\u30CD\u30FC\u30B8\u30E3\u304C\u5B58\u5728\u3059\u308B\u3068\u304D\u3001\u6A5F\u80FD\u3092false\u306B\u8A2D\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002"}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ko.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ko.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"\uB3D9\uC77C\uD55C \uD30C\uC77C\uC5D0 \uC2A4\uD0C0\uC77C\uC2DC\uD2B8\uAC00 \uB450 \uAC1C \uC774\uC0C1 \uC815\uC758\uB418\uC5C8\uC2B5\uB2C8\uB2E4."},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: \uBCF4\uC548 \uAD00\uB9AC\uC790\uAC00 \uC788\uC744 \uACBD\uC6B0 \uAE30\uB2A5\uC744 false\uB85C \uC124\uC815\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_pt_BR.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_pt_BR.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"Mais de uma folha de estilos definida no mesmo arquivo."},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: N\u00E3o \u00E9 poss\u00EDvel definir o recurso como falso quando o gerenciador de seguran\u00E7a est\u00E1 presente."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sk.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sk.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"Viac ne\u017e jeden \u0161t\u00fdl dokumentu bol definovan\u00fd v rovnakom s\u00fabore."},
@@ -853,12 +859,5 @@
"FEATURE_SECURE_PROCESSING: Cannot set the feature to false when security manager is present."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sv.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_sv.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"Fler \u00E4n en formatmall har definierats i samma fil."},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: Funktionen kan inte anges till false om s\u00E4kerhetshanteraren anv\u00E4nds."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"\u540C\u4E00\u6587\u4EF6\u4E2D\u5B9A\u4E49\u4E86\u591A\u4E2A\u6837\u5F0F\u8868\u3002"},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: \u5B58\u5728 Security Manager \u65F6, \u65E0\u6CD5\u5C06\u6B64\u529F\u80FD\u8BBE\u7F6E\u4E3A\u201C\u5047\u201D\u3002"}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_TW.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_TW.java Wed May 07 19:26:26 2014 -0700
@@ -90,7 +90,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
{ErrorMsg.MULTIPLE_STYLESHEET_ERR,
"\u76F8\u540C\u6A94\u6848\u4E2D\u5B9A\u7FA9\u4E86\u8D85\u904E\u4E00\u500B\u6A23\u5F0F\u8868\u3002"},
@@ -913,12 +919,5 @@
"FEATURE_SECURE_PROCESSING: \u5B89\u5168\u7BA1\u7406\u7A0B\u5F0F\u5B58\u5728\u6642\uFF0C\u7121\u6CD5\u5C07\u529F\u80FD\u8A2D\u70BA\u507D\u3002"}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Wed May 07 19:26:26 2014 -0700
@@ -955,6 +955,9 @@
if (Double.isNaN(d) || Double.isInfinite(d))
return(Double.toString(d));
+ //Convert -0.0 to +0.0 other values remains the same
+ d = d + 0.0;
+
// Use the XPath formatter to ignore locales
StringBuffer result = threadLocalStringBuffer.get();
result.setLength(0);
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"Use of the extension element ''{0}'' is not allowed when the secure processing feature is set to true."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ca.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ca.java Wed May 07 19:26:26 2014 -0700
@@ -79,7 +79,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -223,13 +229,6 @@
"No s''ha pogut resoldre la refer\u00e8ncia d''URI ''{0}''."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_cs.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_cs.java Wed May 07 19:26:26 2014 -0700
@@ -79,7 +79,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -223,13 +229,6 @@
"Nelze p\u0159elo\u017eit odkazy URI ''{0}''."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_de.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_de.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"Verwendung des Erweiterungselements \"{0}\" ist nicht zul\u00E4ssig, wenn das Feature f\u00FCr die sichere Verarbeitung auf \"true\" gesetzt ist."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_es.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_es.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"El uso del elemento de extensi\u00F3n ''{0}'' no est\u00E1 permitido cuando la funci\u00F3n de procesamiento seguro se ha definido en true."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_fr.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_fr.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"L''utilisation de l''\u00E9l\u00E9ment d''extension ''{0}'' n''est pas autoris\u00E9e lorsque la fonctionnalit\u00E9 de traitement s\u00E9curis\u00E9 est d\u00E9finie sur True."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_it.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_it.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"Non \u00E8 consentito utilizzare l''elemento di estensione ''{0}'' se la funzione di elaborazione sicura \u00E8 impostata su true."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ja.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ja.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"\u30BB\u30AD\u30E5\u30A2\u51E6\u7406\u6A5F\u80FD\u304Ctrue\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u3068\u304D\u3001\u62E1\u5F35\u8981\u7D20''{0}''\u306E\u4F7F\u7528\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002"},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ko.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_ko.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"\uBCF4\uC548 \uCC98\uB9AC \uAE30\uB2A5\uC774 true\uB85C \uC124\uC815\uB41C \uACBD\uC6B0 \uD655\uC7A5 \uC694\uC18C ''{0}''\uC744(\uB97C) \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_pt_BR.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_pt_BR.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"O uso do elemento da extens\u00E3o ''{0}'' n\u00E3o ser\u00E1 permitido quando o recurso de processamento seguro for definido como verdadeiro."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_sk.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_sk.java Wed May 07 19:26:26 2014 -0700
@@ -79,7 +79,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -223,13 +229,6 @@
"Nebolo mo\u017en\u00e9 rozl\u00ed\u0161i\u0165 referenciu URI ''{0}''."}
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_sv.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_sv.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"Anv\u00E4ndning av till\u00E4ggselementet ''{0}'' \u00E4r inte till\u00E5tet n\u00E4r s\u00E4ker bearbetning till\u00E4mpas."},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_zh_CN.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_zh_CN.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"\u5F53\u5B89\u5168\u5904\u7406\u529F\u80FD\u8BBE\u7F6E\u4E3A\u201C\u771F\u201D\u65F6, \u4E0D\u5141\u8BB8\u4F7F\u7528\u6269\u5C55\u5143\u7D20 ''{0}''\u3002"},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_zh_TW.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages_zh_TW.java Wed May 07 19:26:26 2014 -0700
@@ -81,7 +81,13 @@
*/
// These message should be read from a locale-specific resource bundle
- private static final Object[][] _contents = new Object[][] {
+ /** Get the lookup table for error messages.
+ *
+ * @return The message lookup table.
+ */
+ public Object[][] getContents()
+ {
+ return new Object[][] {
/*
* Note to translators: the substitution text in the following message
@@ -276,13 +282,6 @@
{BasisLibrary.UNALLOWED_EXTENSION_ELEMENT_ERR,
"\u7576\u5B89\u5168\u8655\u7406\u529F\u80FD\u8A2D\u70BA\u771F\u6642\uFF0C\u4E0D\u5141\u8A31\u4F7F\u7528\u64F4\u5145\u5957\u4EF6\u5143\u7D20 ''{0}''\u3002"},
};
- /** Get the lookup table for error messages.
- *
- * @return The message lookup table.
- */
- public Object[][] getContents()
- {
- return _contents;
}
}
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesHandlerImpl.java Wed May 07 19:26:26 2014 -0700
@@ -95,7 +95,7 @@
_tfactory = tfactory;
// Instantiate XSLTC and get reference to parser object
- XSLTC xsltc = new XSLTC(tfactory.useServicesMechnism());
+ XSLTC xsltc = new XSLTC(tfactory.useServicesMechnism(), tfactory.getFeatureManager());
if (tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING))
xsltc.setSecureProcessing(true);
--- ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java Wed May 07 19:26:26 2014 -0700
@@ -23,6 +23,23 @@
package com.sun.org.apache.xalan.internal.xsltc.trax;
+import com.sun.org.apache.xalan.internal.XalanConstants;
+import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
+import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase;
+import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
+import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
+import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
+import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager;
+import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property;
+import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase.State;
+import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
+import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader;
+import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
+import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
+import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager;
+import com.sun.org.apache.xml.internal.utils.StopParseException;
+import com.sun.org.apache.xml.internal.utils.StylesheetPIHandler;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -37,11 +54,9 @@
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-
import javax.xml.XMLConstants;
+import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
@@ -58,27 +73,9 @@
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TemplatesHandler;
import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stax.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
-import javax.xml.transform.stax.*;
-
-import com.sun.org.apache.xml.internal.utils.StylesheetPIHandler;
-import com.sun.org.apache.xml.internal.utils.StopParseException;
-
-import com.sun.org.apache.xalan.internal.XalanConstants;
-import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
-import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader;
-import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
-import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
-import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager;
-import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
-import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
-import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
-import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager;
-import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property;
-import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.State;
-import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
-
import org.xml.sax.InputSource;
import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
@@ -240,6 +237,8 @@
private XMLSecurityPropertyManager _xmlSecurityPropertyMgr;
private XMLSecurityManager _xmlSecurityManager;
+ private final FeatureManager _featureManager;
+
/**
* javax.xml.transform.sax.TransformerFactory implementation.
*/
@@ -254,10 +253,13 @@
private TransformerFactoryImpl(boolean useServicesMechanism) {
this.m_DTMManagerClass = XSLTCDTMManager.getDTMManagerClass(useServicesMechanism);
this._useServicesMechanism = useServicesMechanism;
+ _featureManager = new FeatureManager();
if (System.getSecurityManager() != null) {
_isSecureMode = true;
_isNotSecureProcessing = false;
+ _featureManager.setValue(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION,
+ FeaturePropertyBase.State.FSP, XalanConstants.FEATURE_FALSE);
}
_xmlSecurityPropertyMgr = new XMLSecurityPropertyManager();
@@ -513,6 +515,10 @@
Property.ACCESS_EXTERNAL_STYLESHEET);
}
+ if (value && _featureManager != null) {
+ _featureManager.setValue(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION,
+ FeaturePropertyBase.State.FSP, XalanConstants.FEATURE_FALSE);
+ }
return;
}
else if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) {
@@ -521,6 +527,11 @@
_useServicesMechanism = value;
}
else {
+ if (_featureManager != null &&
+ _featureManager.setValue(name, State.APIPROPERTY, value)) {
+ return;
+ }
+
// unknown feature
ErrorMsg err = new ErrorMsg(ErrorMsg.JAXP_UNSUPPORTED_FEATURE, name);
throw new TransformerConfigurationException(err.toString());
@@ -569,6 +580,13 @@
return !_isNotSecureProcessing;
}
+ /** Check to see if the property is managed by the security manager **/
+ String propertyValue = (_featureManager != null) ?
+ _featureManager.getValueAsString(name) : null;
+ if (propertyValue != null) {
+ return Boolean.parseBoolean(propertyValue);
+ }
+
// Feature not supported
return false;
}
@@ -579,6 +597,13 @@
return _useServicesMechanism;
}
+ /**
+ * @return the feature manager
+ */
+ public FeatureManager getFeatureManager() {
+ return _featureManager;
+ }
+
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Get the object that is used by default during the transformation to
@@ -859,7 +884,7 @@
}
// Create and initialize a stylesheet compiler
- final XSLTC xsltc = new XSLTC(_useServicesMechanism);
+ final XSLTC xsltc = new XSLTC(_useServicesMechanism, _featureManager);
if (_debug) xsltc.setDebug(true);
if (_enableInlining)
xsltc.setTemplateInlining(true);
--- ./jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/XPath.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xerces/internal/impl/xpath/XPath.java Wed May 07 19:26:26 2014 -0700
@@ -1422,7 +1422,7 @@
}
ch = data.charAt(currentOffset);
} while (ch == ' ' || ch == 0x0A || ch == 0x09 || ch == 0x0D);
- if (currentOffset == endOffset || ch == '|') {
+ if (currentOffset == endOffset || ch == '|' || ch == '/') {
addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
starIsMultiplyOperator = true;
break;
--- ./jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DefaultValidationErrorHandler.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DefaultValidationErrorHandler.java Wed May 07 19:26:26 2014 -0700
@@ -20,6 +20,8 @@
package com.sun.org.apache.xerces.internal.jaxp;
+import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter;
+import java.util.Locale;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
@@ -30,6 +32,11 @@
class DefaultValidationErrorHandler extends DefaultHandler {
static private int ERROR_COUNT_LIMIT = 10;
private int errorCount = 0;
+ private Locale locale = Locale.getDefault();
+
+ public DefaultValidationErrorHandler(Locale locale) {
+ this.locale = locale;
+ }
// XXX Fix message i18n
public void error(SAXParseException e) throws SAXException {
@@ -38,11 +45,8 @@
return;
} else if (errorCount == 0) {
// Print a warning before the first error
- System.err.println("Warning: validation was turned on but an org.xml.sax.ErrorHandler was not");
- System.err.println("set, which is probably not what is desired. Parser will use a default");
- System.err.println("ErrorHandler to print the first " +
- ERROR_COUNT_LIMIT + " errors. Please call");
- System.err.println("the 'setErrorHandler' method to fix this.");
+ System.err.println(SAXMessageFormatter.formatMessage(locale,
+ "errorHandlerNotSet", new Object [] {errorCount}));
}
String systemId = e.getSystemId();
--- ./jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderImpl.java Wed May 07 19:26:26 2014 -0700
@@ -140,7 +140,7 @@
// validation errors with a warning telling the user to set an
// ErrorHandler
if (dbf.isValidating()) {
- fInitErrorHandler = new DefaultValidationErrorHandler();
+ fInitErrorHandler = new DefaultValidationErrorHandler(domParser.getXMLParserConfiguration().getLocale());
setErrorHandler(fInitErrorHandler);
}
else {
--- ./jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xerces/internal/jaxp/SAXParserImpl.java Wed May 07 19:26:26 2014 -0700
@@ -20,15 +20,6 @@
package com.sun.org.apache.xerces.internal.jaxp;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.xml.XMLConstants;
-import javax.xml.validation.Schema;
-
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
@@ -46,6 +37,14 @@
import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
import com.sun.org.apache.xerces.internal.xs.PSVIProvider;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import javax.xml.XMLConstants;
+import javax.xml.validation.Schema;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.HandlerBase;
@@ -186,7 +185,7 @@
// validation errors with a warning telling the user to set an
// ErrorHandler.
if (spf.isValidating()) {
- fInitErrorHandler = new DefaultValidationErrorHandler();
+ fInitErrorHandler = new DefaultValidationErrorHandler(xmlReader.getLocale());
xmlReader.setErrorHandler(fInitErrorHandler);
}
else {
@@ -685,6 +684,10 @@
return super.getProperty(name);
}
+ Locale getLocale() {
+ return fConfiguration.getLocale();
+ }
+
private void setSchemaValidatorFeature(String name, boolean value)
throws SAXNotRecognizedException, SAXNotSupportedException {
try {
--- ./jaxp/src/com/sun/org/apache/xerces/internal/util/URI.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xerces/internal/util/URI.java Wed May 07 19:26:26 2014 -0700
@@ -689,9 +689,13 @@
if (!initializeAuthority(uriSpec.substring(startPos, index))) {
index = startPos - 2;
}
- }
- else {
+ } else if (index < uriSpecLen) {
+ //Same as java.net.URI:
+ // DEVIATION: Allow empty authority prior to non-empty
+ // path, query component or fragment identifier
m_host = "";
+ } else {
+ throw new MalformedURIException("Expected authority.");
}
}
--- ./jaxp/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xerces/internal/utils/SecuritySupport.java Wed May 07 19:26:26 2014 -0700
@@ -211,7 +211,7 @@
if (i > 0) {
return uri.substring(i+1, uri.length());
}
- return "";
+ return uri;
}
/**
--- ./jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMAxisIterNodeList.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/DTMAxisIterNodeList.java Wed May 07 19:26:26 2014 -0700
@@ -105,15 +105,15 @@
*/
public Node item(int index) {
if (m_iter != null) {
- int node;
+ int node = 0;
int count = m_cachedNodes.size();
if (count > index) {
node = m_cachedNodes.elementAt(index);
return m_dtm.getNode(node);
} else if (m_last == -1) {
- while (((node = m_iter.next()) != DTMAxisIterator.END)
- && count <= index) {
+ while (count <= index
+ && ((node = m_iter.next()) != DTMAxisIterator.END)) {
m_cachedNodes.addElement(node);
count++;
}
--- ./jaxp/src/com/sun/org/apache/xpath/internal/XPathContext.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xpath/internal/XPathContext.java Wed May 07 19:26:26 2014 -0700
@@ -103,8 +103,7 @@
* the DTMManager, it really is a proxy for this object, which
* is the real DTMManager.
*/
- protected DTMManager m_dtmManager = DTMManager.newInstance(
- com.sun.org.apache.xpath.internal.objects.XMLStringFactoryImpl.getFactory());
+ protected DTMManager m_dtmManager = null;
/**
* Return the DTMManager object. Though XPathContext context extends
--- ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/JAXPExtensionsProvider.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/JAXPExtensionsProvider.java Wed May 07 19:26:26 2014 -0700
@@ -33,6 +33,7 @@
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import com.sun.org.apache.xpath.internal.functions.FuncExtFunction;
import java.util.Vector;
@@ -54,9 +55,12 @@
}
public JAXPExtensionsProvider(XPathFunctionResolver resolver,
- boolean featureSecureProcessing ) {
+ boolean featureSecureProcessing, FeatureManager featureManager ) {
this.resolver = resolver;
- this.extensionInvocationDisabled = featureSecureProcessing;
+ if (featureSecureProcessing &&
+ !featureManager.isFeatureEnabled(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION)) {
+ this.extensionInvocationDisabled = true;
+ }
}
/**
--- ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Wed May 07 19:26:26 2014 -0700
@@ -30,6 +30,7 @@
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
@@ -67,33 +68,36 @@
private boolean featureSecureProcessing = false;
private boolean useServicesMechanism = true;
+
+ private final FeatureManager featureManager;
+
/** Protected constructor to prevent direct instantiation; use compile()
* from the context.
*/
- protected XPathExpressionImpl() { };
+ protected XPathExpressionImpl() {
+ this(null, null, null, null,
+ false, true, new FeatureManager());
+ };
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
JAXPPrefixResolver prefixResolver,
XPathFunctionResolver functionResolver,
XPathVariableResolver variableResolver ) {
- this.xpath = xpath;
- this.prefixResolver = prefixResolver;
- this.functionResolver = functionResolver;
- this.variableResolver = variableResolver;
- this.featureSecureProcessing = false;
+ this(xpath, prefixResolver, functionResolver, variableResolver,
+ false, true, new FeatureManager());
};
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
- JAXPPrefixResolver prefixResolver,
- XPathFunctionResolver functionResolver,
- XPathVariableResolver variableResolver,
- boolean featureSecureProcessing, boolean useServicesMechanism ) {
+ JAXPPrefixResolver prefixResolver,XPathFunctionResolver functionResolver,
+ XPathVariableResolver variableResolver, boolean featureSecureProcessing,
+ boolean useServicesMechanism, FeatureManager featureManager ) {
this.xpath = xpath;
this.prefixResolver = prefixResolver;
this.functionResolver = functionResolver;
this.variableResolver = variableResolver;
this.featureSecureProcessing = featureSecureProcessing;
this.useServicesMechanism = useServicesMechanism;
+ this.featureManager = featureManager;
};
public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath ) {
@@ -111,7 +115,7 @@
com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
if ( functionResolver != null ) {
JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
- functionResolver, featureSecureProcessing );
+ functionResolver, featureSecureProcessing, featureManager );
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
} else {
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
--- ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java Wed May 07 19:26:26 2014 -0700
@@ -24,6 +24,8 @@
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
+import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase;
import javax.xml.XMLConstants;
import javax.xml.xpath.XPathFactory;
@@ -68,6 +70,8 @@
private boolean _useServicesMechanism = true;
+ private final FeatureManager _featureManager;
+
public XPathFactoryImpl() {
this(true);
}
@@ -77,9 +81,12 @@
}
public XPathFactoryImpl(boolean useServicesMechanism) {
+ _featureManager = new FeatureManager();
if (System.getSecurityManager() != null) {
_isSecureMode = true;
_isNotSecureProcessing = false;
+ _featureManager.setValue(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION,
+ FeaturePropertyBase.State.FSP, XalanConstants.FEATURE_FALSE);
}
this._useServicesMechanism = useServicesMechanism;
}
@@ -131,7 +138,8 @@
public javax.xml.xpath.XPath newXPath() {
return new com.sun.org.apache.xpath.internal.jaxp.XPathImpl(
xPathVariableResolver, xPathFunctionResolver,
- !_isNotSecureProcessing, _useServicesMechanism );
+ !_isNotSecureProcessing, _useServicesMechanism,
+ _featureManager );
}
/**
@@ -181,6 +189,10 @@
}
_isNotSecureProcessing = !value;
+ if (value && _featureManager != null) {
+ _featureManager.setValue(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION,
+ FeaturePropertyBase.State.FSP, XalanConstants.FEATURE_FALSE);
+ }
// all done processing feature
return;
@@ -192,6 +204,11 @@
return;
}
+ if (_featureManager != null &&
+ _featureManager.setValue(name, FeaturePropertyBase.State.APIPROPERTY, value)) {
+ return;
+ }
+
// unknown feature
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_FEATURE_UNKNOWN,
@@ -240,6 +257,14 @@
if (name.equals(XalanConstants.ORACLE_FEATURE_SERVICE_MECHANISM)) {
return _useServicesMechanism;
}
+
+ /** Check to see if the property is managed by the security manager **/
+ String propertyValue = (_featureManager != null) ?
+ _featureManager.getValueAsString(name) : null;
+ if (propertyValue != null) {
+ return _featureManager.isFeatureEnabled(name);
+ }
+
// unknown feature
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_GETTING_UNKNOWN_FEATURE,
--- ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Wed May 07 19:26:26 2014 -0700
@@ -35,6 +35,7 @@
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import org.w3c.dom.Node;
import org.w3c.dom.Document;
@@ -70,18 +71,20 @@
// extensions function need to throw XPathFunctionException
private boolean featureSecureProcessing = false;
private boolean useServiceMechanism = true;
+ private final FeatureManager featureManager;
XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr ) {
- this.origVariableResolver = this.variableResolver = vr;
- this.origFunctionResolver = this.functionResolver = fr;
+ this(vr, fr, false, true, new FeatureManager());
}
XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr,
- boolean featureSecureProcessing, boolean useServiceMechanism ) {
+ boolean featureSecureProcessing, boolean useServiceMechanism,
+ FeatureManager featureManager) {
this.origVariableResolver = this.variableResolver = vr;
this.origFunctionResolver = this.functionResolver = fr;
this.featureSecureProcessing = featureSecureProcessing;
this.useServiceMechanism = useServiceMechanism;
+ this.featureManager = featureManager;
}
/**
@@ -190,7 +193,7 @@
com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
if ( functionResolver != null ) {
JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
- functionResolver, featureSecureProcessing );
+ functionResolver, featureSecureProcessing, featureManager );
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
} else {
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
@@ -391,7 +394,7 @@
// Can have errorListener
XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
prefixResolver, functionResolver, variableResolver,
- featureSecureProcessing, useServiceMechanism );
+ featureSecureProcessing, useServiceMechanism, featureManager );
return ximpl;
} catch ( javax.xml.transform.TransformerException te ) {
throw new XPathExpressionException ( te ) ;
--- ./jaxp/src/javax/xml/xpath/XPathException.java Tue Mar 18 12:34:22 2014 -0700
+++ ./jaxp/src/javax/xml/xpath/XPathException.java Wed May 07 19:26:26 2014 -0700
@@ -26,6 +26,11 @@
package javax.xml.xpath;
import java.io.PrintWriter;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.io.InvalidClassException;
/**
* XPathException
represents a generic XPath exception.
@@ -36,7 +41,9 @@
*/
public class XPathException extends Exception {
- private final Throwable cause;
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField( "cause", Throwable.class )
+ };
/**
* Stream Unique Identifier.
@@ -62,7 +69,6 @@
if ( message == null ) {
throw new NullPointerException ( "message can't be null");
}
- this.cause = null;
}
/**
@@ -77,8 +83,7 @@
* @throws NullPointerException if cause
is null
.
*/
public XPathException(Throwable cause) {
- super();
- this.cause = cause;
+ super(cause);
if ( cause == null ) {
throw new NullPointerException ( "cause can't be null");
}
@@ -90,7 +95,47 @@
* @return Cause of this XPathException.
*/
public Throwable getCause() {
- return cause;
+ return super.getCause();
+ }
+
+ /**
+ * Writes "cause" field to the stream.
+ * The cause is got from the parent class.
+ *
+ * @param out stream used for serialization.
+ * @throws IOException thrown by ObjectOutputStream
+ *
+ */
+ private void writeObject(ObjectOutputStream out)
+ throws IOException
+ {
+ ObjectOutputStream.PutField fields = out.putFields();
+ fields.put("cause", (Throwable) super.getCause());
+ out.writeFields();
+ }
+
+ /**
+ * Reads the "cause" field from the stream.
+ * And initializes the "cause" if it wasn't
+ * done before.
+ *
+ * @param in stream used for deserialization
+ * @throws IOException thrown by ObjectInputStream
+ * @throws ClassNotFoundException thrown by ObjectInputStream
+ */
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ ObjectInputStream.GetField fields = in.readFields();
+ Throwable scause = (Throwable) fields.get("cause", null);
+
+ if (super.getCause() == null && scause != null) {
+ try {
+ super.initCause(scause);
+ } catch(IllegalStateException e) {
+ throw new InvalidClassException("Inconsistent state: two causes");
+ }
+ }
}
/**
--- ./jaxws/.hgtags Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/.hgtags Wed May 07 19:26:28 2014 -0700
@@ -417,3 +417,26 @@
0db5b891d1ba10211da0a8158551b35f00da7684 jdk7u55-b11
3834eb921dfd8d29d917a0c57bb9fdd9aa58c209 jdk7u55-b12
3b0da73591b1ea23c48aa7babc34ed776fc183f0 jdk7u55-b13
+5d726bf8fedc1f10d250e980653315919b7602f2 jdk7u55-b30
+81d0f297557c4a876727cabeb2bfcdf066a1fc9d jdk7u55-b14
+2d103c97c9bd0b3357e6d5e2b5b9ffb64c271288 jdk7u55-b31
+cb5f95263f620967f5097c5ff8e0b27cfb9e8c44 jdk7u60-b00
+f675dfce1e61a6ed01732ae7cfbae941791cba74 jdk7u60-b01
+8a3b9e8492a5ac4e2e0c166dbfc5d058be244377 jdk7u60-b02
+d4ba4e1ed3ecdef1ef7c3b7aaf62ff69fc105cb2 jdk7u60-b03
+bef313c7ff7a7a829f8f6a305bf0c3738ad99795 jdk7u60-b04
+30afd3e2e7044b2aa87ce00ab4301990e6d94d27 jdk7u60-b05
+dc6017fb9cde43bce92d403abc2821b741cf977c jdk7u60-b06
+0380cb9d4dc27ed8e2c4fc3502e3d94b0ae0c02d jdk7u60-b07
+d3896e59b04dc4022c3e0d04e8750b281249bbd2 jdk7u60-b08
+c85645aa77cedabeeb6e01373cdd81afd56c602e jdk7u60-b09
+79501d4561e4cfa96fd77e2e92eb6a1b6ad61005 jdk7u60-b10
+5d848774565b5e188d7ba915ce1cb09d8f3fdb87 jdk7u60-b11
+9d34f726e35b321072ce5bd0aad2e513b9fc972f jdk7u60-b12
+d941a701cf5ca11b2777fd1d0238e05e3c963e89 jdk7u60-b13
+43b5a7cf08e7ee018b1fa42a89510b4c381dc4c5 jdk7u60-b14
+d00389bf5439e5c42599604d2ebc909d26df8dcf jdk7u60-b15
+2fc16d3a321212abc0cc93462b22c4be7f693ab9 jdk7u60-b16
+b312ec543dc09db784e161eb89607d4afd4cab1e jdk7u60-b18
+b312ec543dc09db784e161eb89607d4afd4cab1e jdk7u60-b17
+1d21eb9011a060c7761c9a8a53e69d58bbea4893 jdk7u60-b19
--- ./jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/BoundedRangeStatisticImpl.java Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/src/share/jaxws_classes/com/sun/org/glassfish/external/statistics/impl/BoundedRangeStatisticImpl.java Wed May 07 19:26:28 2014 -0700
@@ -26,6 +26,7 @@
package com.sun.org.glassfish.external.statistics.impl;
+
import com.sun.org.glassfish.external.statistics.BoundedRangeStatistic;
import java.util.Map;
import java.lang.reflect.*;
--- ./jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceVisitor.java Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceVisitor.java Wed May 07 19:26:28 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, 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
@@ -204,24 +204,24 @@
}
portName = ClassNameInfo.getName(
d.getSimpleName().replace(
- SIGC_INNERCLASS,
- SIGC_UNDERSCORE));;
- packageName = d.getPackage().getQualifiedName();
- portName = webService != null && webService.name() != null && webService.name().length() >0 ?
- webService.name() : portName;
- serviceName = ClassNameInfo.getName(d.getQualifiedName())+SERVICE;
- serviceName = webService != null && webService.serviceName() != null &&
- webService.serviceName().length() > 0 ?
- webService.serviceName() : serviceName;
- wsdlNamespace = seiContext.getNamespaceURI();
- typeNamespace = wsdlNamespace;
+ SIGC_INNERCLASS,
+ SIGC_UNDERSCORE));;
+ packageName = d.getPackage().getQualifiedName();
+ portName = webService != null && webService.name() != null && webService.name().length() >0 ?
+ webService.name() : portName;
+ serviceName = ClassNameInfo.getName(d.getQualifiedName())+SERVICE;
+ serviceName = webService != null && webService.serviceName() != null &&
+ webService.serviceName().length() > 0 ?
+ webService.serviceName() : serviceName;
+ wsdlNamespace = seiContext.getNamespaceURI();
+ typeNamespace = wsdlNamespace;
- SOAPBinding soapBinding = d.getAnnotation(SOAPBinding.class);
- if (soapBinding != null) {
- pushedSOAPBinding = pushSOAPBinding(soapBinding, d, d);
- } else if (d.equals(typeDecl)) {
- pushedSOAPBinding = pushSOAPBinding(new MySOAPBinding(), d, d);
- }
+ SOAPBinding soapBinding = d.getAnnotation(SOAPBinding.class);
+ if (soapBinding != null) {
+ pushedSOAPBinding = pushSOAPBinding(soapBinding, d, d);
+ } else if (d.equals(typeDecl)) {
+ pushedSOAPBinding = pushSOAPBinding(new MySOAPBinding(), d, d);
+ }
}
public static boolean sameStyle(SOAPBinding.Style style, SOAPStyle soapStyle) {
@@ -235,7 +235,7 @@
}
protected boolean pushSOAPBinding(SOAPBinding soapBinding, Declaration bindingDecl,
- TypeDeclaration classDecl) {
+ TypeDeclaration classDecl) {
boolean changed = false;
if (!sameStyle(soapBinding.style(), soapStyle)) {
changed = true;
@@ -293,7 +293,7 @@
// abstract protected boolean shouldProcessWebService(WebService webService, InterfaceDeclaration intf);
-// abstract protected boolean shouldProcessWebService(WebService webService, ClassDeclaration decl);
+ // abstract protected boolean shouldProcessWebService(WebService webService, ClassDeclaration decl);
protected boolean shouldProcessWebService(WebService webService, InterfaceDeclaration intf) {
hasWebMethods = false;
if (webService == null)
@@ -315,9 +315,9 @@
return false;
hasWebMethods = hasWebMethods(classDecl);
SOAPBinding soapBinding = classDecl.getAnnotation(SOAPBinding.class);
- if(soapBinding != null && soapBinding.style() == SOAPBinding.Style.RPC && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
- builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE(soapBinding, classDecl));
- return false;
+ if(soapBinding != null && soapBinding.style() == SOAPBinding.Style.RPC && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
+ builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE(soapBinding, classDecl));
+ return false;
}
return isLegalImplementation(webService, classDecl);
}
@@ -345,8 +345,8 @@
if (webMethod.exclude()) {
if (webMethod.operationName().length() > 0)
builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE("operationName", d.getQualifiedName(), method.toString()));
- if (webMethod.action().length() > 0)
- builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE("action", d.getQualifiedName(), method.toString()));
+ if (webMethod.action().length() > 0)
+ builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE("action", d.getQualifiedName(), method.toString()));
} else {
return true;
}
@@ -382,7 +382,7 @@
}
private InterfaceDeclaration getEndpointInterfaceDecl(String endpointInterfaceName,
- ClassDeclaration d) {
+ ClassDeclaration d) {
InterfaceDeclaration intTypeDecl = null;
for (InterfaceType interfaceType : d.getSuperinterfaces()) {
if (endpointInterfaceName.equals(interfaceType.toString())) {
@@ -488,7 +488,7 @@
Collection modifiers = classDecl.getModifiers();
if (!modifiers.contains(Modifier.PUBLIC)){
builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_CLASS_NOT_PUBLIC(classDecl.getQualifiedName()));
- return false;
+ return false;
}
if (modifiers.contains(Modifier.FINAL) && !isStateful) {
builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_CLASS_IS_FINAL(classDecl.getQualifiedName()));
@@ -538,7 +538,7 @@
}
protected boolean classImplementsSEI(ClassDeclaration classDecl,
- InterfaceDeclaration intfDecl) {
+ InterfaceDeclaration intfDecl) {
for (InterfaceType interfaceType : classDecl.getSuperinterfaces()) {
if (interfaceType.getDeclaration().equals(intfDecl))
return true;
@@ -637,8 +637,8 @@
*/
if (!isLegalType(method.getReturnType())) {
builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_METHOD_RETURN_TYPE_CANNOT_IMPLEMENT_REMOTE(typeDecl.getQualifiedName(),
- method.getSimpleName(),
- method.getReturnType()));
+ method.getSimpleName(),
+ method.getReturnType()));
}
boolean isOneway = method.getAnnotation(Oneway.class) != null;
if (isOneway && !isValidOnewayMethod(method, typeDecl))
@@ -684,14 +684,14 @@
}
protected boolean isLegalParameter(ParameterDeclaration param,
- MethodDeclaration method,
- TypeDeclaration typeDecl,
- int paramIndex) {
+ MethodDeclaration method,
+ TypeDeclaration typeDecl,
+ int paramIndex) {
if (!isLegalType(param.getType())) {
builder.onError(param.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_METHOD_PARAMETER_TYPES_CANNOT_IMPLEMENT_REMOTE(typeDecl.getQualifiedName(),
- method.getSimpleName(),
- param.getSimpleName(),
- param.getType().toString()));
+ method.getSimpleName(),
+ param.getSimpleName(),
+ param.getType().toString()));
return false;
}
TypeMirror holderType;
--- ./jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportTool.java Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wscompile/WsimportTool.java Wed May 07 19:26:28 2014 -0700
@@ -334,7 +334,7 @@
if(options.verbose) {
listener.message(WscompileMessages.WSIMPORT_ARCHIVE_ARTIFACT(f, options.clientjar));
}
- String entry = f.getCanonicalPath().substring(base.length()+1);
+ String entry = f.getCanonicalPath().substring(base.length()+1).replace(File.separatorChar, '/');
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(f));
JarEntry jarEntry = new JarEntry(entry);
--- ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ModelBuilder.java Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ModelBuilder.java Wed May 07 19:26:28 2014 -0700
@@ -160,8 +160,8 @@
res = Messages.INCOMPATIBLE_API_VERSION;
throw new LinkageError( res.format(
- Which.which(XmlSchema.class),
- Which.which(ModelBuilder.class)
+ Which.which(XmlSchema.class),
+ Which.which(ModelBuilder.class)
));
}
}
@@ -176,8 +176,8 @@
} catch (NoSuchMethodError e) {
// we seem to be getting 1.0 runtime
throw new LinkageError( Messages.RUNNING_WITH_1_0_RUNTIME.format(
- Which.which(WhiteSpaceProcessor.class),
- Which.which(ModelBuilder.class)
+ Which.which(WhiteSpaceProcessor.class),
+ Which.which(ModelBuilder.class)
));
}
}
@@ -293,7 +293,7 @@
if(nav.isArray(t)) { // no need for checking byte[], because above typeInfoset.getTypeInfo() would return non-null
ArrayInfoImpl ai =
- createArrayInfo(upstream, t);
+ createArrayInfo(upstream, t);
addTypeName(ai);
typeInfoSet.add(ai);
return ai;
@@ -329,7 +329,7 @@
}
protected ElementInfoImpl createElementInfo(
- RegistryInfoImpl registryInfo, M m) throws IllegalAnnotationException {
+ RegistryInfoImpl registryInfo, M m) throws IllegalAnnotationException {
return new ElementInfoImpl(this,registryInfo,m);
}
--- ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MemoryData.java Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/MemoryData.java Wed May 07 19:26:28 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
--- ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/TempFiles.java Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/org/jvnet/mimepull/TempFiles.java Wed May 07 19:26:28 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
--- ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java Tue Mar 18 12:34:51 2014 -0700
+++ ./jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java Wed May 07 19:26:28 2014 -0700
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.xml.internal.ws.client;
import com.sun.istack.internal.NotNull;
@@ -140,8 +141,8 @@
/**
* Information about SEI, keyed by their interface type.
*/
- // private final Map seiContext = new HashMap();
- private final Map seiContext = new HashMap();
+ // private final Map seiContext = new HashMap();
+ private final Map seiContext = new HashMap();
// This executor is used for all the async invocations for all proxies
// created from this service. But once the proxy is created, then changing
@@ -166,8 +167,8 @@
public WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class extends Service> serviceClass) {
this(
- wsdlDocumentLocation==null ? null : new StreamSource(wsdlDocumentLocation.toExternalForm()),
- serviceName,serviceClass);
+ wsdlDocumentLocation==null ? null : new StreamSource(wsdlDocumentLocation.toExternalForm()),
+ serviceName,serviceClass);
}
/**
@@ -204,10 +205,10 @@
if(wsdl == null){
if(serviceClass != Service.class){
WebServiceClient wsClient = AccessController.doPrivileged(new PrivilegedAction() {
- public WebServiceClient run() {
- return serviceClass.getAnnotation(WebServiceClient.class);
- }
- });
+ public WebServiceClient run() {
+ return serviceClass.getAnnotation(WebServiceClient.class);
+ }
+ });
String wsdlLocation = wsClient.wsdlLocation();
wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation));
wsdl = new StreamSource(wsdlLocation);
@@ -221,8 +222,8 @@
service = model.getService(this.serviceName);
if (service == null)
throw new WebServiceException(
- ClientMessages.INVALID_SERVICE_NAME(this.serviceName,
- buildNameList(model.getServices().keySet())));
+ ClientMessages.INVALID_SERVICE_NAME(this.serviceName,
+ buildNameList(model.getServices().keySet())));
// fill in statically known ports
for (WSDLPortImpl port : service.getPorts())
ports.put(port.getName(), new PortInfo(this, port));
@@ -255,7 +256,7 @@
private WSDLModelImpl parseWSDL(URL wsdlDocumentLocation, Source wsdlSource) {
try {
return RuntimeWSDLParser.parse(wsdlDocumentLocation, wsdlSource, createDefaultCatalogResolver(),
- true, getContainer(), ServiceFinder.find(WSDLParserExtension.class).toArray());
+ true, getContainer(), ServiceFinder.find(WSDLParserExtension.class).toArray());
} catch (IOException e) {
throw new WebServiceException(e);
} catch (XMLStreamException e) {
@@ -345,7 +346,7 @@
//get the first port corresponding to the SEI
WSDLPortImpl port = wsdlService.getMatchingPort(portTypeName);
if (port == null)
- throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName));
+ throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName));
QName portName = port.getName();
return getPort(portName, portInterface,features);
}
@@ -431,8 +432,8 @@
binding.setMode(mode);
Dispatch