--- a/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -281,3 +281,4 @@
41df50e7303daf73c0d661ef601c4fe250915de5 jdk9-b36
b409bc51bc23cfd51f2bd04ea919ec83535af9d0 jdk9-b37
948cceef81ba4cb34bc233e7cc5952951ff04e88 jdk9-b38
+4e7c4d692e934cb9023af8201e7c2b510e9c4ee1 jdk9-b39
--- a/.hgtags-top-repo Fri Nov 14 17:53:46 2014 +0300
+++ b/.hgtags-top-repo Mon Nov 17 12:32:27 2014 -0800
@@ -281,3 +281,4 @@
201d4e235d597a25a2d3ee1404394789ba386119 jdk9-b36
723a67b0c442391447b1d8aad8b249d06d1032e8 jdk9-b37
d42c0a90afc3c66ca87543076ec9aafd4b4680de jdk9-b38
+512dbbeb1730edcebfec873fc3f1455660b32000 jdk9-b39
--- a/corba/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/corba/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -281,3 +281,4 @@
ffd90c81d4ef9d94d880fc852e2fc482ecd9b374 jdk9-b36
7e9add74ad50841fb39dae75db56374aefa1de4c jdk9-b37
8acf056126e819cf536eef02aee0f61f207a6b52 jdk9-b38
+53bf36cb722db50815712258a77cb6bbe25a2f5f jdk9-b39
--- a/corba/src/java.corba/share/classes/org/omg/CORBA/ORB.java Fri Nov 14 17:53:46 2014 +0300
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/ORB.java Mon Nov 17 12:32:27 2014 -0800
@@ -166,16 +166,15 @@
*
*
* @implNote
- * As described above it is possible to specify, at runtime, an alternative ORBSingleton class and
- * an alternative ORB implementation class, via the system properties {@code org.omg.CORBA.ORBSingletonClass}
- * and {@code org.omg.CORBA.ORBClass} respectively.
- * The class loading strategy is organized, such that, in the case of the ORBSingleton
- * the system class loader is used to load the alternative singleton ORB.
- * Thus, it is necessary that an application's CLASSPATH
- * includes the classes for this alternative ORBSingleton, when specified.
+ * When a singleton ORB is configured via the system property,
+ * or orb.properties, it will be
+ * located, and loaded via the system class loader.
+ * Thus, where appropriate, it is necessary that
+ * the classes for this alternative ORBSingleton are available on the application's class path.
+ * It should be noted that the singleton ORB is system wide.
*
- * In the case of specifying an alternative ORB implementation class, the loading
- * strategy will use the thread context class loader, as appropriate.
+ * When a per-application ORB is created via the 2-arg init methods,
+ * then it will be located using the thread context class loader.
*
* @since JDK1.2
*/
@@ -295,6 +294,11 @@
* creating <code>TypeCode</code> objects are invoked.
*
* @return the singleton ORB
+ *
+ * @implNote
+ * When configured via the system property, or orb.properties,
+ * the system-wide singleton ORB is located via the
+ * system class loader.
*/
public static synchronized ORB init() {
if (singleton == null) {
@@ -354,6 +358,10 @@
* method; may be <code>null</code>
* @param props application-specific properties; may be <code>null</code>
* @return the newly-created ORB instance
+ *
+ * @implNote
+ * When configured via the system property, or orb.properties,
+ * the ORB is located via the thread context class loader.
*/
public static ORB init(String[] args, Properties props) {
//
@@ -392,6 +400,10 @@
* @param app the applet; may be <code>null</code>
* @param props applet-specific properties; may be <code>null</code>
* @return the newly-created ORB instance
+ *
+ * @implNote
+ * When configured via the system property, or orb.properties,
+ * the ORB is located via the thread context class loader.
*/
public static ORB init(Applet app, Properties props) {
String className;
--- a/hotspot/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -441,3 +441,4 @@
464ab653fbb17eb518d8ef60f8df301de7ef00d0 jdk9-b36
b1c2dd843f247a1db19e1e85eb62ca405f72dc26 jdk9-b37
c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
+9cb75e5e394827ccbaf2e15524108a412dc4ddc5 jdk9-b39
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CodeCacheSweeperThread.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2000, 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 sun.jvm.hotspot.runtime;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+
+public class CodeCacheSweeperThread extends JavaThread {
+ public CodeCacheSweeperThread(Address addr) {
+ super(addr);
+ }
+
+ public boolean isJavaThread() { return false; }
+ public boolean isHiddenFromExternalView() { return true; }
+ public boolean isCodeCacheSweeperThread() { return true; }
+
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java Mon Nov 17 12:32:27 2014 -0800
@@ -118,9 +118,10 @@
return VM.getVM().getThreads().createJavaThreadWrapper(threadAddr);
}
- /** NOTE: for convenience, this differs in definition from the
- underlying VM. Only "pure" JavaThreads return true;
- CompilerThreads and JVMDIDebuggerThreads return false. FIXME:
+ /** NOTE: for convenience, this differs in definition from the underlying VM.
+ Only "pure" JavaThreads return true; CompilerThreads, the CodeCacheSweeperThread,
+ JVMDIDebuggerThreads return false.
+ FIXME:
consider encapsulating platform-specific functionality in an
object instead of using inheritance (which is the primary reason
we can't traverse CompilerThreads, etc; didn't want to have, for
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java Mon Nov 17 12:32:27 2014 -0800
@@ -111,14 +111,15 @@
return allocatedBytesField.getValue(addr);
}
- public boolean isVMThread() { return false; }
- public boolean isJavaThread() { return false; }
- public boolean isCompilerThread() { return false; }
- public boolean isHiddenFromExternalView() { return false; }
- public boolean isJvmtiAgentThread() { return false; }
- public boolean isWatcherThread() { return false; }
+ public boolean isVMThread() { return false; }
+ public boolean isJavaThread() { return false; }
+ public boolean isCompilerThread() { return false; }
+ public boolean isCodeCacheSweeperThread() { return false; }
+ public boolean isHiddenFromExternalView() { return false; }
+ public boolean isJvmtiAgentThread() { return false; }
+ public boolean isWatcherThread() { return false; }
public boolean isConcurrentMarkSweepThread() { return false; }
- public boolean isServiceThread() { return false; }
+ public boolean isServiceThread() { return false; }
/** Memory operations */
public void oopsDo(AddressVisitor oopVisitor) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Mon Nov 17 12:32:27 2014 -0800
@@ -120,6 +120,7 @@
virtualConstructor.addMapping("JavaThread", JavaThread.class);
if (!VM.getVM().isCore()) {
virtualConstructor.addMapping("CompilerThread", CompilerThread.class);
+ virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class);
}
// for now, use JavaThread itself. fix it later with appropriate class if needed
virtualConstructor.addMapping("SurrogateLockerThread", JavaThread.class);
@@ -164,7 +165,7 @@
return thread;
} catch (Exception e) {
throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr +
- " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, or SurrogateLockerThread)", e);
+ " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, SurrogateLockerThread, or CodeCacheSweeperThread)", e);
}
}
@@ -201,7 +202,7 @@
public List getPendingThreads(ObjectMonitor monitor) {
List pendingThreads = new ArrayList();
for (JavaThread thread = first(); thread != null; thread = thread.next()) {
- if (thread.isCompilerThread()) {
+ if (thread.isCompilerThread() || thread.isCodeCacheSweeperThread()) {
continue;
}
ObjectMonitor pending = thread.getCurrentPendingMonitor();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Mon Nov 17 12:32:27 2014 -0800
@@ -836,6 +836,7 @@
// Java Threads
vmType2Class["JavaThread"] = sapkg.runtime.JavaThread;
vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread;
+vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread;
vmType2Class["SurrogateLockerThread"] = sapkg.runtime.JavaThread;
vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread;
--- a/hotspot/make/solaris/makefiles/vm.make Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/make/solaris/makefiles/vm.make Mon Nov 17 12:32:27 2014 -0800
@@ -143,7 +143,7 @@
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks
-LIBS += -lkstat -lpicl
+LIBS += -lkstat
# By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM
--- a/hotspot/make/windows/makefiles/compile.make Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/make/windows/makefiles/compile.make Mon Nov 17 12:32:27 2014 -0800
@@ -158,7 +158,7 @@
!endif
LD_FLAGS= $(LD_FLAGS) kernel32.lib user32.lib gdi32.lib winspool.lib \
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
- uuid.lib Wsock32.lib winmm.lib /nologo /machine:$(MACHINE) /opt:REF \
+ uuid.lib Wsock32.lib winmm.lib version.lib /nologo /machine:$(MACHINE) /opt:REF \
/opt:ICF,8
!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
LD_FLAGS= $(LD_FLAGS) /map /debug
--- a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -237,7 +237,7 @@
// handle arguments
// Warning: We use reg arg slot 00 temporarily to return the RegArgSignature
// back to the code that pops the arguments into the CPU registers
- SlowSignatureHandler(m, (address)from, m->is_static() ? to+2 : to+1, to).iterate(UCONST64(-1));
+ SlowSignatureHandler(m, (address)from, m->is_static() ? to+2 : to+1, to).iterate((uint64_t)CONST64(-1));
// return result handler
return Interpreter::result_handler(m->result_type());
IRT_END
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -60,10 +60,10 @@
static jlong fp_signmask_pool[(4+1)*2]; // 4*128bits(data) + 128bits(alignment)
// Static initialization during VM startup.
-static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF));
-static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF));
-static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
-static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
+static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF));
+static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF));
+static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], (jlong)UCONST64(0x8000000080000000), (jlong)UCONST64(0x8000000080000000));
+static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], (jlong)UCONST64(0x8000000000000000), (jlong)UCONST64(0x8000000000000000));
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1597,7 +1597,7 @@
__ movl(rdx, 0x80000000);
__ xorl(rax, rax);
#else
- __ mov64(rax, CONST64(0x8000000000000000));
+ __ mov64(rax, UCONST64(0x8000000000000000));
#endif // _LP64
__ jmp(do_return);
--- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -135,7 +135,7 @@
methodHandle m(thread, (Method*)method);
assert(m->is_native(), "sanity check");
// handle arguments
- SlowSignatureHandler(m, (address)from, to + 1).iterate(UCONST64(-1));
+ SlowSignatureHandler(m, (address)from, to + 1).iterate((uint64_t)CONST64(-1));
// return result handler
return Interpreter::result_handler(m->result_type());
IRT_END
--- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -487,7 +487,7 @@
assert(m->is_native(), "sanity check");
// handle arguments
- SlowSignatureHandler(m, (address)from, to + 1).iterate(UCONST64(-1));
+ SlowSignatureHandler(m, (address)from, to + 1).iterate((uint64_t)CONST64(-1));
// return result handler
return Interpreter::result_handler(m->result_type());
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -865,14 +865,19 @@
if (supports_bmi1()) {
// tzcnt does not require VEX prefix
if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
- UseCountTrailingZerosInstruction = true;
+ if (!UseBMI1Instructions && !FLAG_IS_DEFAULT(UseBMI1Instructions)) {
+ // Don't use tzcnt if BMI1 is switched off on command line.
+ UseCountTrailingZerosInstruction = false;
+ } else {
+ UseCountTrailingZerosInstruction = true;
+ }
}
} else if (UseCountTrailingZerosInstruction) {
warning("tzcnt instruction is not available on this CPU");
FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
}
- // BMI instructions use an encoding with VEX prefix.
+ // BMI instructions (except tzcnt) use an encoding with VEX prefix.
// VEX prefix is generated only when AVX > 0.
if (supports_bmi1() && supports_avx()) {
if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
--- a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -155,7 +155,7 @@
intptr_t *buf = (intptr_t *) stack->alloc(required_words * wordSize);
SlowSignatureHandlerGenerator sshg(methodHandle(thread, method), buf);
- sshg.generate(UCONST64(-1));
+ sshg.generate((uint64_t)CONST64(-1));
SignatureHandler *handler = sshg.handler();
handler->finalize();
--- a/hotspot/src/os/aix/vm/os_aix.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/aix/vm/os_aix.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1641,7 +1641,8 @@
char* rp = realpath((char *)dlinfo.dli_fname, buf);
assert(rp != NULL, "error in realpath(): maybe the 'path' argument is too long?");
- strcpy(saved_jvm_path, buf);
+ strncpy(saved_jvm_path, buf, sizeof(saved_jvm_path));
+ saved_jvm_path[sizeof(saved_jvm_path) - 1] = '\0';
}
void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
@@ -3829,11 +3830,6 @@
return JNI_OK;
}
-// this is called at the end of vm_initialization
-void os::init_3(void) {
- return;
-}
-
// Mark the polling page as unreadable
void os::make_polling_page_unreadable(void) {
if (!guard_memory((char*)_polling_page, Aix::page_size())) {
@@ -4137,15 +4133,6 @@
return 1;
}
-int os::socket_available(int fd, jint *pbytes) {
- // Linux doc says EINTR not returned, unlike Solaris
- int ret = ::ioctl(fd, FIONREAD, pbytes);
-
- //%% note ioctl can return 0 when successful, JVM_SocketAvailable
- // is expected to return 0 on failure and 1 on success to the jdk.
- return (ret < 0) ? 0 : 1;
-}
-
// Map a block of memory.
char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
--- a/hotspot/src/os/aix/vm/os_aix.inline.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/aix/vm/os_aix.inline.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -178,92 +178,14 @@
return os::send(fd, buf, nBytes, flags);
}
-inline int os::timeout(int fd, long timeout) {
- julong prevtime,newtime;
- struct timeval t;
-
- gettimeofday(&t, NULL);
- prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
-
- for(;;) {
- struct pollfd pfd;
-
- pfd.fd = fd;
- pfd.events = POLLIN | POLLERR;
-
- int res = ::poll(&pfd, 1, timeout);
-
- if (res == OS_ERR && errno == EINTR) {
-
- // On Linux any value < 0 means "forever"
-
- if(timeout >= 0) {
- gettimeofday(&t, NULL);
- newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if(timeout <= 0)
- return OS_OK;
- prevtime = newtime;
- }
- } else
- return res;
- }
-}
-
-inline int os::listen(int fd, int count) {
- return ::listen(fd, count);
-}
-
inline int os::connect(int fd, struct sockaddr* him, socklen_t len) {
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
}
-inline int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
- // Linux doc says this can't return EINTR, unlike accept() on Solaris.
- // But see attachListener_linux.cpp, LinuxAttachListener::dequeue().
- return (int)::accept(fd, him, len);
-}
-
-inline int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
- sockaddr* from, socklen_t* fromlen) {
- RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
-}
-
-inline int os::sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr* to, socklen_t tolen) {
- RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
-}
-
-inline int os::socket_shutdown(int fd, int howto) {
- return ::shutdown(fd, howto);
-}
-
-inline int os::bind(int fd, struct sockaddr* him, socklen_t len) {
- return ::bind(fd, him, len);
-}
-
-inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
- return ::getsockname(fd, him, len);
-}
-
-inline int os::get_host_name(char* name, int namelen) {
- return ::gethostname(name, namelen);
-}
-
inline struct hostent* os::get_host_by_name(char* name) {
return ::gethostbyname(name);
}
-inline int os::get_sock_opt(int fd, int level, int optname,
- char* optval, socklen_t* optlen) {
- return ::getsockopt(fd, level, optname, optval, optlen);
-}
-
-inline int os::set_sock_opt(int fd, int level, int optname,
- const char* optval, socklen_t optlen) {
- return ::setsockopt(fd, level, optname, optval, optlen);
-}
-
inline bool os::supports_monotonic_clock() {
// mread_real_time() is monotonic on AIX (see os::javaTimeNanos() comments)
return true;
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -506,6 +506,7 @@
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
+ os::closedir(dirp);
return;
}
@@ -853,6 +854,9 @@
//
if (!is_directory_secure(dirname)) {
FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ if (luser != user) {
+ FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ }
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1875,6 +1875,7 @@
}
strncpy(saved_jvm_path, buf, MAXPATHLEN);
+ saved_jvm_path[MAXPATHLEN - 1] = '\0';
}
void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
@@ -3635,9 +3636,6 @@
return JNI_OK;
}
-// this is called at the end of vm_initialization
-void os::init_3(void) { }
-
// Mark the polling page as unreadable
void os::make_polling_page_unreadable(void) {
if (!guard_memory((char*)_polling_page, Bsd::page_size())) {
@@ -3958,21 +3956,6 @@
return 1;
}
-int os::socket_available(int fd, jint *pbytes) {
- if (fd < 0) {
- return OS_OK;
- }
-
- int ret;
-
- RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret);
-
- //%% note ioctl can return 0 when successful, JVM_SocketAvailable
- // is expected to return 0 on failure and 1 on success to the jdk.
-
- return (ret == OS_ERR) ? 0 : 1;
-}
-
// Map a block of memory.
char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
@@ -4133,7 +4116,18 @@
}
-// Refer to the comments in os_solaris.cpp park-unpark.
+// Refer to the comments in os_solaris.cpp park-unpark. The next two
+// comment paragraphs are worth repeating here:
+//
+// Assumption:
+// Only one parker can exist on an event, which is why we allocate
+// them per-thread. Multiple unparkers can coexist.
+//
+// _Event serves as a restricted-range semaphore.
+// -1 : thread is blocked, i.e. there is a waiter
+// 0 : neutral: thread is running or ready,
+// could have been signaled after a wait started
+// 1 : signaled - thread is running or ready
//
// Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can
// hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable.
@@ -4218,6 +4212,11 @@
}
void os::PlatformEvent::park() { // AKA "down()"
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
// Invariant: Only the thread associated with the Event/PlatformEvent
// may call park().
// TODO: assert that _Assoc != NULL or _Assoc == Self
@@ -4255,6 +4254,11 @@
}
int os::PlatformEvent::park(jlong millis) {
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
guarantee(_nParked == 0, "invariant");
int v;
@@ -4318,11 +4322,11 @@
void os::PlatformEvent::unpark() {
// Transitions for _Event:
- // 0 :=> 1
- // 1 :=> 1
- // -1 :=> either 0 or 1; must signal target thread
- // That is, we can safely transition _Event from -1 to either
- // 0 or 1.
+ // 0 => 1 : just return
+ // 1 => 1 : just return
+ // -1 => either 0 or 1; must signal target thread
+ // That is, we can safely transition _Event from -1 to either
+ // 0 or 1.
// See also: "Semaphores in Plan 9" by Mullender & Cox
//
// Note: Forcing a transition from "-1" to "1" on an unpark() means
@@ -4345,15 +4349,16 @@
status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock");
if (AnyWaiters != 0) {
+ // Note that we signal() *after* dropping the lock for "immortal" Events.
+ // This is safe and avoids a common class of futile wakeups. In rare
+ // circumstances this can cause a thread to return prematurely from
+ // cond_{timed}wait() but the spurious wakeup is benign and the victim
+ // will simply re-test the condition and re-park itself.
+ // This provides particular benefit if the underlying platform does not
+ // provide wait morphing.
status = pthread_cond_signal(_cond);
assert_status(status == 0, status, "cond_signal");
}
-
- // Note that we signal() _after dropping the lock for "immortal" Events.
- // This is safe and avoids a common class of futile wakeups. In rare
- // circumstances this can cause a thread to return prematurely from
- // cond_{timed}wait() but the spurious wakeup is benign and the victim will
- // simply re-test the condition and re-park itself.
}
--- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -181,91 +181,14 @@
return os::send(fd, buf, nBytes, flags);
}
-inline int os::timeout(int fd, long timeout) {
- julong prevtime,newtime;
- struct timeval t;
-
- gettimeofday(&t, NULL);
- prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
-
- for(;;) {
- struct pollfd pfd;
-
- pfd.fd = fd;
- pfd.events = POLLIN | POLLERR;
-
- int res = ::poll(&pfd, 1, timeout);
-
- if (res == OS_ERR && errno == EINTR) {
-
- // On Bsd any value < 0 means "forever"
-
- if(timeout >= 0) {
- gettimeofday(&t, NULL);
- newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if(timeout <= 0)
- return OS_OK;
- prevtime = newtime;
- }
- } else
- return res;
- }
-}
-
-inline int os::listen(int fd, int count) {
- return ::listen(fd, count);
-}
-
inline int os::connect(int fd, struct sockaddr* him, socklen_t len) {
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
}
-inline int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
- // At least OpenBSD and FreeBSD can return EINTR from accept.
- RESTARTABLE_RETURN_INT(::accept(fd, him, len));
-}
-
-inline int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
- sockaddr* from, socklen_t* fromlen) {
- RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
-}
-
-inline int os::sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr *to, socklen_t tolen) {
- RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
-}
-
-inline int os::socket_shutdown(int fd, int howto) {
- return ::shutdown(fd, howto);
-}
-
-inline int os::bind(int fd, struct sockaddr* him, socklen_t len) {
- return ::bind(fd, him, len);
-}
-
-inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
- return ::getsockname(fd, him, len);
-}
-
-inline int os::get_host_name(char* name, int namelen) {
- return ::gethostname(name, namelen);
-}
-
inline struct hostent* os::get_host_by_name(char* name) {
return ::gethostbyname(name);
}
-inline int os::get_sock_opt(int fd, int level, int optname,
- char *optval, socklen_t* optlen) {
- return ::getsockopt(fd, level, optname, optval, optlen);
-}
-
-inline int os::set_sock_opt(int fd, int level, int optname,
- const char* optval, socklen_t optlen) {
- return ::setsockopt(fd, level, optname, optval, optlen);
-}
-
inline bool os::supports_monotonic_clock() {
#ifdef __APPLE__
return true;
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -506,6 +506,7 @@
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
+ os::closedir(dirp);
return;
}
@@ -872,6 +873,9 @@
//
if (!is_directory_secure(dirname)) {
FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ if (luser != user) {
+ FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ }
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -163,35 +163,6 @@
// Declarations
static void unpackTime(timespec* absTime, bool isAbsolute, jlong time);
-#ifdef JAVASE_EMBEDDED
-class MemNotifyThread: public Thread {
- friend class VMStructs;
- public:
- virtual void run();
-
- private:
- static MemNotifyThread* _memnotify_thread;
- int _fd;
-
- public:
-
- // Constructor
- MemNotifyThread(int fd);
-
- // Tester
- bool is_memnotify_thread() const { return true; }
-
- // Printing
- char* name() const { return (char*)"Linux MemNotify Thread"; }
-
- // Returns the single instance of the MemNotifyThread
- static MemNotifyThread* memnotify_thread() { return _memnotify_thread; }
-
- // Create and start the single instance of MemNotifyThread
- static void start();
-};
-#endif // JAVASE_EMBEDDED
-
// utility functions
static int SR_initialize();
@@ -384,7 +355,10 @@
// Found the full path to libjvm.so.
// Now cut the path to <java_home>/jre if we can.
- *(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
+ pslash = strrchr(buf, '/');
+ if (pslash != NULL) {
+ *pslash = '\0'; // Get rid of /libjvm.so.
+ }
pslash = strrchr(buf, '/');
if (pslash != NULL) {
*pslash = '\0'; // Get rid of /{client|server|hotspot}.
@@ -1223,7 +1197,7 @@
i = 0;
if (s) {
// Skip blank chars
- do s++; while (isspace(*s));
+ do { s++; } while (s && isspace(*s));
#define _UFM UINTX_FORMAT
#define _DFM INTX_FORMAT
@@ -2372,6 +2346,9 @@
// Check the current module name "libjvm.so".
p = strrchr(buf, '/');
+ if (p == NULL) {
+ return;
+ }
assert(strstr(p, "/libjvm") == p, "invalid library name");
rp = realpath(java_home_var, buf);
@@ -2405,6 +2382,7 @@
}
strncpy(saved_jvm_path, buf, MAXPATHLEN);
+ saved_jvm_path[MAXPATHLEN - 1] = '\0';
}
void os::print_jni_name_prefix_on(outputStream* st, int args_size) {
@@ -4866,17 +4844,6 @@
return JNI_OK;
}
-// this is called at the end of vm_initialization
-void os::init_3(void) {
-#ifdef JAVASE_EMBEDDED
- // Start the MemNotifyThread
- if (LowMemoryProtection) {
- MemNotifyThread::start();
- }
- return;
-#endif
-}
-
// Mark the polling page as unreadable
void os::make_polling_page_unreadable(void) {
if (!guard_memory((char*)_polling_page, Linux::page_size())) {
@@ -5103,9 +5070,38 @@
errno = ENAMETOOLONG;
return -1;
}
- int fd;
-
- fd = ::open64(path, oflag, mode);
+
+ // All file descriptors that are opened in the Java process and not
+ // specifically destined for a subprocess should have the close-on-exec
+ // flag set. If we don't set it, then careless 3rd party native code
+ // might fork and exec without closing all appropriate file descriptors
+ // (e.g. as we do in closeDescriptors in UNIXProcess.c), and this in
+ // turn might:
+ //
+ // - cause end-of-file to fail to be detected on some file
+ // descriptors, resulting in mysterious hangs, or
+ //
+ // - might cause an fopen in the subprocess to fail on a system
+ // suffering from bug 1085341.
+ //
+ // (Yes, the default setting of the close-on-exec flag is a Unix
+ // design flaw)
+ //
+ // See:
+ // 1085341: 32-bit stdio routines should support file descriptors >255
+ // 4843136: (process) pipe file descriptor from Runtime.exec not being closed
+ // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
+ //
+ // Modern Linux kernels (after 2.6.23 2007) support O_CLOEXEC with open().
+ // O_CLOEXEC is preferable to using FD_CLOEXEC on an open file descriptor
+ // because it saves a system call and removes a small window where the flag
+ // is unset. On ancient Linux kernels the O_CLOEXEC flag will be ignored
+ // and we fall back to using FD_CLOEXEC (see below).
+#ifdef O_CLOEXEC
+ oflag |= O_CLOEXEC;
+#endif
+
+ int fd = ::open64(path, oflag, mode);
if (fd == -1) return -1;
//If the open succeeded, the file might still be a directory
@@ -5126,32 +5122,17 @@
}
}
- // All file descriptors that are opened in the JVM and not
- // specifically destined for a subprocess should have the
- // close-on-exec flag set. If we don't set it, then careless 3rd
- // party native code might fork and exec without closing all
- // appropriate file descriptors (e.g. as we do in closeDescriptors in
- // UNIXProcess.c), and this in turn might:
- //
- // - cause end-of-file to fail to be detected on some file
- // descriptors, resulting in mysterious hangs, or
- //
- // - might cause an fopen in the subprocess to fail on a system
- // suffering from bug 1085341.
- //
- // (Yes, the default setting of the close-on-exec flag is a Unix
- // design flaw)
- //
- // See:
- // 1085341: 32-bit stdio routines should support file descriptors >255
- // 4843136: (process) pipe file descriptor from Runtime.exec not being closed
- // 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
- //
#ifdef FD_CLOEXEC
- {
+ // Validate that the use of the O_CLOEXEC flag on open above worked.
+ // With recent kernels, we will perform this check exactly once.
+ static sig_atomic_t O_CLOEXEC_is_known_to_work = 0;
+ if (!O_CLOEXEC_is_known_to_work) {
int flags = ::fcntl(fd, F_GETFD);
if (flags != -1) {
- ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ if ((flags & FD_CLOEXEC) != 0)
+ O_CLOEXEC_is_known_to_work = 1;
+ else
+ ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}
}
#endif
@@ -5211,15 +5192,6 @@
return 1;
}
-int os::socket_available(int fd, jint *pbytes) {
- // Linux doc says EINTR not returned, unlike Solaris
- int ret = ::ioctl(fd, FIONREAD, pbytes);
-
- //%% note ioctl can return 0 when successful, JVM_SocketAvailable
- // is expected to return 0 on failure and 1 on success to the jdk.
- return (ret < 0) ? 0 : 1;
-}
-
// Map a block of memory.
char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
@@ -5349,7 +5321,7 @@
if (s == NULL) return -1;
// Skip blank chars
- do s++; while (isspace(*s));
+ do { s++; } while (s && isspace(*s));
count = sscanf(s,"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu",
&cdummy, &idummy, &idummy, &idummy, &idummy, &idummy,
@@ -5410,7 +5382,18 @@
}
-// Refer to the comments in os_solaris.cpp park-unpark.
+// Refer to the comments in os_solaris.cpp park-unpark. The next two
+// comment paragraphs are worth repeating here:
+//
+// Assumption:
+// Only one parker can exist on an event, which is why we allocate
+// them per-thread. Multiple unparkers can coexist.
+//
+// _Event serves as a restricted-range semaphore.
+// -1 : thread is blocked, i.e. there is a waiter
+// 0 : neutral: thread is running or ready,
+// could have been signaled after a wait started
+// 1 : signaled - thread is running or ready
//
// Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can
// hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable.
@@ -5509,6 +5492,11 @@
}
void os::PlatformEvent::park() { // AKA "down()"
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
// Invariant: Only the thread associated with the Event/PlatformEvent
// may call park().
// TODO: assert that _Assoc != NULL or _Assoc == Self
@@ -5546,6 +5534,11 @@
}
int os::PlatformEvent::park(jlong millis) {
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
guarantee(_nParked == 0, "invariant");
int v;
@@ -5609,11 +5602,11 @@
void os::PlatformEvent::unpark() {
// Transitions for _Event:
- // 0 :=> 1
- // 1 :=> 1
- // -1 :=> either 0 or 1; must signal target thread
- // That is, we can safely transition _Event from -1 to either
- // 0 or 1.
+ // 0 => 1 : just return
+ // 1 => 1 : just return
+ // -1 => either 0 or 1; must signal target thread
+ // That is, we can safely transition _Event from -1 to either
+ // 0 or 1.
// See also: "Semaphores in Plan 9" by Mullender & Cox
//
// Note: Forcing a transition from "-1" to "1" on an unpark() means
@@ -5636,15 +5629,16 @@
status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock");
if (AnyWaiters != 0) {
+ // Note that we signal() *after* dropping the lock for "immortal" Events.
+ // This is safe and avoids a common class of futile wakeups. In rare
+ // circumstances this can cause a thread to return prematurely from
+ // cond_{timed}wait() but the spurious wakeup is benign and the victim
+ // will simply re-test the condition and re-park itself.
+ // This provides particular benefit if the underlying platform does not
+ // provide wait morphing.
status = pthread_cond_signal(_cond);
assert_status(status == 0, status, "cond_signal");
}
-
- // Note that we signal() _after dropping the lock for "immortal" Events.
- // This is safe and avoids a common class of futile wakeups. In rare
- // circumstances this can cause a thread to return prematurely from
- // cond_{timed}wait() but the spurious wakeup is benign and the victim will
- // simply re-test the condition and re-park itself.
}
@@ -6006,82 +6000,6 @@
return strlen(buffer);
}
-#ifdef JAVASE_EMBEDDED
-//
-// A thread to watch the '/dev/mem_notify' device, which will tell us when the OS is running low on memory.
-//
-MemNotifyThread* MemNotifyThread::_memnotify_thread = NULL;
-
-// ctor
-//
-MemNotifyThread::MemNotifyThread(int fd): Thread() {
- assert(memnotify_thread() == NULL, "we can only allocate one MemNotifyThread");
- _fd = fd;
-
- if (os::create_thread(this, os::os_thread)) {
- _memnotify_thread = this;
- os::set_priority(this, NearMaxPriority);
- os::start_thread(this);
- }
-}
-
-// Where all the work gets done
-//
-void MemNotifyThread::run() {
- assert(this == memnotify_thread(), "expected the singleton MemNotifyThread");
-
- // Set up the select arguments
- fd_set rfds;
- if (_fd != -1) {
- FD_ZERO(&rfds);
- FD_SET(_fd, &rfds);
- }
-
- // Now wait for the mem_notify device to wake up
- while (1) {
- // Wait for the mem_notify device to signal us..
- int rc = select(_fd+1, _fd != -1 ? &rfds : NULL, NULL, NULL, NULL);
- if (rc == -1) {
- perror("select!\n");
- break;
- } else if (rc) {
- //ssize_t free_before = os::available_memory();
- //tty->print ("Notified: Free: %dK \n",os::available_memory()/1024);
-
- // The kernel is telling us there is not much memory left...
- // try to do something about that
-
- // If we are not already in a GC, try one.
- if (!Universe::heap()->is_gc_active()) {
- Universe::heap()->collect(GCCause::_allocation_failure);
-
- //ssize_t free_after = os::available_memory();
- //tty->print ("Post-Notify: Free: %dK\n",free_after/1024);
- //tty->print ("GC freed: %dK\n", (free_after - free_before)/1024);
- }
- // We might want to do something like the following if we find the GC's are not helping...
- // Universe::heap()->size_policy()->set_gc_time_limit_exceeded(true);
- }
- }
-}
-
-// See if the /dev/mem_notify device exists, and if so, start a thread to monitor it.
-//
-void MemNotifyThread::start() {
- int fd;
- fd = open("/dev/mem_notify", O_RDONLY, 0);
- if (fd < 0) {
- return;
- }
-
- if (memnotify_thread() == NULL) {
- new MemNotifyThread(fd);
- }
-}
-
-#endif // JAVASE_EMBEDDED
-
-
/////////////// Unit tests ///////////////
#ifndef PRODUCT
--- a/hotspot/src/os/linux/vm/os_linux.inline.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -173,92 +173,14 @@
return os::send(fd, buf, nBytes, flags);
}
-inline int os::timeout(int fd, long timeout) {
- julong prevtime,newtime;
- struct timeval t;
-
- gettimeofday(&t, NULL);
- prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
-
- for(;;) {
- struct pollfd pfd;
-
- pfd.fd = fd;
- pfd.events = POLLIN | POLLERR;
-
- int res = ::poll(&pfd, 1, timeout);
-
- if (res == OS_ERR && errno == EINTR) {
-
- // On Linux any value < 0 means "forever"
-
- if(timeout >= 0) {
- gettimeofday(&t, NULL);
- newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if(timeout <= 0)
- return OS_OK;
- prevtime = newtime;
- }
- } else
- return res;
- }
-}
-
-inline int os::listen(int fd, int count) {
- return ::listen(fd, count);
-}
-
inline int os::connect(int fd, struct sockaddr* him, socklen_t len) {
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
}
-inline int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
- // Linux doc says this can't return EINTR, unlike accept() on Solaris.
- // But see attachListener_linux.cpp, LinuxAttachListener::dequeue().
- return (int)::accept(fd, him, len);
-}
-
-inline int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
- sockaddr* from, socklen_t* fromlen) {
- RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
-}
-
-inline int os::sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr* to, socklen_t tolen) {
- RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
-}
-
-inline int os::socket_shutdown(int fd, int howto) {
- return ::shutdown(fd, howto);
-}
-
-inline int os::bind(int fd, struct sockaddr* him, socklen_t len) {
- return ::bind(fd, him, len);
-}
-
-inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
- return ::getsockname(fd, him, len);
-}
-
-inline int os::get_host_name(char* name, int namelen) {
- return ::gethostname(name, namelen);
-}
-
inline struct hostent* os::get_host_by_name(char* name) {
return ::gethostbyname(name);
}
-inline int os::get_sock_opt(int fd, int level, int optname,
- char* optval, socklen_t* optlen) {
- return ::getsockopt(fd, level, optname, optval, optlen);
-}
-
-inline int os::set_sock_opt(int fd, int level, int optname,
- const char* optval, socklen_t optlen) {
- return ::setsockopt(fd, level, optname, optval, optlen);
-}
-
inline bool os::supports_monotonic_clock() {
return Linux::_clock_gettime != NULL;
}
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -506,6 +506,7 @@
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
+ os::closedir(dirp);
return;
}
@@ -872,6 +873,9 @@
//
if (!is_directory_secure(dirname)) {
FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ if (luser != user) {
+ FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ }
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
--- a/hotspot/src/os/posix/vm/os_posix.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/posix/vm/os_posix.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -663,7 +663,10 @@
}
}
- jio_snprintf(out, outlen, ret);
+ if (out && outlen > 0) {
+ strncpy(out, ret, outlen);
+ out[outlen - 1] = '\0';
+ }
return out;
}
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -2221,6 +2221,7 @@
}
strncpy(saved_jvm_path, buf, MAXPATHLEN);
+ saved_jvm_path[MAXPATHLEN - 1] = '\0';
}
@@ -4761,10 +4762,6 @@
return JNI_OK;
}
-void os::init_3(void) {
- return;
-}
-
// Mark the polling page as unreadable
void os::make_polling_page_unreadable(void) {
if (mprotect((char *)_polling_page, page_size, PROT_NONE) != 0) {
@@ -5372,31 +5369,32 @@
// to immediately return 0 your code should still work,
// albeit degenerating to a spin loop.
//
-// An interesting optimization for park() is to use a trylock()
-// to attempt to acquire the mutex. If the trylock() fails
-// then we know that a concurrent unpark() operation is in-progress.
-// in that case the park() code could simply set _count to 0
-// and return immediately. The subsequent park() operation *might*
-// return immediately. That's harmless as the caller of park() is
-// expected to loop. By using trylock() we will have avoided a
-// avoided a context switch caused by contention on the per-thread mutex.
+// In a sense, park()-unpark() just provides more polite spinning
+// and polling with the key difference over naive spinning being
+// that a parked thread needs to be explicitly unparked() in order
+// to wake up and to poll the underlying condition.
//
-// TODO-FIXME:
-// 1. Reconcile Doug's JSR166 j.u.c park-unpark with the
-// objectmonitor implementation.
-// 2. Collapse the JSR166 parker event, and the
-// objectmonitor ParkEvent into a single "Event" construct.
-// 3. In park() and unpark() add:
-// assert (Thread::current() == AssociatedWith).
-// 4. add spurious wakeup injection on a -XX:EarlyParkReturn=N switch.
-// 1-out-of-N park() operations will return immediately.
+// Assumption:
+// Only one parker can exist on an event, which is why we allocate
+// them per-thread. Multiple unparkers can coexist.
//
// _Event transitions in park()
// -1 => -1 : illegal
// 1 => 0 : pass - return immediately
-// 0 => -1 : block
+// 0 => -1 : block; then set _Event to 0 before returning
+//
+// _Event transitions in unpark()
+// 0 => 1 : just return
+// 1 => 1 : just return
+// -1 => either 0 or 1; must signal target thread
+// That is, we can safely transition _Event from -1 to either
+// 0 or 1.
//
// _Event serves as a restricted-range semaphore.
+// -1 : thread is blocked, i.e. there is a waiter
+// 0 : neutral: thread is running or ready,
+// could have been signaled after a wait started
+// 1 : signaled - thread is running or ready
//
// Another possible encoding of _Event would be with
// explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
@@ -5456,6 +5454,11 @@
}
void os::PlatformEvent::park() { // AKA: down()
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
// Invariant: Only the thread associated with the Event/PlatformEvent
// may call park().
assert(_nParked == 0, "invariant");
@@ -5497,6 +5500,11 @@
}
int os::PlatformEvent::park(jlong millis) {
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
guarantee(_nParked == 0, "invariant");
int v;
for (;;) {
@@ -5542,11 +5550,11 @@
void os::PlatformEvent::unpark() {
// Transitions for _Event:
- // 0 :=> 1
- // 1 :=> 1
- // -1 :=> either 0 or 1; must signal target thread
- // That is, we can safely transition _Event from -1 to either
- // 0 or 1.
+ // 0 => 1 : just return
+ // 1 => 1 : just return
+ // -1 => either 0 or 1; must signal target thread
+ // That is, we can safely transition _Event from -1 to either
+ // 0 or 1.
// See also: "Semaphores in Plan 9" by Mullender & Cox
//
// Note: Forcing a transition from "-1" to "1" on an unpark() means
@@ -5566,8 +5574,13 @@
assert_status(status == 0, status, "mutex_unlock");
guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
if (AnyWaiters != 0) {
- // We intentional signal *after* dropping the lock
- // to avoid a common class of futile wakeups.
+ // Note that we signal() *after* dropping the lock for "immortal" Events.
+ // This is safe and avoids a common class of futile wakeups. In rare
+ // circumstances this can cause a thread to return prematurely from
+ // cond_{timed}wait() but the spurious wakeup is benign and the victim
+ // will simply re-test the condition and re-park itself.
+ // This provides particular benefit if the underlying platform does not
+ // provide wait morphing.
status = os::Solaris::cond_signal(_cond);
assert_status(status == 0, status, "cond_signal");
}
@@ -5912,37 +5925,6 @@
// a poll() is done with timeout == -1, in which case we repeat with this
// "wait forever" value.
-int os::timeout(int fd, long timeout) {
- int res;
- struct timeval t;
- julong prevtime, newtime;
- static const char* aNull = 0;
- struct pollfd pfd;
- pfd.fd = fd;
- pfd.events = POLLIN;
-
- assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
- "Assumed _thread_in_native");
-
- gettimeofday(&t, &aNull);
- prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
-
- for (;;) {
- res = ::poll(&pfd, 1, timeout);
- if (res == OS_ERR && errno == EINTR) {
- if (timeout != -1) {
- gettimeofday(&t, &aNull);
- newtime = ((julong)t.tv_sec * 1000) + t.tv_usec /1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0) {
- return OS_OK;
- }
- prevtime = newtime;
- }
- } else return res;
- }
-}
-
int os::connect(int fd, struct sockaddr *him, socklen_t len) {
int _result;
_result = ::connect(fd, him, len);
@@ -5982,46 +5964,6 @@
return _result;
}
-int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
- if (fd < 0) {
- return OS_ERR;
- }
- assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
- "Assumed _thread_in_native");
- RESTARTABLE_RETURN_INT((int)::accept(fd, him, len));
-}
-
-int os::recvfrom(int fd, char* buf, size_t nBytes, uint flags,
- sockaddr* from, socklen_t* fromlen) {
- assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
- "Assumed _thread_in_native");
- RESTARTABLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, flags, from, fromlen));
-}
-
-int os::sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr* to, socklen_t tolen) {
- assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
- "Assumed _thread_in_native");
- RESTARTABLE_RETURN_INT((int)::sendto(fd, buf, len, flags, to, tolen));
-}
-
-int os::socket_available(int fd, jint *pbytes) {
- if (fd < 0) {
- return OS_OK;
- }
- int ret;
- RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret);
- // note: ioctl can return 0 when successful, JVM_SocketAvailable
- // is expected to return 0 on failure and 1 on success to the jdk.
- return (ret == OS_ERR) ? 0 : 1;
-}
-
-int os::bind(int fd, struct sockaddr* him, socklen_t len) {
- assert(((JavaThread*)Thread::current())->thread_state() == _thread_in_native,
- "Assumed _thread_in_native");
- return ::bind(fd, him, len);
-}
-
// Get the default path to the core file
// Returns the length of the string
int os::get_core_path(char* buffer, size_t bufferSize) {
--- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -120,38 +120,10 @@
return ::socket(domain, type, protocol);
}
-inline int os::listen(int fd, int count) {
- if (fd < 0) return OS_ERR;
-
- return ::listen(fd, count);
-}
-
-inline int os::socket_shutdown(int fd, int howto){
- return ::shutdown(fd, howto);
-}
-
-inline int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len){
- return ::getsockname(fd, him, len);
-}
-
-inline int os::get_host_name(char* name, int namelen){
- return ::gethostname(name, namelen);
-}
-
inline struct hostent* os::get_host_by_name(char* name) {
return ::gethostbyname(name);
}
-inline int os::get_sock_opt(int fd, int level, int optname,
- char* optval, socklen_t* optlen) {
- return ::getsockopt(fd, level, optname, optval, optlen);
-}
-
-inline int os::set_sock_opt(int fd, int level, int optname,
- const char *optval, socklen_t optlen) {
- return ::setsockopt(fd, level, optname, optval, optlen);
-}
-
inline bool os::supports_monotonic_clock() {
// javaTimeNanos() is monotonic on Solaris, see getTimeNanos() comments
return true;
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -545,6 +545,7 @@
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
+ os::closedir(dirp);
return;
}
@@ -890,6 +891,9 @@
//
if (!is_directory_secure(dirname)) {
FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ if (luser != user) {
+ FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ }
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
--- a/hotspot/src/os/windows/vm/attachListener_windows.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/windows/vm/attachListener_windows.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -30,6 +30,7 @@
#include <windows.h>
#include <signal.h> // SIGBREAK
+#include <stdio.h>
// The AttachListener thread services a queue of operations. It blocks in the dequeue
// function until an operation is enqueued. A client enqueues an operation by creating
@@ -269,6 +270,7 @@
if (hPipe != INVALID_HANDLE_VALUE) {
// shouldn't happen as there is a pipe created per operation
if (::GetLastError() == ERROR_PIPE_BUSY) {
+ ::CloseHandle(hPipe);
return INVALID_HANDLE_VALUE;
}
}
@@ -313,7 +315,8 @@
BOOL fSuccess;
char msg[32];
- sprintf(msg, "%d\n", result);
+ _snprintf(msg, sizeof(msg), "%d\n", result);
+ msg[sizeof(msg) - 1] = '\0';
fSuccess = write_pipe(hPipe, msg, (int)strlen(msg));
if (fSuccess) {
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -96,7 +96,7 @@
#include <vdmdbg.h>
// for timer info max values which include all bits
-#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
+#define ALL_64_BITS CONST64(-1)
// For DLL loading/load error detection
// Values of PE COFF
@@ -211,6 +211,7 @@
}
strcpy(home_path, home_dir);
Arguments::set_java_home(home_path);
+ FREE_C_HEAP_ARRAY(char, home_path, mtInternal);
dll_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + strlen(bin) + 1,
mtInternal);
@@ -220,6 +221,7 @@
strcpy(dll_path, home_dir);
strcat(dll_path, bin);
Arguments::set_dll_dir(dll_path);
+ FREE_C_HEAP_ARRAY(char, dll_path, mtInternal);
if (!set_boot_path('\\', ';')) {
return;
@@ -297,6 +299,9 @@
char * buf = NEW_C_HEAP_ARRAY(char, len, mtInternal);
sprintf(buf, "%s%s", Arguments::get_java_home(), ENDORSED_DIR);
Arguments::set_endorsed_dirs(buf);
+ // (Arguments::set_endorsed_dirs() calls SystemProperty::set_value(), which
+ // duplicates the input.)
+ FREE_C_HEAP_ARRAY(char, buf, mtInternal);
#undef ENDORSED_DIR
}
@@ -436,9 +441,9 @@
}
// Diagnostic code to investigate JDK-6573254
- int res = 90115; // non-java thread
+ int res = 50115; // non-java thread
if (thread->is_Java_thread()) {
- res = 60115; // java thread
+ res = 40115; // java thread
}
// Install a win32 structured exception handler around every thread created
@@ -1610,96 +1615,123 @@
void os::win32::print_windows_version(outputStream* st) {
OSVERSIONINFOEX osvi;
- SYSTEM_INFO si;
-
+ VS_FIXEDFILEINFO *file_info;
+ TCHAR kernel32_path[MAX_PATH];
+ UINT len, ret;
+
+ // Use the GetVersionEx information to see if we're on a server or
+ // workstation edition of Windows. Starting with Windows 8.1 we can't
+ // trust the OS version information returned by this API.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
if (!GetVersionEx((OSVERSIONINFO *)&osvi)) {
- st->print_cr("N/A");
+ st->print_cr("Call to GetVersionEx failed");
+ return;
+ }
+ bool is_workstation = (osvi.wProductType == VER_NT_WORKSTATION);
+
+ // Get the full path to \Windows\System32\kernel32.dll and use that for
+ // determining what version of Windows we're running on.
+ len = MAX_PATH - (UINT)strlen("\\kernel32.dll") - 1;
+ ret = GetSystemDirectory(kernel32_path, len);
+ if (ret == 0 || ret > len) {
+ st->print_cr("Call to GetSystemDirectory failed");
+ return;
+ }
+ strncat(kernel32_path, "\\kernel32.dll", MAX_PATH - ret);
+
+ DWORD version_size = GetFileVersionInfoSize(kernel32_path, NULL);
+ if (version_size == 0) {
+ st->print_cr("Call to GetFileVersionInfoSize failed");
+ return;
+ }
+
+ LPTSTR version_info = (LPTSTR)os::malloc(version_size, mtInternal);
+ if (version_info == NULL) {
+ st->print_cr("Failed to allocate version_info");
return;
}
- int os_vers = osvi.dwMajorVersion * 1000 + osvi.dwMinorVersion;
-
- ZeroMemory(&si, sizeof(SYSTEM_INFO));
- if (os_vers >= 5002) {
- // Retrieve SYSTEM_INFO from GetNativeSystemInfo call so that we could
- // find out whether we are running on 64 bit processor or not.
- if (os::Kernel32Dll::GetNativeSystemInfoAvailable()) {
- os::Kernel32Dll::GetNativeSystemInfo(&si);
+ if (!GetFileVersionInfo(kernel32_path, NULL, version_size, version_info)) {
+ os::free(version_info);
+ st->print_cr("Call to GetFileVersionInfo failed");
+ return;
+ }
+
+ if (!VerQueryValue(version_info, TEXT("\\"), (LPVOID*)&file_info, &len)) {
+ os::free(version_info);
+ st->print_cr("Call to VerQueryValue failed");
+ return;
+ }
+
+ int major_version = HIWORD(file_info->dwProductVersionMS);
+ int minor_version = LOWORD(file_info->dwProductVersionMS);
+ int build_number = HIWORD(file_info->dwProductVersionLS);
+ int build_minor = LOWORD(file_info->dwProductVersionLS);
+ int os_vers = major_version * 1000 + minor_version;
+ os::free(version_info);
+
+ st->print(" Windows ");
+ switch (os_vers) {
+
+ case 6000:
+ if (is_workstation) {
+ st->print("Vista");
} else {
- GetSystemInfo(&si);
+ st->print("Server 2008");
}
- }
-
- if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- switch (os_vers) {
- case 3051: st->print(" Windows NT 3.51"); break;
- case 4000: st->print(" Windows NT 4.0"); break;
- case 5000: st->print(" Windows 2000"); break;
- case 5001: st->print(" Windows XP"); break;
- case 5002:
- if (osvi.wProductType == VER_NT_WORKSTATION &&
- si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
- st->print(" Windows XP x64 Edition");
- } else {
- st->print(" Windows Server 2003 family");
- }
- break;
-
- case 6000:
- if (osvi.wProductType == VER_NT_WORKSTATION) {
- st->print(" Windows Vista");
- } else {
- st->print(" Windows Server 2008");
- }
- break;
-
- case 6001:
- if (osvi.wProductType == VER_NT_WORKSTATION) {
- st->print(" Windows 7");
- } else {
- st->print(" Windows Server 2008 R2");
- }
- break;
-
- case 6002:
- if (osvi.wProductType == VER_NT_WORKSTATION) {
- st->print(" Windows 8");
- } else {
- st->print(" Windows Server 2012");
- }
- break;
-
- case 6003:
- if (osvi.wProductType == VER_NT_WORKSTATION) {
- st->print(" Windows 8.1");
- } else {
- st->print(" Windows Server 2012 R2");
- }
- break;
-
- default: // future os
- // Unrecognized windows, print out its major and minor versions
- st->print(" Windows NT %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion);
+ break;
+
+ case 6001:
+ if (is_workstation) {
+ st->print("7");
+ } else {
+ st->print("Server 2008 R2");
+ }
+ break;
+
+ case 6002:
+ if (is_workstation) {
+ st->print("8");
+ } else {
+ st->print("Server 2012");
+ }
+ break;
+
+ case 6003:
+ if (is_workstation) {
+ st->print("8.1");
+ } else {
+ st->print("Server 2012 R2");
}
- } else {
- switch (os_vers) {
- case 4000: st->print(" Windows 95"); break;
- case 4010: st->print(" Windows 98"); break;
- case 4090: st->print(" Windows Me"); break;
- default: // future windows, print out its major and minor versions
- st->print(" Windows %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion);
+ break;
+
+ case 6004:
+ if (is_workstation) {
+ st->print("10");
+ } else {
+ // The server version name of Windows 10 is not known at this time
+ st->print("%d.%d", major_version, minor_version);
}
- }
-
- if (os_vers >= 6000 && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+ break;
+
+ default:
+ // Unrecognized windows, print out its major and minor versions
+ st->print("%d.%d", major_version, minor_version);
+ break;
+ }
+
+ // Retrieve SYSTEM_INFO from GetNativeSystemInfo call so that we could
+ // find out whether we are running on 64 bit processor or not
+ SYSTEM_INFO si;
+ ZeroMemory(&si, sizeof(SYSTEM_INFO));
+ os::Kernel32Dll::GetNativeSystemInfo(&si);
+ if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
st->print(" , 64 bit");
}
- st->print(" Build %d", osvi.dwBuildNumber);
- st->print(" %s", osvi.szCSDVersion); // service pack
+ st->print(" Build %d", build_number);
+ st->print(" (%d.%d.%d.%d)", major_version, minor_version, build_number, build_minor);
st->cr();
}
@@ -1807,6 +1839,7 @@
GetModuleFileName(vm_lib_handle, buf, buflen);
}
strncpy(saved_jvm_path, buf, MAX_PATH);
+ saved_jvm_path[MAX_PATH - 1] = '\0';
}
@@ -3719,8 +3752,12 @@
// search system directory
if ((size = GetSystemDirectory(path, pathLen)) > 0) {
- strcat(path, "\\");
- strcat(path, name);
+ if (size >= pathLen) {
+ return NULL; // truncated
+ }
+ if (jio_snprintf(path + size, pathLen - size, "\\%s", name) == -1) {
+ return NULL; // truncated
+ }
if ((result = (HINSTANCE)os::dll_load(path, ebuf, ebuflen)) != NULL) {
return result;
}
@@ -3728,8 +3765,12 @@
// try Windows directory
if ((size = GetWindowsDirectory(path, pathLen)) > 0) {
- strcat(path, "\\");
- strcat(path, name);
+ if (size >= pathLen) {
+ return NULL; // truncated
+ }
+ if (jio_snprintf(path + size, pathLen - size, "\\%s", name) == -1) {
+ return NULL; // truncated
+ }
if ((result = (HINSTANCE)os::dll_load(path, ebuf, ebuflen)) != NULL) {
return result;
}
@@ -3740,68 +3781,134 @@
return NULL;
}
-#define MIN_EXIT_MUTEXES 1
-#define MAX_EXIT_MUTEXES 16
-
-struct ExitMutexes {
- DWORD count;
- HANDLE handles[MAX_EXIT_MUTEXES];
-};
-
-static BOOL CALLBACK init_muts_call(PINIT_ONCE, PVOID ppmuts, PVOID*) {
- static ExitMutexes muts;
-
- muts.count = os::processor_count();
- if (muts.count < MIN_EXIT_MUTEXES) {
- muts.count = MIN_EXIT_MUTEXES;
- } else if (muts.count > MAX_EXIT_MUTEXES) {
- muts.count = MAX_EXIT_MUTEXES;
- }
-
- for (DWORD i = 0; i < muts.count; ++i) {
- muts.handles[i] = CreateMutex(NULL, FALSE, NULL);
- if (muts.handles[i] == NULL) {
- return FALSE;
- }
- }
- *((ExitMutexes**)ppmuts) = &muts;
+#define MAX_EXIT_HANDLES 16
+#define EXIT_TIMEOUT 1000 /* 1 sec */
+
+static BOOL CALLBACK init_crit_sect_call(PINIT_ONCE, PVOID pcrit_sect, PVOID*) {
+ InitializeCriticalSection((CRITICAL_SECTION*)pcrit_sect);
return TRUE;
}
int os::win32::exit_process_or_thread(Ept what, int exit_code) {
+ // Basic approach:
+ // - Each exiting thread registers its intent to exit and then does so.
+ // - A thread trying to terminate the process must wait for all
+ // threads currently exiting to complete their exit.
+
if (os::win32::has_exit_bug()) {
- static INIT_ONCE init_once_muts = INIT_ONCE_STATIC_INIT;
- static ExitMutexes* pmuts;
-
- if (!InitOnceExecuteOnce(&init_once_muts, init_muts_call, &pmuts, NULL)) {
- warning("ExitMutex initialization failed in %s: %d\n", __FILE__, __LINE__);
- } else if (WaitForMultipleObjects(pmuts->count, pmuts->handles,
- (what != EPT_THREAD), // exiting process waits for all mutexes
- INFINITE) == WAIT_FAILED) {
- warning("ExitMutex acquisition failed in %s: %d\n", __FILE__, __LINE__);
+ // The array holds handles of the threads that have started exiting by calling
+ // _endthreadex().
+ // Should be large enough to avoid blocking the exiting thread due to lack of
+ // a free slot.
+ static HANDLE handles[MAX_EXIT_HANDLES];
+ static int handle_count = 0;
+
+ static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
+ static CRITICAL_SECTION crit_sect;
+ int i, j;
+ DWORD res;
+ HANDLE hproc, hthr;
+
+ // The first thread that reached this point, initializes the critical section.
+ if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {
+ warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);
+ } else {
+ EnterCriticalSection(&crit_sect);
+
+ if (what == EPT_THREAD) {
+ // Remove from the array those handles of the threads that have completed exiting.
+ for (i = 0, j = 0; i < handle_count; ++i) {
+ res = WaitForSingleObject(handles[i], 0 /* don't wait */);
+ if (res == WAIT_TIMEOUT) {
+ handles[j++] = handles[i];
+ } else {
+ if (res != WAIT_OBJECT_0) {
+ warning("WaitForSingleObject failed in %s: %d\n", __FILE__, __LINE__);
+ // Don't keep the handle, if we failed waiting for it.
+ }
+ CloseHandle(handles[i]);
+ }
+ }
+
+ // If there's no free slot in the array of the kept handles, we'll have to
+ // wait until at least one thread completes exiting.
+ if ((handle_count = j) == MAX_EXIT_HANDLES) {
+ res = WaitForMultipleObjects(MAX_EXIT_HANDLES, handles, FALSE, EXIT_TIMEOUT);
+ if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAX_EXIT_HANDLES)) {
+ i = (res - WAIT_OBJECT_0);
+ handle_count = MAX_EXIT_HANDLES - 1;
+ for (; i < handle_count; ++i) {
+ handles[i] = handles[i + 1];
+ }
+ } else {
+ warning("WaitForMultipleObjects failed in %s: %d\n", __FILE__, __LINE__);
+ // Don't keep handles, if we failed waiting for them.
+ for (i = 0; i < MAX_EXIT_HANDLES; ++i) {
+ CloseHandle(handles[i]);
+ }
+ handle_count = 0;
+ }
+ }
+
+ // Store a duplicate of the current thread handle in the array of handles.
+ hproc = GetCurrentProcess();
+ hthr = GetCurrentThread();
+ if (!DuplicateHandle(hproc, hthr, hproc, &handles[handle_count],
+ 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+ warning("DuplicateHandle failed in %s: %d\n", __FILE__, __LINE__);
+ } else {
+ ++handle_count;
+ }
+
+ // The current exiting thread has stored its handle in the array, and now
+ // should leave the critical section before calling _endthreadex().
+
+ } else { // what != EPT_THREAD
+ if (handle_count > 0) {
+ // Before ending the process, make sure all the threads that had called
+ // _endthreadex() completed.
+ res = WaitForMultipleObjects(handle_count, handles, TRUE, EXIT_TIMEOUT);
+ if (res == WAIT_FAILED) {
+ warning("WaitForMultipleObjects failed in %s: %d\n", __FILE__, __LINE__);
+ }
+ for (i = 0; i < handle_count; ++i) {
+ CloseHandle(handles[i]);
+ }
+ handle_count = 0;
+ }
+
+ // End the process, not leaving critical section.
+ // This makes sure no other thread executes exit-related code at the same
+ // time, thus a race is avoided.
+ if (what == EPT_PROCESS) {
+ ::exit(exit_code);
+ } else {
+ _exit(exit_code);
+ }
+ }
+
+ LeaveCriticalSection(&crit_sect);
}
}
- switch (what) {
- case EPT_THREAD:
+ // We are here if either
+ // - there's no 'race at exit' bug on this OS release;
+ // - initialization of the critical section failed (unlikely);
+ // - the current thread has stored its handle and left the critical section.
+ if (what == EPT_THREAD) {
_endthreadex((unsigned)exit_code);
- break;
-
- case EPT_PROCESS:
+ } else if (what == EPT_PROCESS) {
::exit(exit_code);
- break;
-
- case EPT_PROCESS_DIE:
+ } else {
_exit(exit_code);
- break;
- }
-
- // should not reach here
+ }
+
+ // Should not reach here
return exit_code;
}
-#undef MIN_EXIT_MUTEXES
-#undef MAX_EXIT_MUTEXES
+#undef MAX_EXIT_HANDLES
+#undef EXIT_TIMEOUT
void os::win32::setmode_streams() {
_setmode(_fileno(stdin), _O_BINARY);
@@ -4047,10 +4154,6 @@
return JNI_OK;
}
-void os::init_3(void) {
- return;
-}
-
// Mark the polling page as unreadable
void os::make_polling_page_unreadable(void) {
DWORD old_status;
@@ -4792,27 +4895,46 @@
// 3. Collapse the interrupt_event, the JSR166 parker event, and the objectmonitor ParkEvent
// into a single win32 CreateEvent() handle.
//
+// Assumption:
+// Only one parker can exist on an event, which is why we allocate
+// them per-thread. Multiple unparkers can coexist.
+//
// _Event transitions in park()
// -1 => -1 : illegal
// 1 => 0 : pass - return immediately
-// 0 => -1 : block
+// 0 => -1 : block; then set _Event to 0 before returning
+//
+// _Event transitions in unpark()
+// 0 => 1 : just return
+// 1 => 1 : just return
+// -1 => either 0 or 1; must signal target thread
+// That is, we can safely transition _Event from -1 to either
+// 0 or 1.
//
-// _Event serves as a restricted-range semaphore :
-// -1 : thread is blocked
-// 0 : neutral - thread is running or ready
-// 1 : signaled - thread is running or ready
+// _Event serves as a restricted-range semaphore.
+// -1 : thread is blocked, i.e. there is a waiter
+// 0 : neutral: thread is running or ready,
+// could have been signaled after a wait started
+// 1 : signaled - thread is running or ready
//
-// Another possible encoding of _Event would be
-// with explicit "PARKED" and "SIGNALED" bits.
+// Another possible encoding of _Event would be with
+// explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
+//
int os::PlatformEvent::park(jlong Millis) {
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
guarantee(_ParkHandle != NULL , "Invariant");
guarantee(Millis > 0 , "Invariant");
- int v;
// CONSIDER: defer assigning a CreateEvent() handle to the Event until
// the initial park() operation.
-
+ // Consider: use atomic decrement instead of CAS-loop
+
+ int v;
for (;;) {
v = _Event;
if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
@@ -4860,9 +4982,15 @@
}
void os::PlatformEvent::park() {
+ // Transitions for _Event:
+ // -1 => -1 : illegal
+ // 1 => 0 : pass - return immediately
+ // 0 => -1 : block; then set _Event to 0 before returning
+
guarantee(_ParkHandle != NULL, "Invariant");
// Invariant: Only the thread associated with the Event/PlatformEvent
// may call park().
+ // Consider: use atomic decrement instead of CAS-loop
int v;
for (;;) {
v = _Event;
@@ -4891,11 +5019,11 @@
guarantee(_ParkHandle != NULL, "Invariant");
// Transitions for _Event:
- // 0 :=> 1
- // 1 :=> 1
- // -1 :=> either 0 or 1; must signal target thread
- // That is, we can safely transition _Event from -1 to either
- // 0 or 1.
+ // 0 => 1 : just return
+ // 1 => 1 : just return
+ // -1 => either 0 or 1; must signal target thread
+ // That is, we can safely transition _Event from -1 to either
+ // 0 or 1.
// See also: "Semaphores in Plan 9" by Mullender & Cox
//
// Note: Forcing a transition from "-1" to "1" on an unpark() means
@@ -5091,39 +5219,14 @@
return ::closesocket(fd);
}
-int os::socket_available(int fd, jint *pbytes) {
- int ret = ::ioctlsocket(fd, FIONREAD, (u_long*)pbytes);
- return (ret < 0) ? 0 : 1;
-}
-
int os::socket(int domain, int type, int protocol) {
return ::socket(domain, type, protocol);
}
-int os::listen(int fd, int count) {
- return ::listen(fd, count);
-}
-
int os::connect(int fd, struct sockaddr* him, socklen_t len) {
return ::connect(fd, him, len);
}
-int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
- return ::accept(fd, him, len);
-}
-
-int os::sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr* to, socklen_t tolen) {
-
- return ::sendto(fd, buf, (int)len, flags, to, tolen);
-}
-
-int os::recvfrom(int fd, char *buf, size_t nBytes, uint flags,
- sockaddr* from, socklen_t* fromlen) {
-
- return ::recvfrom(fd, buf, (int)nBytes, flags, from, fromlen);
-}
-
int os::recv(int fd, char* buf, size_t nBytes, uint flags) {
return ::recv(fd, buf, (int)nBytes, flags);
}
@@ -5136,45 +5239,6 @@
return ::send(fd, buf, (int)nBytes, flags);
}
-int os::timeout(int fd, long timeout) {
- fd_set tbl;
- struct timeval t;
-
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
-
- tbl.fd_count = 1;
- tbl.fd_array[0] = fd;
-
- return ::select(1, &tbl, 0, 0, &t);
-}
-
-int os::get_host_name(char* name, int namelen) {
- return ::gethostname(name, namelen);
-}
-
-int os::socket_shutdown(int fd, int howto) {
- return ::shutdown(fd, howto);
-}
-
-int os::bind(int fd, struct sockaddr* him, socklen_t len) {
- return ::bind(fd, him, len);
-}
-
-int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
- return ::getsockname(fd, him, len);
-}
-
-int os::get_sock_opt(int fd, int level, int optname,
- char* optval, socklen_t* optlen) {
- return ::getsockopt(fd, level, optname, optval, optlen);
-}
-
-int os::set_sock_opt(int fd, int level, int optname,
- const char* optval, socklen_t optlen) {
- return ::setsockopt(fd, level, optname, optval, optlen);
-}
-
// WINDOWS CONTEXT Flags for THREAD_SAMPLING
#if defined(IA32)
#define sampling_context_flags (CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS)
@@ -5367,11 +5431,6 @@
return ::Module32Next(hSnapshot, lpme);
}
-
-inline BOOL os::Kernel32Dll::GetNativeSystemInfoAvailable() {
- return true;
-}
-
inline void os::Kernel32Dll::GetNativeSystemInfo(LPSYSTEM_INFO lpSystemInfo) {
::GetNativeSystemInfo(lpSystemInfo);
}
--- a/hotspot/src/os/windows/vm/os_windows.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os/windows/vm/os_windows.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -210,7 +210,6 @@
static BOOL Module32First(HANDLE,LPMODULEENTRY32);
static BOOL Module32Next(HANDLE,LPMODULEENTRY32);
- static BOOL GetNativeSystemInfoAvailable();
static void GetNativeSystemInfo(LPSYSTEM_INFO);
// NUMA calls
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -910,7 +910,7 @@
*/
char* hint = (char*) (Linux::initial_thread_stack_bottom() -
((StackYellowPages + StackRedPages + 1) * page_size));
- char* codebuf = os::reserve_memory(page_size, hint);
+ char* codebuf = os::attempt_reserve_memory_at(page_size, hint);
if ( (codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true)) ) {
return; // No matter, we tried, best effort.
}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -33,18 +33,50 @@
#include <sys/systeminfo.h>
#include <kstat.h>
#include <picl.h>
+#include <dlfcn.h>
+#include <link.h>
-extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
-extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result);
+
+// Functions from the library we need (signatures should match those in picl.h)
+extern "C" {
+ typedef int (*picl_initialize_func_t)(void);
+ typedef int (*picl_shutdown_func_t)(void);
+ typedef int (*picl_get_root_func_t)(picl_nodehdl_t *nodehandle);
+ typedef int (*picl_walk_tree_by_class_func_t)(picl_nodehdl_t rooth,
+ const char *classname, void *c_args,
+ int (*callback_fn)(picl_nodehdl_t hdl, void *args));
+ typedef int (*picl_get_prop_by_name_func_t)(picl_nodehdl_t nodeh, const char *nm,
+ picl_prophdl_t *ph);
+ typedef int (*picl_get_propval_func_t)(picl_prophdl_t proph, void *valbuf, size_t sz);
+ typedef int (*picl_get_propinfo_func_t)(picl_prophdl_t proph, picl_propinfo_t *pi);
+}
class PICL {
+ // Pointers to functions in the library
+ picl_initialize_func_t _picl_initialize;
+ picl_shutdown_func_t _picl_shutdown;
+ picl_get_root_func_t _picl_get_root;
+ picl_walk_tree_by_class_func_t _picl_walk_tree_by_class;
+ picl_get_prop_by_name_func_t _picl_get_prop_by_name;
+ picl_get_propval_func_t _picl_get_propval;
+ picl_get_propinfo_func_t _picl_get_propinfo;
+ // Handle to the library that is returned by dlopen
+ void *_dl_handle;
+
+ bool open_library();
+ void close_library();
+
+ template<typename FuncType> bool bind(FuncType& func, const char* name);
+ bool bind_library_functions();
+
// Get a value of the integer property. The value in the tree can be either 32 or 64 bit
// depending on the platform. The result is converted to int.
- static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
+ int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
picl_propinfo_t pinfo;
picl_prophdl_t proph;
- if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
- picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
+ if (_picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
+ _picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
return PICL_FAILURE;
}
@@ -54,13 +86,13 @@
}
if (pinfo.size == sizeof(int64_t)) {
int64_t val;
- if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
+ if (_picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
return PICL_FAILURE;
}
*result = static_cast<int>(val);
} else if (pinfo.size == sizeof(int32_t)) {
int32_t val;
- if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
+ if (_picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
return PICL_FAILURE;
}
*result = static_cast<int>(val);
@@ -74,6 +106,7 @@
// Visitor and a state machine that visits integer properties and verifies that the
// values are the same. Stores the unique value observed.
class UniqueValueVisitor {
+ PICL *_picl;
enum {
INITIAL, // Start state, no assignments happened
ASSIGNED, // Assigned a value
@@ -81,7 +114,7 @@
} _state;
int _value;
public:
- UniqueValueVisitor() : _state(INITIAL) { }
+ UniqueValueVisitor(PICL* picl) : _picl(picl), _state(INITIAL) { }
int value() {
assert(_state == ASSIGNED, "Precondition");
return _value;
@@ -96,71 +129,125 @@
bool is_inconsistent() { return _state == INCONSISTENT; }
void set_inconsistent() { _state = INCONSISTENT; }
- static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
- UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
- assert(!state->is_inconsistent(), "Precondition");
+ void visit(picl_nodehdl_t nodeh, const char* name) {
+ assert(!is_inconsistent(), "Precondition");
int curr;
- if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
- if (!state->is_assigned()) { // first iteration
- state->set_value(curr);
- } else if (curr != state->value()) { // following iterations
- state->set_inconsistent();
+ if (_picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
+ if (!is_assigned()) { // first iteration
+ set_value(curr);
+ } else if (curr != value()) { // following iterations
+ set_inconsistent();
}
}
- if (state->is_inconsistent()) {
+ }
+ };
+
+ class CPUVisitor {
+ UniqueValueVisitor _l1_visitor;
+ UniqueValueVisitor _l2_visitor;
+ int _limit; // number of times visit() can be run
+ public:
+ CPUVisitor(PICL *picl, int limit) : _l1_visitor(picl), _l2_visitor(picl), _limit(limit) {}
+ static int visit(picl_nodehdl_t nodeh, void *arg) {
+ CPUVisitor *cpu_visitor = static_cast<CPUVisitor*>(arg);
+ UniqueValueVisitor* l1_visitor = cpu_visitor->l1_visitor();
+ UniqueValueVisitor* l2_visitor = cpu_visitor->l2_visitor();
+ if (!l1_visitor->is_inconsistent()) {
+ l1_visitor->visit(nodeh, "l1-dcache-line-size");
+ }
+ if (!l2_visitor->is_inconsistent()) {
+ l2_visitor->visit(nodeh, "l2-cache-line-size");
+ }
+
+ if (l1_visitor->is_inconsistent() && l2_visitor->is_inconsistent()) {
+ return PICL_WALK_TERMINATE;
+ }
+ cpu_visitor->_limit--;
+ if (cpu_visitor->_limit <= 0) {
return PICL_WALK_TERMINATE;
}
return PICL_WALK_CONTINUE;
}
+ UniqueValueVisitor* l1_visitor() { return &_l1_visitor; }
+ UniqueValueVisitor* l2_visitor() { return &_l2_visitor; }
};
-
int _L1_data_cache_line_size;
int _L2_cache_line_size;
public:
- static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
- return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
- }
- static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
- return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
+ static int visit_cpu(picl_nodehdl_t nodeh, void *state) {
+ return CPUVisitor::visit(nodeh, state);
}
- PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) {
- if (picl_initialize() == PICL_SUCCESS) {
+ PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_cache_line_size(0), _dl_handle(NULL) {
+ if (!open_library()) {
+ return;
+ }
+ if (_picl_initialize() == PICL_SUCCESS) {
picl_nodehdl_t rooth;
- if (picl_get_root(&rooth) == PICL_SUCCESS) {
- UniqueValueVisitor L1_state;
- // Visit all "cpu" class instances
- picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
- if (L1_state.is_initial()) { // Still initial, iteration found no values
- // Try walk all "core" class instances, it might be a Fujitsu machine
- picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+ if (_picl_get_root(&rooth) == PICL_SUCCESS) {
+ const char* cpu_class = "cpu";
+ // If it's a Fujitsu machine, it's a "core"
+ if (is_fujitsu) {
+ cpu_class = "core";
}
- if (L1_state.is_assigned()) { // Is there a value?
- _L1_data_cache_line_size = L1_state.value();
+ CPUVisitor cpu_visitor(this, os::processor_count());
+ _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper);
+ if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value?
+ _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value();
}
-
- UniqueValueVisitor L2_state;
- picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
- if (L2_state.is_initial()) {
- picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
- }
- if (L2_state.is_assigned()) {
- _L2_cache_line_size = L2_state.value();
+ if (cpu_visitor.l2_visitor()->is_assigned()) {
+ _L2_cache_line_size = cpu_visitor.l2_visitor()->value();
}
}
- picl_shutdown();
+ _picl_shutdown();
}
+ close_library();
}
unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
};
-extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
- return PICL::get_l1_data_cache_line_size(nodeh, result);
+
+extern "C" static int PICL_visit_cpu_helper(picl_nodehdl_t nodeh, void *result) {
+ return PICL::visit_cpu(nodeh, result);
+}
+
+template<typename FuncType>
+bool PICL::bind(FuncType& func, const char* name) {
+ func = reinterpret_cast<FuncType>(dlsym(_dl_handle, name));
+ return func != NULL;
}
-extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
- return PICL::get_l2_cache_line_size(nodeh, result);
+
+bool PICL::bind_library_functions() {
+ assert(_dl_handle != NULL, "library should be open");
+ return bind(_picl_initialize, "picl_initialize" ) &&
+ bind(_picl_shutdown, "picl_shutdown" ) &&
+ bind(_picl_get_root, "picl_get_root" ) &&
+ bind(_picl_walk_tree_by_class, "picl_walk_tree_by_class") &&
+ bind(_picl_get_prop_by_name, "picl_get_prop_by_name" ) &&
+ bind(_picl_get_propval, "picl_get_propval" ) &&
+ bind(_picl_get_propinfo, "picl_get_propinfo" );
+}
+
+bool PICL::open_library() {
+ _dl_handle = dlopen("libpicl.so.1", RTLD_LAZY);
+ if (_dl_handle == NULL) {
+ warning("PICL (libpicl.so.1) is missing. Performance will not be optimal.");
+ return false;
+ }
+ if (!bind_library_functions()) {
+ assert(false, "unexpected PICL API change");
+ close_library();
+ return false;
+ }
+ return true;
+}
+
+void PICL::close_library() {
+ assert(_dl_handle != NULL, "library should be open");
+ dlclose(_dl_handle);
+ _dl_handle = NULL;
}
// We need to keep these here as long as we have to build on Solaris
@@ -342,7 +429,7 @@
}
// Figure out cache line sizes using PICL
- PICL picl;
+ PICL picl((features & sparc64_family_m) != 0);
_L1_data_cache_line_size = picl.L1_data_cache_line_size();
_L2_cache_line_size = picl.L2_cache_line_size();
--- a/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/tools/ProjectCreator/WinGammaPlatformVC10.java Mon Nov 17 12:32:27 2014 -0800
@@ -411,7 +411,7 @@
"/export:jio_vsnprintf "+
"/export:JVM_GetVersionInfo "+
"/export:JVM_InitAgentProperties");
- addAttr(rv, "AdditionalDependencies", "kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;Wsock32.lib;winmm.lib;psapi.lib");
+ addAttr(rv, "AdditionalDependencies", "kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;Wsock32.lib;winmm.lib;psapi.lib;version.lib");
addAttr(rv, "OutputFile", outDll);
addAttr(rv, "SuppressStartupBanner", "true");
addAttr(rv, "ModuleDefinitionFile", outDir+Util.sep+"vm.def");
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1093,9 +1093,8 @@
// JVMTI -- compiled method notification (must be done outside lock)
nm->post_compiled_method_load_event();
} else {
- // The CodeCache is full. Print out warning and disable compilation.
+ // The CodeCache is full.
record_failure("code cache is full");
- CompileBroker::handle_full_code_cache(CodeCache::get_code_blob_type(comp_level));
}
}
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -2557,7 +2557,7 @@
Array<Method*>* ClassFileParser::parse_methods(bool is_interface,
AccessFlags* promoted_flags,
bool* has_final_method,
- bool* has_default_methods,
+ bool* declares_default_methods,
TRAPS) {
ClassFileStream* cfs = stream();
cfs->guarantee_more(2, CHECK_NULL); // length
@@ -2576,11 +2576,11 @@
if (method->is_final()) {
*has_final_method = true;
}
- if (is_interface && !(*has_default_methods)
- && !method->is_abstract() && !method->is_static()
- && !method->is_private()) {
- // default method
- *has_default_methods = true;
+ // declares_default_methods: declares concrete instance methods, any access flags
+ // used for interface initialization, and default method inheritance analysis
+ if (is_interface && !(*declares_default_methods)
+ && !method->is_abstract() && !method->is_static()) {
+ *declares_default_methods = true;
}
_methods->at_put(index, method());
}
@@ -3739,6 +3739,7 @@
JvmtiCachedClassFileData *cached_class_file = NULL;
Handle class_loader(THREAD, loader_data->class_loader());
bool has_default_methods = false;
+ bool declares_default_methods = false;
ResourceMark rm(THREAD);
ClassFileStream* cfs = stream();
@@ -3976,9 +3977,13 @@
Array<Method*>* methods = parse_methods(access_flags.is_interface(),
&promoted_flags,
&has_final_method,
- &has_default_methods,
+ &declares_default_methods,
CHECK_(nullHandle));
+ if (declares_default_methods) {
+ has_default_methods = true;
+ }
+
// Additional attributes
ClassAnnotationCollector parsed_annotations;
parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));
@@ -4120,6 +4125,7 @@
this_klass->set_minor_version(minor_version);
this_klass->set_major_version(major_version);
this_klass->set_has_default_methods(has_default_methods);
+ this_klass->set_declares_default_methods(declares_default_methods);
if (!host_klass.is_null()) {
assert (this_klass->is_anonymous(), "should be the same");
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -247,7 +247,7 @@
Array<Method*>* parse_methods(bool is_interface,
AccessFlags* promoted_flags,
bool* has_final_method,
- bool* has_default_method,
+ bool* declares_default_methods,
TRAPS);
intArray* sort_methods(Array<Method*>* methods);
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -553,6 +553,7 @@
ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL;
bool ClassLoaderDataGraph::_should_purge = false;
+bool ClassLoaderDataGraph::_metaspace_oom = false;
// Add a new class loader data node to the list. Assign the newly created
// ClassLoaderData into the java/lang/ClassLoader object as a hidden field
@@ -804,12 +805,17 @@
ClassLoaderData* list = _unloading;
_unloading = NULL;
ClassLoaderData* next = list;
+ bool classes_unloaded = false;
while (next != NULL) {
ClassLoaderData* purge_me = next;
next = purge_me->next();
delete purge_me;
+ classes_unloaded = true;
}
- Metaspace::purge();
+ if (classes_unloaded) {
+ Metaspace::purge();
+ set_metaspace_oom(false);
+ }
}
void ClassLoaderDataGraph::post_class_unload_events(void) {
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -68,6 +68,9 @@
static ClassLoaderData* _saved_head;
static ClassLoaderData* _saved_unloading;
static bool _should_purge;
+ // OOM has been seen in metaspace allocation. Used to prevent some
+ // allocations until class unloading
+ static bool _metaspace_oom;
static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS);
static void post_class_unload_events(void);
@@ -107,6 +110,9 @@
}
}
+ static bool has_metaspace_oom() { return _metaspace_oom; }
+ static void set_metaspace_oom(bool value) { _metaspace_oom = value; }
+
static void free_deallocate_lists();
static void dump_on(outputStream * const out) PRODUCT_RETURN;
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -455,6 +455,7 @@
template(object_void_signature, "(Ljava/lang/Object;)V") \
template(object_int_signature, "(Ljava/lang/Object;)I") \
template(object_boolean_signature, "(Ljava/lang/Object;)Z") \
+ template(object_object_signature, "(Ljava/lang/Object;)Ljava/lang/Object;") \
template(string_void_signature, "(Ljava/lang/String;)V") \
template(string_int_signature, "(Ljava/lang/String;)I") \
template(throwable_void_signature, "(Ljava/lang/Throwable;)V") \
@@ -746,6 +747,8 @@
do_name( isPrimitive_name, "isPrimitive") \
do_intrinsic(_getSuperclass, java_lang_Class, getSuperclass_name, void_class_signature, F_RN) \
do_name( getSuperclass_name, "getSuperclass") \
+ do_intrinsic(_Class_cast, java_lang_Class, Class_cast_name, object_object_signature, F_R) \
+ do_name( Class_cast_name, "cast") \
\
do_intrinsic(_getClassAccessFlags, sun_reflect_Reflection, getClassAccessFlags_name, class_int_signature, F_SN) \
do_name( getClassAccessFlags_name, "getClassAccessFlags") \
--- a/hotspot/src/share/vm/code/codeBlob.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -229,8 +229,8 @@
return blob;
}
-void* BufferBlob::operator new(size_t s, unsigned size, bool is_critical) throw() {
- return CodeCache::allocate(size, CodeBlobType::NonNMethod, is_critical);
+void* BufferBlob::operator new(size_t s, unsigned size) throw() {
+ return CodeCache::allocate(size, CodeBlobType::NonNMethod);
}
void BufferBlob::free(BufferBlob *blob) {
@@ -260,10 +260,7 @@
unsigned int size = allocation_size(cb, sizeof(AdapterBlob));
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- // The parameter 'true' indicates a critical memory allocation.
- // This means that CodeCacheMinimumFreeSpace is used, if necessary
- const bool is_critical = true;
- blob = new (size, is_critical) AdapterBlob(size, cb);
+ blob = new (size) AdapterBlob(size, cb);
}
// Track memory usage statistic after releasing CodeCache_lock
MemoryService::track_code_cache_memory_usage();
@@ -285,10 +282,7 @@
size += round_to(buffer_size, oopSize);
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- // The parameter 'true' indicates a critical memory allocation.
- // This means that CodeCacheMinimumFreeSpace is used, if necessary
- const bool is_critical = true;
- blob = new (size, is_critical) MethodHandlesAdapterBlob(size);
+ blob = new (size) MethodHandlesAdapterBlob(size);
}
// Track memory usage statistic after releasing CodeCache_lock
MemoryService::track_code_cache_memory_usage();
@@ -336,14 +330,14 @@
void* RuntimeStub::operator new(size_t s, unsigned size) throw() {
- void* p = CodeCache::allocate(size, CodeBlobType::NonNMethod, true);
+ void* p = CodeCache::allocate(size, CodeBlobType::NonNMethod);
if (!p) fatal("Initial size of CodeCache is too small");
return p;
}
// operator new shared by all singletons:
void* SingletonBlob::operator new(size_t s, unsigned size) throw() {
- void* p = CodeCache::allocate(size, CodeBlobType::NonNMethod, true);
+ void* p = CodeCache::allocate(size, CodeBlobType::NonNMethod);
if (!p) fatal("Initial size of CodeCache is too small");
return p;
}
--- a/hotspot/src/share/vm/code/codeBlob.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/code/codeBlob.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -221,7 +221,7 @@
BufferBlob(const char* name, int size);
BufferBlob(const char* name, int size, CodeBuffer* cb);
- void* operator new(size_t s, unsigned size, bool is_critical = false) throw();
+ void* operator new(size_t s, unsigned size) throw();
public:
// Creation
--- a/hotspot/src/share/vm/code/codeCache.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/code/codeCache.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -44,6 +44,7 @@
#include "runtime/icache.hpp"
#include "runtime/java.hpp"
#include "runtime/mutexLocker.hpp"
+#include "runtime/sweeper.hpp"
#include "runtime/compilationPolicy.hpp"
#include "services/memoryService.hpp"
#include "trace/tracing.hpp"
@@ -192,16 +193,16 @@
}
// Make sure we have enough space for VM internal code
- uint min_code_cache_size = (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3)) + CodeCacheMinimumFreeSpace;
+ uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
if (NonNMethodCodeHeapSize < (min_code_cache_size + code_buffers_size)) {
vm_exit_during_initialization("Not enough space in non-nmethod code heap to run VM.");
}
guarantee(NonProfiledCodeHeapSize + ProfiledCodeHeapSize + NonNMethodCodeHeapSize <= ReservedCodeCacheSize, "Size check");
// Align reserved sizes of CodeHeaps
- size_t non_method_size = ReservedCodeSpace::allocation_align_size_up(NonNMethodCodeHeapSize);
- size_t profiled_size = ReservedCodeSpace::allocation_align_size_up(ProfiledCodeHeapSize);
- size_t non_profiled_size = ReservedCodeSpace::allocation_align_size_up(NonProfiledCodeHeapSize);
+ size_t non_method_size = ReservedCodeSpace::allocation_align_size_up(NonNMethodCodeHeapSize);
+ size_t profiled_size = ReservedCodeSpace::allocation_align_size_up(ProfiledCodeHeapSize);
+ size_t non_profiled_size = ReservedCodeSpace::allocation_align_size_up(NonProfiledCodeHeapSize);
// Compute initial sizes of CodeHeaps
size_t init_non_method_size = MIN2(InitialCodeCacheSize, non_method_size);
@@ -267,6 +268,22 @@
}
}
+const char* CodeCache::get_code_heap_flag_name(int code_blob_type) {
+ switch(code_blob_type) {
+ case CodeBlobType::NonNMethod:
+ return "NonNMethodCodeHeapSize";
+ break;
+ case CodeBlobType::MethodNonProfiled:
+ return "NonProfiledCodeHeapSize";
+ break;
+ case CodeBlobType::MethodProfiled:
+ return "ProfiledCodeHeapSize";
+ break;
+ }
+ ShouldNotReachHere();
+ return NULL;
+}
+
void CodeCache::add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type) {
// Check if heap is needed
if (!heap_available(code_blob_type)) {
@@ -332,14 +349,18 @@
return next_blob(get_code_heap(cb), cb);
}
-CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool is_critical) {
- // Do not seize the CodeCache lock here--if the caller has not
- // already done so, we are going to lose bigtime, since the code
- // cache will contain a garbage CodeBlob until the caller can
- // run the constructor for the CodeBlob subclass he is busy
- // instantiating.
+/**
+ * Do not seize the CodeCache lock here--if the caller has not
+ * already done so, we are going to lose bigtime, since the code
+ * cache will contain a garbage CodeBlob until the caller can
+ * run the constructor for the CodeBlob subclass he is busy
+ * instantiating.
+ */
+CodeBlob* CodeCache::allocate(int size, int code_blob_type) {
+ // Possibly wakes up the sweeper thread.
+ NMethodSweeper::notify(code_blob_type);
assert_locked_or_safepoint(CodeCache_lock);
- assert(size > 0, "allocation request must be reasonable");
+ assert(size > 0, err_msg_res("Code cache allocation request must be > 0 but is %d", size));
if (size <= 0) {
return NULL;
}
@@ -350,14 +371,18 @@
assert(heap != NULL, "heap is null");
while (true) {
- cb = (CodeBlob*)heap->allocate(size, is_critical);
+ cb = (CodeBlob*)heap->allocate(size);
if (cb != NULL) break;
if (!heap->expand_by(CodeCacheExpansionSize)) {
// Expansion failed
if (SegmentedCodeCache && (code_blob_type == CodeBlobType::NonNMethod)) {
- // Fallback solution: Store non-nmethod code in the non-profiled code heap
- return allocate(size, CodeBlobType::MethodNonProfiled, is_critical);
+ // Fallback solution: Store non-nmethod code in the non-profiled code heap.
+ // Note that at in the sweeper, we check the reverse_free_ratio of the non-profiled
+ // code heap and force stack scanning if less than 10% if the code heap are free.
+ return allocate(size, CodeBlobType::MethodNonProfiled);
}
+ MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ CompileBroker::handle_full_code_cache(code_blob_type);
return NULL;
}
if (PrintCodeCacheExtension) {
@@ -755,19 +780,6 @@
}
/**
- * Returns true if a CodeHeap is full and sets code_blob_type accordingly.
- */
-bool CodeCache::is_full(int* code_blob_type) {
- FOR_ALL_HEAPS(heap) {
- if ((*heap)->unallocated_capacity() < CodeCacheMinimumFreeSpace) {
- *code_blob_type = (*heap)->code_blob_type();
- return true;
- }
- }
- return false;
-}
-
-/**
* Returns the reverse free ratio. E.g., if 25% (1/4) of the code heap
* is free, reverse_free_ratio() returns 4.
*/
@@ -776,9 +788,13 @@
if (heap == NULL) {
return 0;
}
- double unallocated_capacity = (double)(heap->unallocated_capacity() - CodeCacheMinimumFreeSpace);
+
+ double unallocated_capacity = MAX2((double)heap->unallocated_capacity(), 1.0); // Avoid division by 0;
double max_capacity = (double)heap->max_capacity();
- return max_capacity / unallocated_capacity;
+ double result = max_capacity / unallocated_capacity;
+ assert (max_capacity >= unallocated_capacity, "Must be");
+ assert (result >= 1.0, err_msg_res("reverse_free_ratio must be at least 1. It is %f", result));
+ return result;
}
size_t CodeCache::bytes_allocated_in_freelists() {
@@ -1011,9 +1027,8 @@
// Not yet reported for this heap, report
heap->report_full();
if (SegmentedCodeCache) {
- warning("%s is full. Compiler has been disabled.", CodeCache::get_code_heap_name(code_blob_type));
- warning("Try increasing the code heap size using -XX:%s=",
- (code_blob_type == CodeBlobType::MethodNonProfiled) ? "NonProfiledCodeHeapSize" : "ProfiledCodeHeapSize");
+ warning("%s is full. Compiler has been disabled.", get_code_heap_name(code_blob_type));
+ warning("Try increasing the code heap size using -XX:%s=", get_code_heap_flag_name(code_blob_type));
} else {
warning("CodeCache is full. Compiler has been disabled.");
warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize=");
--- a/hotspot/src/share/vm/code/codeCache.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/code/codeCache.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -100,6 +100,8 @@
static void add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type);
static CodeHeap* get_code_heap(CodeBlob* cb); // Returns the CodeHeap for the given CodeBlob
static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType
+ // Returns the name of the VM option to set the size of the corresponding CodeHeap
+ static const char* get_code_heap_flag_name(int code_blob_type);
static bool heap_available(int code_blob_type); // Returns true if an own CodeHeap for the given CodeBlobType is available
static ReservedCodeSpace reserve_heap_memory(size_t size); // Reserves one continuous chunk of memory for the CodeHeaps
@@ -118,16 +120,16 @@
static void initialize();
// Allocation/administration
- static CodeBlob* allocate(int size, int code_blob_type, bool is_critical = false); // allocates a new CodeBlob
- static void commit(CodeBlob* cb); // called when the allocated CodeBlob has been filled
- static int alignment_unit(); // guaranteed alignment of all CodeBlobs
- static int alignment_offset(); // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)
- static void free(CodeBlob* cb); // frees a CodeBlob
- static bool contains(void *p); // returns whether p is included
- static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
- static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs
- static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
- static void alive_nmethods_do(void f(nmethod* nm)); // iterates over all alive nmethods
+ static CodeBlob* allocate(int size, int code_blob_type); // allocates a new CodeBlob
+ static void commit(CodeBlob* cb); // called when the allocated CodeBlob has been filled
+ static int alignment_unit(); // guaranteed alignment of all CodeBlobs
+ static int alignment_offset(); // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)
+ static void free(CodeBlob* cb); // frees a CodeBlob
+ static bool contains(void *p); // returns whether p is included
+ static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
+ static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs
+ static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
+ static void alive_nmethods_do(void f(nmethod* nm)); // iterates over all alive nmethods
// Lookup
static CodeBlob* find_blob(void* start); // Returns the CodeBlob containing the given address
@@ -180,7 +182,6 @@
static size_t unallocated_capacity();
static size_t max_capacity();
- static bool is_full(int* code_blob_type);
static double reverse_free_ratio(int code_blob_type);
static bool needs_cache_clean() { return _needs_cache_clean; }
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/code/nmethod.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -804,10 +804,7 @@
#endif // def HAVE_DTRACE_H
void* nmethod::operator new(size_t size, int nmethod_size, int comp_level) throw () {
- // With a SegmentedCodeCache, nmethods are allocated on separate heaps and therefore do not share memory
- // with critical CodeBlobs. We define the allocation as critical to make sure all code heap memory is used.
- bool is_critical = SegmentedCodeCache;
- return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level), is_critical);
+ return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level));
}
nmethod::nmethod(
--- a/hotspot/src/share/vm/code/vtableStubs.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/code/vtableStubs.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -63,7 +63,6 @@
// If changing the name, update the other file accordingly.
BufferBlob* blob = BufferBlob::create("vtable chunks", bytes);
if (blob == NULL) {
- CompileBroker::handle_full_code_cache(CodeBlobType::NonNMethod);
return NULL;
}
_chunk = blob->content_begin();
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -156,8 +156,6 @@
CompileQueue* CompileBroker::_c2_compile_queue = NULL;
CompileQueue* CompileBroker::_c1_compile_queue = NULL;
-GrowableArray<CompilerThread*>* CompileBroker::_compiler_threads = NULL;
-
class CompilationLog : public StringEventLog {
public:
@@ -187,6 +185,14 @@
lm.print("\n");
log(thread, "%s", (const char*)lm);
}
+
+ void log_metaspace_failure(const char* reason) {
+ ResourceMark rm;
+ StringLogMessage lm;
+ lm.print("%4d COMPILE PROFILING SKIPPED: %s", -1, reason);
+ lm.print("\n");
+ log(JavaThread::current(), "%s", (const char*)lm);
+ }
};
static CompilationLog* _compilation_log = NULL;
@@ -649,13 +655,10 @@
lock()->notify_all();
}
-// ------------------------------------------------------------------
-// CompileQueue::get
-//
-// Get the next CompileTask from a CompileQueue
+/**
+ * Get the next CompileTask from a CompileQueue
+ */
CompileTask* CompileQueue::get() {
- NMethodSweeper::possibly_sweep();
-
MutexLocker locker(lock());
// If _first is NULL we have no more compile jobs. There are two reasons for
// having no compile jobs: First, we compiled everything we wanted. Second,
@@ -668,35 +671,16 @@
return NULL;
}
- if (UseCodeCacheFlushing && !CompileBroker::should_compile_new_jobs()) {
- // Wait a certain amount of time to possibly do another sweep.
- // We must wait until stack scanning has happened so that we can
- // transition a method's state from 'not_entrant' to 'zombie'.
- long wait_time = NmethodSweepCheckInterval * 1000;
- if (FLAG_IS_DEFAULT(NmethodSweepCheckInterval)) {
- // Only one thread at a time can do sweeping. Scale the
- // wait time according to the number of compiler threads.
- // As a result, the next sweep is likely to happen every 100ms
- // with an arbitrary number of threads that do sweeping.
- wait_time = 100 * CICompilerCount;
- }
- bool timeout = lock()->wait(!Mutex::_no_safepoint_check_flag, wait_time);
- if (timeout) {
- MutexUnlocker ul(lock());
- NMethodSweeper::possibly_sweep();
- }
- } else {
- // If there are no compilation tasks and we can compile new jobs
- // (i.e., there is enough free space in the code cache) there is
- // no need to invoke the sweeper. As a result, the hotness of methods
- // remains unchanged. This behavior is desired, since we want to keep
- // the stable state, i.e., we do not want to evict methods from the
- // code cache if it is unnecessary.
- // We need a timed wait here, since compiler threads can exit if compilation
- // is disabled forever. We use 5 seconds wait time; the exiting of compiler threads
- // is not critical and we do not want idle compiler threads to wake up too often.
- lock()->wait(!Mutex::_no_safepoint_check_flag, 5*1000);
- }
+ // If there are no compilation tasks and we can compile new jobs
+ // (i.e., there is enough free space in the code cache) there is
+ // no need to invoke the sweeper. As a result, the hotness of methods
+ // remains unchanged. This behavior is desired, since we want to keep
+ // the stable state, i.e., we do not want to evict methods from the
+ // code cache if it is unnecessary.
+ // We need a timed wait here, since compiler threads can exit if compilation
+ // is disabled forever. We use 5 seconds wait time; the exiting of compiler threads
+ // is not critical and we do not want idle compiler threads to wake up too often.
+ lock()->wait(!Mutex::_no_safepoint_check_flag, 5*1000);
}
if (CompileBroker::is_compilation_disabled_forever()) {
@@ -886,8 +870,8 @@
_compilers[1] = new SharkCompiler();
#endif // SHARK
- // Start the CompilerThreads
- init_compiler_threads(c1_count, c2_count);
+ // Start the compiler thread(s) and the sweeper thread
+ init_compiler_sweeper_threads(c1_count, c2_count);
// totalTime performance counter is always created as it is required
// by the implementation of java.lang.management.CompilationMBean.
{
@@ -991,13 +975,10 @@
}
-CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters,
- AbstractCompiler* comp, TRAPS) {
- CompilerThread* compiler_thread = NULL;
-
- Klass* k =
- SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
- true, CHECK_0);
+JavaThread* CompileBroker::make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters,
+ AbstractCompiler* comp, bool compiler_thread, TRAPS) {
+ JavaThread* thread = NULL;
+ Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_0);
instanceKlassHandle klass (THREAD, k);
instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_0);
Handle string = java_lang_String::create_from_str(name, CHECK_0);
@@ -1015,7 +996,11 @@
{
MutexLocker mu(Threads_lock, THREAD);
- compiler_thread = new CompilerThread(queue, counters);
+ if (compiler_thread) {
+ thread = new CompilerThread(queue, counters);
+ } else {
+ thread = new CodeCacheSweeperThread();
+ }
// At this point the new CompilerThread data-races with this startup
// thread (which I believe is the primoridal thread and NOT the VM
// thread). This means Java bytecodes being executed at startup can
@@ -1028,12 +1013,12 @@
// in that case. However, since this must work and we do not allow
// exceptions anyway, check and abort if this fails.
- if (compiler_thread == NULL || compiler_thread->osthread() == NULL){
+ if (thread == NULL || thread->osthread() == NULL) {
vm_exit_during_initialization("java.lang.OutOfMemoryError",
os::native_thread_creation_failed_msg());
}
- java_lang_Thread::set_thread(thread_oop(), compiler_thread);
+ java_lang_Thread::set_thread(thread_oop(), thread);
// Note that this only sets the JavaThread _priority field, which by
// definition is limited to Java priorities and not OS priorities.
@@ -1054,24 +1039,26 @@
native_prio = os::java_to_os_priority[NearMaxPriority];
}
}
- os::set_native_priority(compiler_thread, native_prio);
+ os::set_native_priority(thread, native_prio);
java_lang_Thread::set_daemon(thread_oop());
- compiler_thread->set_threadObj(thread_oop());
- compiler_thread->set_compiler(comp);
- Threads::add(compiler_thread);
- Thread::start(compiler_thread);
+ thread->set_threadObj(thread_oop());
+ if (compiler_thread) {
+ thread->as_CompilerThread()->set_compiler(comp);
+ }
+ Threads::add(thread);
+ Thread::start(thread);
}
// Let go of Threads_lock before yielding
os::naked_yield(); // make sure that the compiler thread is started early (especially helpful on SOLARIS)
- return compiler_thread;
+ return thread;
}
-void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) {
+void CompileBroker::init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count) {
EXCEPTION_MARK;
#if !defined(ZERO) && !defined(SHARK)
assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?");
@@ -1088,17 +1075,14 @@
int compiler_count = c1_compiler_count + c2_compiler_count;
- _compiler_threads =
- new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<CompilerThread*>(compiler_count, true);
-
char name_buffer[256];
+ const bool compiler_thread = true;
for (int i = 0; i < c2_compiler_count; i++) {
// Create a name for our thread.
sprintf(name_buffer, "C2 CompilerThread%d", i);
CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
// Shark and C2
- CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], CHECK);
- _compiler_threads->append(new_thread);
+ make_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], compiler_thread, CHECK);
}
for (int i = c2_compiler_count; i < compiler_count; i++) {
@@ -1106,13 +1090,17 @@
sprintf(name_buffer, "C1 CompilerThread%d", i);
CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK);
// C1
- CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_compile_queue, counters, _compilers[0], CHECK);
- _compiler_threads->append(new_thread);
+ make_thread(name_buffer, _c1_compile_queue, counters, _compilers[0], compiler_thread, CHECK);
}
if (UsePerfData) {
PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, compiler_count, CHECK);
}
+
+ if (MethodFlushing) {
+ // Initialize the sweeper thread
+ make_thread("Sweeper thread", NULL, NULL, NULL, false, CHECK);
+ }
}
@@ -1759,13 +1747,6 @@
// We need this HandleMark to avoid leaking VM handles.
HandleMark hm(thread);
- // Check if the CodeCache is full
- int code_blob_type = 0;
- if (CodeCache::is_full(&code_blob_type)) {
- // The CodeHeap for code_blob_type is really full
- handle_full_code_cache(code_blob_type);
- }
-
CompileTask* task = queue->get();
if (task == NULL) {
continue;
@@ -1773,8 +1754,9 @@
// Give compiler threads an extra quanta. They tend to be bursty and
// this helps the compiler to finish up the job.
- if( CompilerThreadHintNoPreempt )
+ if (CompilerThreadHintNoPreempt) {
os::hint_no_preempt();
+ }
// trace per thread time and compile statistics
CompilerCounters* counters = ((CompilerThread*)thread)->counters();
@@ -1843,6 +1825,18 @@
warning("Cannot open log file: %s", file_name);
}
+void CompileBroker::log_metaspace_failure() {
+ const char* message = "some methods may not be compiled because metaspace "
+ "is out of memory";
+ if (_compilation_log != NULL) {
+ _compilation_log->log_metaspace_failure(message);
+ }
+ if (PrintCompilation) {
+ tty->print_cr("COMPILE PROFILING SKIPPED: %s", message);
+ }
+}
+
+
// ------------------------------------------------------------------
// CompileBroker::set_should_block
//
@@ -2074,8 +2068,10 @@
}
/**
- * The CodeCache is full. Print out warning and disable compilation
- * or try code cache cleaning so compilation can continue later.
+ * The CodeCache is full. Print warning and disable compilation.
+ * Schedule code cache cleaning so compilation can continue later.
+ * This function needs to be called only from CodeCache::allocate(),
+ * since we currently handle a full code cache uniformly.
*/
void CompileBroker::handle_full_code_cache(int code_blob_type) {
UseInterpreter = true;
@@ -2107,10 +2103,6 @@
if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) {
NMethodSweeper::log_sweep("disable_compiler");
}
- // Switch to 'vm_state'. This ensures that possibly_sweep() can be called
- // without having to consider the state in which the current thread is.
- ThreadInVMfromUnknown in_vm;
- NMethodSweeper::possibly_sweep();
} else {
disable_compilation_forever();
}
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -290,8 +290,6 @@
static CompileQueue* _c2_compile_queue;
static CompileQueue* _c1_compile_queue;
- static GrowableArray<CompilerThread*>* _compiler_threads;
-
// performance counters
static PerfCounter* _perf_total_compilation;
static PerfCounter* _perf_native_compilation;
@@ -339,8 +337,8 @@
static volatile jint _print_compilation_warning;
- static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, TRAPS);
- static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count);
+ static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS);
+ static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count);
static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level);
static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level);
static bool is_compile_blocking();
@@ -473,6 +471,9 @@
static int get_sum_nmethod_code_size() { return _sum_nmethod_code_size; }
static long get_peak_compilation_time() { return _peak_compilation_time; }
static long get_total_compilation_time() { return _t_total_compilation.milliseconds(); }
+
+ // Log that compilation profiling is skipped because metaspace is full.
+ static void log_metaspace_failure();
};
#endif // SHARE_VM_COMPILER_COMPILEBROKER_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -127,41 +127,6 @@
};
-class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure {
- size_t _num_processed;
- CardTableModRefBS* _ctbs;
- int _histo[256];
-
- public:
- ClearLoggedCardTableEntryClosure() :
- _num_processed(0), _ctbs(G1CollectedHeap::heap()->g1_barrier_set())
- {
- for (int i = 0; i < 256; i++) _histo[i] = 0;
- }
-
- bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
- unsigned char* ujb = (unsigned char*)card_ptr;
- int ind = (int)(*ujb);
- _histo[ind]++;
-
- *card_ptr = (jbyte)CardTableModRefBS::clean_card_val();
- _num_processed++;
-
- return true;
- }
-
- size_t num_processed() { return _num_processed; }
-
- void print_histo() {
- gclog_or_tty->print_cr("Card table value histogram:");
- for (int i = 0; i < 256; i++) {
- if (_histo[i] != 0) {
- gclog_or_tty->print_cr(" %d: %d", i, _histo[i]);
- }
- }
- }
-};
-
class RedirtyLoggedCardTableEntryClosure : public CardTableEntryClosure {
private:
size_t _num_processed;
@@ -475,48 +440,6 @@
return !hr->is_humongous();
}
-void G1CollectedHeap::check_ct_logs_at_safepoint() {
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
- CardTableModRefBS* ct_bs = g1_barrier_set();
-
- // Count the dirty cards at the start.
- CountNonCleanMemRegionClosure count1(this);
- ct_bs->mod_card_iterate(&count1);
- int orig_count = count1.n();
-
- // First clear the logged cards.
- ClearLoggedCardTableEntryClosure clear;
- dcqs.apply_closure_to_all_completed_buffers(&clear);
- dcqs.iterate_closure_all_threads(&clear, false);
- clear.print_histo();
-
- // Now ensure that there's no dirty cards.
- CountNonCleanMemRegionClosure count2(this);
- ct_bs->mod_card_iterate(&count2);
- if (count2.n() != 0) {
- gclog_or_tty->print_cr("Card table has %d entries; %d originally",
- count2.n(), orig_count);
- }
- guarantee(count2.n() == 0, "Card table should be clean.");
-
- RedirtyLoggedCardTableEntryClosure redirty;
- dcqs.apply_closure_to_all_completed_buffers(&redirty);
- dcqs.iterate_closure_all_threads(&redirty, false);
- gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.",
- clear.num_processed(), orig_count);
- guarantee(redirty.num_processed() == clear.num_processed(),
- err_msg("Redirtied "SIZE_FORMAT" cards, bug cleared "SIZE_FORMAT,
- redirty.num_processed(), clear.num_processed()));
-
- CountNonCleanMemRegionClosure count3(this);
- ct_bs->mod_card_iterate(&count3);
- if (count3.n() != orig_count) {
- gclog_or_tty->print_cr("Should have restored them all: orig = %d, final = %d.",
- orig_count, count3.n());
- guarantee(count3.n() >= orig_count, "Should have restored them all.");
- }
-}
-
// Private class members.
G1CollectedHeap* G1CollectedHeap::_g1h;
@@ -5760,14 +5683,10 @@
// not copied during the pause.
process_discovered_references(n_workers);
- // Weak root processing.
- {
+ if (G1StringDedup::is_enabled()) {
G1STWIsAliveClosure is_alive(this);
G1KeepAliveClosure keep_alive(this);
- JNIHandles::weak_oops_do(&is_alive, &keep_alive);
- if (G1StringDedup::is_enabled()) {
- G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive);
- }
+ G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive);
}
_allocator->release_gc_alloc_regions(n_workers, evacuation_info);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -797,9 +797,6 @@
// The closure used to refine a single card.
RefineCardTableEntryClosure* _refine_cte_cl;
- // A function to check the consistency of dirty card logs.
- void check_ct_logs_at_safepoint();
-
// A DirtyCardQueueSet that is used to hold cards that contain
// references into the current collection set. This is used to
// update the remembered sets of the regions in the collection
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1077,7 +1077,6 @@
address SignatureHandlerLibrary::set_handler_blob() {
BufferBlob* handler_blob = BufferBlob::create("native signature handlers", blob_size);
if (handler_blob == NULL) {
- CompileBroker::handle_full_code_cache(CodeBlobType::NonNMethod);
return NULL;
}
address handler = handler_blob->code_begin();
--- a/hotspot/src/share/vm/memory/heap.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/memory/heap.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -171,13 +171,13 @@
}
-void* CodeHeap::allocate(size_t instance_size, bool is_critical) {
+void* CodeHeap::allocate(size_t instance_size) {
size_t number_of_segments = size_to_segments(instance_size + header_size());
assert(segments_to_size(number_of_segments) >= sizeof(FreeBlock), "not enough room for FreeList");
// First check if we can satisfy request from freelist
NOT_PRODUCT(verify());
- HeapBlock* block = search_freelist(number_of_segments, is_critical);
+ HeapBlock* block = search_freelist(number_of_segments);
NOT_PRODUCT(verify());
if (block != NULL) {
@@ -191,15 +191,6 @@
// Ensure minimum size for allocation to the heap.
number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments);
- if (!is_critical) {
- // Make sure the allocation fits in the unallocated heap without using
- // the CodeCacheMimimumFreeSpace that is reserved for critical allocations.
- if (segments_to_size(number_of_segments) > (heap_unallocated_capacity() - CodeCacheMinimumFreeSpace)) {
- // Fail allocation
- return NULL;
- }
- }
-
if (_next_segment + number_of_segments <= _number_of_committed_segments) {
mark_segmap_as_used(_next_segment, _next_segment + number_of_segments);
HeapBlock* b = block_at(_next_segment);
@@ -427,24 +418,17 @@
* Search freelist for an entry on the list with the best fit.
* @return NULL, if no one was found
*/
-FreeBlock* CodeHeap::search_freelist(size_t length, bool is_critical) {
+FreeBlock* CodeHeap::search_freelist(size_t length) {
FreeBlock* found_block = NULL;
FreeBlock* found_prev = NULL;
size_t found_length = 0;
FreeBlock* prev = NULL;
FreeBlock* cur = _freelist;
- const size_t critical_boundary = (size_t)high_boundary() - CodeCacheMinimumFreeSpace;
// Search for first block that fits
while(cur != NULL) {
if (cur->length() >= length) {
- // Non critical allocations are not allowed to use the last part of the code heap.
- // Make sure the end of the allocation doesn't cross into the last part of the code heap.
- if (!is_critical && (((size_t)cur + length) > critical_boundary)) {
- // The freelist is sorted by address - if one fails, all consecutive will also fail.
- break;
- }
// Remember block, its previous element, and its length
found_block = cur;
found_prev = prev;
--- a/hotspot/src/share/vm/memory/heap.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/memory/heap.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -120,7 +120,7 @@
// Toplevel freelist management
void add_to_freelist(HeapBlock* b);
- FreeBlock* search_freelist(size_t length, bool is_critical);
+ FreeBlock* search_freelist(size_t length);
// Iteration helpers
void* next_free(HeapBlock* b) const;
@@ -140,8 +140,8 @@
bool expand_by(size_t size); // expands committed memory by size
// Memory allocation
- void* allocate (size_t size, bool is_critical); // allocates a block of size or returns NULL
- void deallocate(void* p); // deallocates a block
+ void* allocate (size_t size); // Allocate 'size' bytes in the code cache or return NULL
+ void deallocate(void* p); // Deallocate memory
// Attributes
char* low_boundary() const { return _memory.low_boundary (); }
--- a/hotspot/src/share/vm/memory/metaspace.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -3157,6 +3157,16 @@
SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment);
SharedMiscCodeSize = align_size_up(SharedMiscCodeSize, max_alignment);
+ // the min_misc_code_size estimate is based on MetaspaceShared::generate_vtable_methods()
+ uintx min_misc_code_size = align_size_up(
+ (MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size) *
+ (sizeof(void*) + MetaspaceShared::vtbl_method_size) + MetaspaceShared::vtbl_common_code_size,
+ max_alignment);
+
+ if (SharedMiscCodeSize < min_misc_code_size) {
+ report_out_of_shared_space(SharedMiscCode);
+ }
+
// Initialize with the sum of the shared space sizes. The read-only
// and read write metaspace chunks will be allocated out of this and the
// remainder is the misc code and data chunks.
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -714,12 +714,17 @@
int class_list_path_len = (int)strlen(class_list_path_str);
if (class_list_path_len >= 3) {
if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) {
- strcat(class_list_path_str, os::file_separator());
- strcat(class_list_path_str, "lib");
+ if (class_list_path_len < JVM_MAXPATHLEN - 4) {
+ strncat(class_list_path_str, os::file_separator(), 1);
+ strncat(class_list_path_str, "lib", 3);
+ }
}
}
- strcat(class_list_path_str, os::file_separator());
- strcat(class_list_path_str, "classlist");
+ class_list_path_len = (int)strlen(class_list_path_str);
+ if (class_list_path_len < JVM_MAXPATHLEN - 10) {
+ strncat(class_list_path_str, os::file_separator(), 1);
+ strncat(class_list_path_str, "classlist", 9);
+ }
class_list_path = class_list_path_str;
} else {
class_list_path = SharedClassListFile;
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -57,11 +57,16 @@
static bool _archive_loading_failed;
public:
enum {
- vtbl_list_size = 17, // number of entries in the shared space vtable list.
- num_virtuals = 200 // maximum number of virtual functions
- // If virtual functions are added to Metadata,
- // this number needs to be increased. Also,
- // SharedMiscCodeSize will need to be increased.
+ vtbl_list_size = 17, // number of entries in the shared space vtable list.
+ num_virtuals = 200, // maximum number of virtual functions
+ // If virtual functions are added to Metadata,
+ // this number needs to be increased. Also,
+ // SharedMiscCodeSize will need to be increased.
+ // The following 2 sizes were based on
+ // MetaspaceShared::generate_vtable_methods()
+ vtbl_method_size = 16, // conservative size of the mov1 and jmp instructions
+ // for the x64 platform
+ vtbl_common_code_size = (1*K) // conservative size of the "common_code" for the x64 platform
};
enum {
--- a/hotspot/src/share/vm/oops/constMethod.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/constMethod.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -277,7 +277,7 @@
bool has_stackmap_table() const { return _stackmap_data != NULL; }
void init_fingerprint() {
- const uint64_t initval = CONST64(0x8000000000000000);
+ const uint64_t initval = UCONST64(0x8000000000000000);
_fingerprint = initval;
}
--- a/hotspot/src/share/vm/oops/constantPool.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -206,7 +206,8 @@
}
}
-Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, TRAPS) {
+Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which,
+ bool save_resolution_error, TRAPS) {
assert(THREAD->is_Java_thread(), "must be a Java thread");
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
@@ -249,7 +250,18 @@
// Failed to resolve class. We must record the errors so that subsequent attempts
// to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
if (HAS_PENDING_EXCEPTION) {
- save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_0);
+ if (save_resolution_error) {
+ save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_NULL);
+ // If CHECK_NULL above doesn't return the exception, that means that
+ // some other thread has beaten us and has resolved the class.
+ // To preserve old behavior, we return the resolved class.
+ entry = this_cp->resolved_klass_at(which);
+ assert(entry.is_resolved(), "must be resolved if exception was cleared");
+ assert(entry.get_klass()->is_klass(), "must be resolved to a klass");
+ return entry.get_klass();
+ } else {
+ return NULL; // return the pending exception
+ }
}
// Make this class loader depend upon the class loader owning the class reference
@@ -260,10 +272,10 @@
// skip resolving the constant pool so that this code gets
// called the next time some bytecodes refer to this class.
trace_class_resolution(this_cp, k);
- return k();
- } else {
- this_cp->klass_at_put(which, k());
- }
+ return k();
+ } else {
+ this_cp->klass_at_put(which, k());
+ }
entry = this_cp->resolved_klass_at(which);
assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
@@ -573,24 +585,25 @@
Symbol* message = exception_message(this_cp, which, tag, PENDING_EXCEPTION);
SystemDictionary::add_resolution_error(this_cp, which, error, message);
// CAS in the tag. If a thread beat us to registering this error that's fine.
- // If another thread resolved the reference, this is an error. The resolution
- // must deterministically get an error. So why do we save this?
- // We save this because jvmti can add classes to the bootclass path after this
- // error, so it needs to get the same error if the error is first.
+ // If another thread resolved the reference, this is a race condition. This
+ // thread may have had a security manager or something temporary.
+ // This doesn't deterministically get an error. So why do we save this?
+ // We save this because jvmti can add classes to the bootclass path after
+ // this error, so it needs to get the same error if the error is first.
jbyte old_tag = Atomic::cmpxchg((jbyte)error_tag,
(jbyte*)this_cp->tag_addr_at(which), (jbyte)tag.value());
- assert(old_tag == error_tag || old_tag == tag.value(), "should not be resolved otherwise");
+ if (old_tag != error_tag && old_tag != tag.value()) {
+ // MethodHandles and MethodType doesn't change to resolved version.
+ assert(this_cp->tag_at(which).is_klass(), "Wrong tag value");
+ // Forget the exception and use the resolved class.
+ CLEAR_PENDING_EXCEPTION;
+ }
} else {
// some other thread put this in error state
throw_resolution_error(this_cp, which, CHECK);
}
-
- // This exits with some pending exception
- assert(HAS_PENDING_EXCEPTION, "should not be cleared");
}
-
-
// Called to resolve constants in the constant pool and return an oop.
// Some constant pool entries cache their resolved oop. This is also
// called to create oops from constants to use in arguments for invokedynamic
@@ -627,7 +640,7 @@
case JVM_CONSTANT_Class:
{
assert(cache_index == _no_index_sentinel, "should not have been set");
- Klass* resolved = klass_at_impl(this_cp, index, CHECK_NULL);
+ Klass* resolved = klass_at_impl(this_cp, index, true, CHECK_NULL);
// ldc wants the java mirror.
result_oop = resolved->java_mirror();
break;
@@ -660,7 +673,7 @@
ref_kind, index, this_cp->method_handle_index_at(index),
callee_index, name->as_C_string(), signature->as_C_string());
KlassHandle callee;
- { Klass* k = klass_at_impl(this_cp, callee_index, CHECK_NULL);
+ { Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL);
callee = KlassHandle(THREAD, k);
}
KlassHandle klass(THREAD, this_cp->pool_holder());
--- a/hotspot/src/share/vm/oops/constantPool.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -336,7 +336,13 @@
Klass* klass_at(int which, TRAPS) {
constantPoolHandle h_this(THREAD, this);
- return klass_at_impl(h_this, which, CHECK_NULL);
+ return klass_at_impl(h_this, which, true, CHECK_NULL);
+ }
+
+ // Version of klass_at that doesn't save the resolution error, called during deopt
+ Klass* klass_at_ignore_error(int which, TRAPS) {
+ constantPoolHandle h_this(THREAD, this);
+ return klass_at_impl(h_this, which, false, CHECK_NULL);
}
Symbol* klass_name_at(int which); // Returns the name, w/o resolving.
@@ -793,7 +799,8 @@
// Implementation of methods that needs an exposed 'this' pointer, in order to
// handle GC while executing the method
- static Klass* klass_at_impl(constantPoolHandle this_cp, int which, TRAPS);
+ static Klass* klass_at_impl(constantPoolHandle this_cp, int which,
+ bool save_resolution_error, TRAPS);
static oop string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS);
static void trace_class_resolution(constantPoolHandle this_cp, KlassHandle k);
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -736,6 +736,41 @@
}
}
+// Eagerly initialize superinterfaces that declare default methods (concrete instance: any access)
+void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAPS) {
+ if (this_k->has_default_methods()) {
+ for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
+ Klass* iface = this_k->local_interfaces()->at(i);
+ InstanceKlass* ik = InstanceKlass::cast(iface);
+ if (ik->should_be_initialized()) {
+ if (ik->has_default_methods()) {
+ ik->initialize_super_interfaces(ik, THREAD);
+ }
+ // Only initialize() interfaces that "declare" concrete methods.
+ // has_default_methods drives searching superinterfaces since it
+ // means has_default_methods in its superinterface hierarchy
+ if (!HAS_PENDING_EXCEPTION && ik->declares_default_methods()) {
+ ik->initialize(THREAD);
+ }
+ if (HAS_PENDING_EXCEPTION) {
+ Handle e(THREAD, PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+ {
+ EXCEPTION_MARK;
+ // Locks object, set state, and notify all waiting threads
+ this_k->set_initialization_state_and_notify(
+ initialization_error, THREAD);
+
+ // ignore any exception thrown, superclass initialization error is
+ // thrown below
+ CLEAR_PENDING_EXCEPTION;
+ }
+ THROW_OOP(e());
+ }
+ }
+ }
+ }
+}
void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) {
// Make sure klass is linked (verified) before initialization
@@ -815,33 +850,11 @@
}
}
+ // Recursively initialize any superinterfaces that declare default methods
+ // Only need to recurse if has_default_methods which includes declaring and
+ // inheriting default methods
if (this_k->has_default_methods()) {
- // Step 7.5: initialize any interfaces which have default methods
- for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
- Klass* iface = this_k->local_interfaces()->at(i);
- InstanceKlass* ik = InstanceKlass::cast(iface);
- if (ik->has_default_methods() && ik->should_be_initialized()) {
- ik->initialize(THREAD);
-
- if (HAS_PENDING_EXCEPTION) {
- Handle e(THREAD, PENDING_EXCEPTION);
- CLEAR_PENDING_EXCEPTION;
- {
- EXCEPTION_MARK;
- // Locks object, set state, and notify all waiting threads
- this_k->set_initialization_state_and_notify(
- initialization_error, THREAD);
-
- // ignore any exception thrown, superclass initialization error is
- // thrown below
- CLEAR_PENDING_EXCEPTION;
- }
- DTRACE_CLASSINIT_PROBE_WAIT(
- super__failed, InstanceKlass::cast(this_k()), -1, wait);
- THROW_OOP(e());
- }
- }
- }
+ this_k->initialize_super_interfaces(this_k, CHECK);
}
// Step 8
@@ -1717,6 +1730,25 @@
return id;
}
+// Figure out how many jmethodIDs haven't been allocated, and make
+// sure space for them is pre-allocated. This makes getting all
+// method ids much, much faster with classes with more than 8
+// methods, and has a *substantial* effect on performance with jvmti
+// code that loads all jmethodIDs for all classes.
+void InstanceKlass::ensure_space_for_methodids(int start_offset) {
+ int new_jmeths = 0;
+ int length = methods()->length();
+ for (int index = start_offset; index < length; index++) {
+ Method* m = methods()->at(index);
+ jmethodID id = m->find_jmethod_id_or_null();
+ if (id == NULL) {
+ new_jmeths++;
+ }
+ }
+ if (new_jmeths != 0) {
+ Method::ensure_jmethod_ids(class_loader_data(), new_jmeths);
+ }
+}
// Common code to fetch the jmethodID from the cache or update the
// cache with the new jmethodID. This function should never do anything
@@ -2486,7 +2518,7 @@
// If this is an anonymous class, append a hash to make the name unique
if (is_anonymous()) {
intptr_t hash = (java_mirror() != NULL) ? java_mirror()->identity_hash() : 0;
- sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);
+ jio_snprintf(hash_buf, sizeof(hash_buf), "/" UINTX_FORMAT, (uintx)hash);
hash_len = (int)strlen(hash_buf);
}
@@ -2779,19 +2811,18 @@
// On-stack replacement stuff
void InstanceKlass::add_osr_nmethod(nmethod* n) {
// only one compilation can be active
- NEEDS_CLEANUP
- // This is a short non-blocking critical region, so the no safepoint check is ok.
- OsrList_lock->lock_without_safepoint_check();
- assert(n->is_osr_method(), "wrong kind of nmethod");
- n->set_osr_link(osr_nmethods_head());
- set_osr_nmethods_head(n);
- // Raise the highest osr level if necessary
- if (TieredCompilation) {
- Method* m = n->method();
- m->set_highest_osr_comp_level(MAX2(m->highest_osr_comp_level(), n->comp_level()));
+ {
+ // This is a short non-blocking critical region, so the no safepoint check is ok.
+ MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
+ assert(n->is_osr_method(), "wrong kind of nmethod");
+ n->set_osr_link(osr_nmethods_head());
+ set_osr_nmethods_head(n);
+ // Raise the highest osr level if necessary
+ if (TieredCompilation) {
+ Method* m = n->method();
+ m->set_highest_osr_comp_level(MAX2(m->highest_osr_comp_level(), n->comp_level()));
+ }
}
- // Remember to unlock again
- OsrList_lock->unlock();
// Get rid of the osr methods for the same bci that have lower levels.
if (TieredCompilation) {
@@ -2807,7 +2838,7 @@
void InstanceKlass::remove_osr_nmethod(nmethod* n) {
// This is a short non-blocking critical region, so the no safepoint check is ok.
- OsrList_lock->lock_without_safepoint_check();
+ MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
assert(n->is_osr_method(), "wrong kind of nmethod");
nmethod* last = NULL;
nmethod* cur = osr_nmethods_head();
@@ -2844,13 +2875,27 @@
}
m->set_highest_osr_comp_level(max_level);
}
- // Remember to unlock again
- OsrList_lock->unlock();
+}
+
+int InstanceKlass::mark_osr_nmethods(const Method* m) {
+ // This is a short non-blocking critical region, so the no safepoint check is ok.
+ MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
+ nmethod* osr = osr_nmethods_head();
+ int found = 0;
+ while (osr != NULL) {
+ assert(osr->is_osr_method(), "wrong kind of nmethod found in chain");
+ if (osr->method() == m) {
+ osr->mark_for_deoptimization();
+ found++;
+ }
+ osr = osr->osr_link();
+ }
+ return found;
}
nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, bool match_level) const {
// This is a short non-blocking critical region, so the no safepoint check is ok.
- OsrList_lock->lock_without_safepoint_check();
+ MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
nmethod* osr = osr_nmethods_head();
nmethod* best = NULL;
while (osr != NULL) {
@@ -2866,14 +2911,12 @@
if (match_level) {
if (osr->comp_level() == comp_level) {
// Found a match - return it.
- OsrList_lock->unlock();
return osr;
}
} else {
if (best == NULL || (osr->comp_level() > best->comp_level())) {
if (osr->comp_level() == CompLevel_highest_tier) {
// Found the best possible - return it.
- OsrList_lock->unlock();
return osr;
}
best = osr;
@@ -2882,7 +2925,6 @@
}
osr = osr->osr_link();
}
- OsrList_lock->unlock();
if (best != NULL && best->comp_level() >= comp_level && match_level == false) {
return best;
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -199,13 +199,14 @@
bool _has_unloaded_dependent;
enum {
- _misc_rewritten = 1 << 0, // methods rewritten.
- _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
- _misc_should_verify_class = 1 << 2, // allow caching of preverification
- _misc_is_anonymous = 1 << 3, // has embedded _host_klass field
- _misc_is_contended = 1 << 4, // marked with contended annotation
- _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods
- _misc_has_been_redefined = 1 << 6 // class has been redefined
+ _misc_rewritten = 1 << 0, // methods rewritten.
+ _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
+ _misc_should_verify_class = 1 << 2, // allow caching of preverification
+ _misc_is_anonymous = 1 << 3, // has embedded _host_klass field
+ _misc_is_contended = 1 << 4, // marked with contended annotation
+ _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods
+ _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access)
+ _misc_has_been_redefined = 1 << 7 // class has been redefined
};
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
@@ -651,6 +652,17 @@
}
}
+ bool declares_default_methods() const {
+ return (_misc_flags & _misc_declares_default_methods) != 0;
+ }
+ void set_declares_default_methods(bool b) {
+ if (b) {
+ _misc_flags |= _misc_declares_default_methods;
+ } else {
+ _misc_flags &= ~_misc_declares_default_methods;
+ }
+ }
+
// for adding methods, ConstMethod::UNSET_IDNUM means no more ids available
inline u2 next_method_idnum();
void set_initial_method_idnum(u2 value) { _idnum_allocated_count = value; }
@@ -686,6 +698,7 @@
jmethodID** to_dealloc_jmeths_p);
static void get_jmethod_id_length_value(jmethodID* cache, size_t idnum,
size_t *length_p, jmethodID* id_p);
+ void ensure_space_for_methodids(int start_offset = 0);
jmethodID jmethod_id_or_null(Method* method);
// annotations support
@@ -742,6 +755,7 @@
void set_osr_nmethods_head(nmethod* h) { _osr_nmethods_head = h; };
void add_osr_nmethod(nmethod* n);
void remove_osr_nmethod(nmethod* n);
+ int mark_osr_nmethods(const Method* m);
nmethod* lookup_osr_nmethod(const Method* m, int bci, int level, bool match_level) const;
// Breakpoint support (see methods on Method* for details)
@@ -1022,6 +1036,7 @@
static bool link_class_impl (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS);
static bool verify_code (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS);
static void initialize_impl (instanceKlassHandle this_k, TRAPS);
+ static void initialize_super_interfaces (instanceKlassHandle this_k, TRAPS);
static void eager_initialize_impl (instanceKlassHandle this_k);
static void set_initialization_state_and_notify_impl (instanceKlassHandle this_k, ClassState state, TRAPS);
static void call_class_initializer_impl (instanceKlassHandle this_k, TRAPS);
--- a/hotspot/src/share/vm/oops/method.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/method.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -368,6 +368,13 @@
// Build a MethodData* object to hold information about this method
// collected in the interpreter.
void Method::build_interpreter_method_data(methodHandle method, TRAPS) {
+ // Do not profile the method if metaspace has hit an OOM previously
+ // allocating profiling data. Callers clear pending exception so don't
+ // add one here.
+ if (ClassLoaderDataGraph::has_metaspace_oom()) {
+ return;
+ }
+
// Do not profile method if current thread holds the pending list lock,
// which avoids deadlock for acquiring the MethodData_lock.
if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
@@ -379,7 +386,13 @@
MutexLocker ml(MethodData_lock, THREAD);
if (method->method_data() == NULL) {
ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
- MethodData* method_data = MethodData::allocate(loader_data, method, CHECK);
+ MethodData* method_data = MethodData::allocate(loader_data, method, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ CompileBroker::log_metaspace_failure();
+ ClassLoaderDataGraph::set_metaspace_oom(true);
+ return; // return the exception (which is cleared)
+ }
+
method->set_method_data(method_data);
if (PrintMethodData && (Verbose || WizardMode)) {
ResourceMark rm(THREAD);
@@ -392,9 +405,19 @@
}
MethodCounters* Method::build_method_counters(Method* m, TRAPS) {
+ // Do not profile the method if metaspace has hit an OOM previously
+ if (ClassLoaderDataGraph::has_metaspace_oom()) {
+ return NULL;
+ }
+
methodHandle mh(m);
ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
- MethodCounters* counters = MethodCounters::allocate(loader_data, CHECK_NULL);
+ MethodCounters* counters = MethodCounters::allocate(loader_data, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ CompileBroker::log_metaspace_failure();
+ ClassLoaderDataGraph::set_metaspace_oom(true);
+ return NULL; // return the exception (which is cleared)
+ }
if (!mh->init_method_counters(counters)) {
MetadataFactory::free_metadata(loader_data, counters);
}
@@ -1295,6 +1318,10 @@
vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
if (id != vmIntrinsics::_none) {
set_intrinsic_id(id);
+ if (id == vmIntrinsics::_Class_cast) {
+ // Even if the intrinsic is rejected, we want to inline this simple method.
+ set_force_inline(true);
+ }
return;
}
@@ -1704,59 +1731,98 @@
// jmethodID handling
// This is a block allocating object, sort of like JNIHandleBlock, only a
-// lot simpler. There aren't many of these, they aren't long, they are rarely
-// deleted and so we can do some suboptimal things.
+// lot simpler.
// It's allocated on the CHeap because once we allocate a jmethodID, we can
// never get rid of it.
-// It would be nice to be able to parameterize the number of methods for
-// the null_class_loader but then we'd have to turn this and ClassLoaderData
-// into templates.
+
+static const int min_block_size = 8;
+
+class JNIMethodBlockNode : public CHeapObj<mtClass> {
+ friend class JNIMethodBlock;
+ Method** _methods;
+ int _number_of_methods;
+ int _top;
+ JNIMethodBlockNode* _next;
+
+ public:
+
+ JNIMethodBlockNode(int num_methods = min_block_size);
-// I feel like this brain dead class should exist somewhere in the STL
+ ~JNIMethodBlockNode() { FREE_C_HEAP_ARRAY(Method*, _methods, mtInternal); }
+
+ void ensure_methods(int num_addl_methods) {
+ if (_top < _number_of_methods) {
+ num_addl_methods -= _number_of_methods - _top;
+ if (num_addl_methods <= 0) {
+ return;
+ }
+ }
+ if (_next == NULL) {
+ _next = new JNIMethodBlockNode(MAX2(num_addl_methods, min_block_size));
+ } else {
+ _next->ensure_methods(num_addl_methods);
+ }
+ }
+};
class JNIMethodBlock : public CHeapObj<mtClass> {
- enum { number_of_methods = 8 };
-
- Method* _methods[number_of_methods];
- int _top;
- JNIMethodBlock* _next;
+ JNIMethodBlockNode _head;
+ JNIMethodBlockNode *_last_free;
public:
static Method* const _free_method;
- JNIMethodBlock() : _next(NULL), _top(0) {
- for (int i = 0; i< number_of_methods; i++) _methods[i] = _free_method;
+ JNIMethodBlock(int initial_capacity = min_block_size)
+ : _head(initial_capacity), _last_free(&_head) {}
+
+ void ensure_methods(int num_addl_methods) {
+ _last_free->ensure_methods(num_addl_methods);
}
Method** add_method(Method* m) {
- if (_top < number_of_methods) {
- // top points to the next free entry.
- int i = _top;
- _methods[i] = m;
- _top++;
- return &_methods[i];
- } else if (_top == number_of_methods) {
- // if the next free entry ran off the block see if there's a free entry
- for (int i = 0; i< number_of_methods; i++) {
- if (_methods[i] == _free_method) {
- _methods[i] = m;
- return &_methods[i];
+ for (JNIMethodBlockNode* b = _last_free; b != NULL; b = b->_next) {
+ if (b->_top < b->_number_of_methods) {
+ // top points to the next free entry.
+ int i = b->_top;
+ b->_methods[i] = m;
+ b->_top++;
+ _last_free = b;
+ return &(b->_methods[i]);
+ } else if (b->_top == b->_number_of_methods) {
+ // if the next free entry ran off the block see if there's a free entry
+ for (int i = 0; i < b->_number_of_methods; i++) {
+ if (b->_methods[i] == _free_method) {
+ b->_methods[i] = m;
+ _last_free = b;
+ return &(b->_methods[i]);
+ }
}
+ // Only check each block once for frees. They're very unlikely.
+ // Increment top past the end of the block.
+ b->_top++;
}
- // Only check each block once for frees. They're very unlikely.
- // Increment top past the end of the block.
- _top++;
+ // need to allocate a next block.
+ if (b->_next == NULL) {
+ b->_next = _last_free = new JNIMethodBlockNode();
+ }
}
- // need to allocate a next block.
- if (_next == NULL) {
- _next = new JNIMethodBlock();
- }
- return _next->add_method(m);
+ guarantee(false, "Should always allocate a free block");
+ return NULL;
}
bool contains(Method** m) {
- for (JNIMethodBlock* b = this; b != NULL; b = b->_next) {
- for (int i = 0; i< number_of_methods; i++) {
- if (&(b->_methods[i]) == m) {
+ if (m == NULL) return false;
+ for (JNIMethodBlockNode* b = &_head; b != NULL; b = b->_next) {
+ if (b->_methods <= m && m < b->_methods + b->_number_of_methods) {
+ // This is a bit of extra checking, for two reasons. One is
+ // that contains() deals with pointers that are passed in by
+ // JNI code, so making sure that the pointer is aligned
+ // correctly is valuable. The other is that <= and > are
+ // technically not defined on pointers, so the if guard can
+ // pass spuriously; no modern compiler is likely to make that
+ // a problem, though (and if one did, the guard could also
+ // fail spuriously, which would be bad).
+ ptrdiff_t idx = m - b->_methods;
+ if (b->_methods + idx == m) {
return true;
}
}
@@ -1775,9 +1841,9 @@
// During class unloading the methods are cleared, which is different
// than freed.
void clear_all_methods() {
- for (JNIMethodBlock* b = this; b != NULL; b = b->_next) {
- for (int i = 0; i< number_of_methods; i++) {
- _methods[i] = NULL;
+ for (JNIMethodBlockNode* b = &_head; b != NULL; b = b->_next) {
+ for (int i = 0; i< b->_number_of_methods; i++) {
+ b->_methods[i] = NULL;
}
}
}
@@ -1785,9 +1851,9 @@
int count_methods() {
// count all allocated methods
int count = 0;
- for (JNIMethodBlock* b = this; b != NULL; b = b->_next) {
- for (int i = 0; i< number_of_methods; i++) {
- if (_methods[i] != _free_method) count++;
+ for (JNIMethodBlockNode* b = &_head; b != NULL; b = b->_next) {
+ for (int i = 0; i< b->_number_of_methods; i++) {
+ if (b->_methods[i] != _free_method) count++;
}
}
return count;
@@ -1798,6 +1864,36 @@
// Something that can't be mistaken for an address or a markOop
Method* const JNIMethodBlock::_free_method = (Method*)55;
+JNIMethodBlockNode::JNIMethodBlockNode(int num_methods) : _next(NULL), _top(0) {
+ _number_of_methods = MAX2(num_methods, min_block_size);
+ _methods = NEW_C_HEAP_ARRAY(Method*, _number_of_methods, mtInternal);
+ for (int i = 0; i < _number_of_methods; i++) {
+ _methods[i] = JNIMethodBlock::_free_method;
+ }
+}
+
+void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) {
+ ClassLoaderData* cld = loader_data;
+ if (!SafepointSynchronize::is_at_safepoint()) {
+ // Have to add jmethod_ids() to class loader data thread-safely.
+ // Also have to add the method to the list safely, which the cld lock
+ // protects as well.
+ MutexLockerEx ml(cld->metaspace_lock(), Mutex::_no_safepoint_check_flag);
+ if (cld->jmethod_ids() == NULL) {
+ cld->set_jmethod_ids(new JNIMethodBlock(capacity));
+ } else {
+ cld->jmethod_ids()->ensure_methods(capacity);
+ }
+ } else {
+ // At safepoint, we are single threaded and can set this.
+ if (cld->jmethod_ids() == NULL) {
+ cld->set_jmethod_ids(new JNIMethodBlock(capacity));
+ } else {
+ cld->jmethod_ids()->ensure_methods(capacity);
+ }
+ }
+}
+
// Add a method id to the jmethod_ids
jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) {
ClassLoaderData* cld = loader_data;
--- a/hotspot/src/share/vm/oops/method.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/method.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -729,6 +729,11 @@
static jmethodID make_jmethod_id(ClassLoaderData* loader_data, Method* mh);
static void destroy_jmethod_id(ClassLoaderData* loader_data, jmethodID mid);
+ // Ensure there is enough capacity in the internal tracking data
+ // structures to hold the number of jmethodIDs you plan to generate.
+ // This saves substantial time doing allocations.
+ static void ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity);
+
// Use resolve_jmethod_id() in situations where the caller is expected
// to provide a valid jmethodID; the only sanity checks are in asserts;
// result guaranteed not to be NULL.
@@ -813,6 +818,10 @@
return method_holder()->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
}
+ int mark_osr_nmethods() {
+ return method_holder()->mark_osr_nmethods(this);
+ }
+
nmethod* lookup_osr_nmethod_for(int bci, int level, bool match_level) {
return method_holder()->lookup_osr_nmethod(this, bci, level, match_level);
}
--- a/hotspot/src/share/vm/oops/objArrayOop.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/objArrayOop.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -45,9 +45,10 @@
private:
// Give size of objArrayOop in HeapWords minus the header
static int array_size(int length) {
- const int OopsPerHeapWord = HeapWordSize/heapOopSize;
+ const uint OopsPerHeapWord = HeapWordSize/heapOopSize;
assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0),
"Else the following (new) computation would be in error");
+ uint res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord;
#ifdef ASSERT
// The old code is left in for sanity-checking; it'll
// go away pretty soon. XXX
@@ -55,16 +56,15 @@
// oop->length() * HeapWordsPerOop;
// With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer.
// The oop elements are aligned up to wordSize
- const int HeapWordsPerOop = heapOopSize/HeapWordSize;
- int old_res;
+ const uint HeapWordsPerOop = heapOopSize/HeapWordSize;
+ uint old_res;
if (HeapWordsPerOop > 0) {
old_res = length * HeapWordsPerOop;
} else {
- old_res = align_size_up(length, OopsPerHeapWord)/OopsPerHeapWord;
+ old_res = align_size_up((uint)length, OopsPerHeapWord)/OopsPerHeapWord;
}
+ assert(res == old_res, "Inconsistency between old and new.");
#endif // ASSERT
- int res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord;
- assert(res == old_res, "Inconsistency between old and new.");
return res;
}
--- a/hotspot/src/share/vm/oops/typeArrayOop.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -150,7 +150,7 @@
DEBUG_ONLY(BasicType etype = Klass::layout_helper_element_type(lh));
assert(length <= arrayOopDesc::max_array_length(etype), "no overflow");
- julong size_in_bytes = length;
+ julong size_in_bytes = (juint)length;
size_in_bytes <<= element_shift;
size_in_bytes += instance_header_size;
julong size_in_words = ((size_in_bytes + (HeapWordSize-1)) >> LogHeapWordSize);
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -476,6 +476,9 @@
product(bool, DoEscapeAnalysis, true, \
"Perform escape analysis") \
\
+ product(double, EscapeAnalysisTimeout, 20. DEBUG_ONLY(+40.), \
+ "Abort EA when it reaches time limit (in sec)") \
+ \
develop(bool, ExitEscapeAnalysisOnTimeout, true, \
"Exit or throw assert in EA when it reaches time limit") \
\
--- a/hotspot/src/share/vm/opto/callnode.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/callnode.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -939,7 +939,8 @@
#ifndef PRODUCT
if (!(call->req() > TypeFunc::Parms &&
call->in(TypeFunc::Parms) != NULL &&
- call->in(TypeFunc::Parms)->is_Con())) {
+ call->in(TypeFunc::Parms)->is_Con() &&
+ call->in(TypeFunc::Parms)->bottom_type()->isa_int())) {
assert(in_dump() != 0, "OK if dumping");
tty->print("[bad uncommon trap]");
return 0;
--- a/hotspot/src/share/vm/opto/coalesce.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/coalesce.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -281,9 +281,11 @@
Block *pred = _phc._cfg.get_block_for_node(b->pred(j));
Node *copy;
assert(!m->is_Con() || m->is_Mach(), "all Con must be Mach");
- // Rematerialize constants instead of copying them
- if( m->is_Mach() && m->as_Mach()->is_Con() &&
- m->as_Mach()->rematerialize() ) {
+ // Rematerialize constants instead of copying them.
+ // We do this only for immediate constants, we avoid constant table loads
+ // because that will unsafely extend the live range of the constant table base.
+ if (m->is_Mach() && m->as_Mach()->is_Con() && !m->as_Mach()->is_MachConstant() &&
+ m->as_Mach()->rematerialize()) {
copy = m->clone();
// Insert the copy in the predecessor basic block
pred->add_inst(copy);
@@ -317,8 +319,8 @@
assert(!m->is_Con() || m->is_Mach(), "all Con must be Mach");
// At this point it is unsafe to extend live ranges (6550579).
// Rematerialize only constants as we do for Phi above.
- if(m->is_Mach() && m->as_Mach()->is_Con() &&
- m->as_Mach()->rematerialize()) {
+ if (m->is_Mach() && m->as_Mach()->is_Con() && !m->as_Mach()->is_MachConstant() &&
+ m->as_Mach()->rematerialize()) {
copy = m->clone();
// Insert the copy in the basic block, just before us
b->insert_node(copy, l++);
--- a/hotspot/src/share/vm/opto/compile.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/compile.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -535,7 +535,6 @@
if (scratch_buffer_blob() == NULL) {
// Let CompilerBroker disable further compilations.
record_failure("Not enough space for scratch buffer in CodeCache");
- CompileBroker::handle_full_code_cache(CodeBlobType::NonNMethod);
return;
}
}
--- a/hotspot/src/share/vm/opto/escape.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/escape.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -38,6 +38,8 @@
ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
_nodes(C->comp_arena(), C->unique(), C->unique(), NULL),
+ _in_worklist(C->comp_arena()),
+ _next_pidx(0),
_collecting(true),
_verify(false),
_compile(C),
@@ -125,13 +127,19 @@
if (C->root() != NULL) {
ideal_nodes.push(C->root());
}
+ // Processed ideal nodes are unique on ideal_nodes list
+ // but several ideal nodes are mapped to the phantom_obj.
+ // To avoid duplicated entries on the following worklists
+ // add the phantom_obj only once to them.
+ ptnodes_worklist.append(phantom_obj);
+ java_objects_worklist.append(phantom_obj);
for( uint next = 0; next < ideal_nodes.size(); ++next ) {
Node* n = ideal_nodes.at(next);
// Create PointsTo nodes and add them to Connection Graph. Called
// only once per ideal node since ideal_nodes is Unique_Node list.
add_node_to_connection_graph(n, &delayed_worklist);
PointsToNode* ptn = ptnode_adr(n->_idx);
- if (ptn != NULL) {
+ if (ptn != NULL && ptn != phantom_obj) {
ptnodes_worklist.append(ptn);
if (ptn->is_JavaObject()) {
java_objects_worklist.append(ptn->as_JavaObject());
@@ -415,7 +423,7 @@
}
case Op_CreateEx: {
// assume that all exception objects globally escape
- add_java_object(n, PointsToNode::GlobalEscape);
+ map_ideal_node(n, phantom_obj);
break;
}
case Op_LoadKlass:
@@ -1074,13 +1082,8 @@
// on graph complexity. Observed 8 passes in jvm2008 compiler.compiler.
// Set limit to 20 to catch situation when something did go wrong and
// bailout Escape Analysis.
- // Also limit build time to 30 sec (60 in debug VM).
+ // Also limit build time to 20 sec (60 in debug VM), EscapeAnalysisTimeout flag.
#define CG_BUILD_ITER_LIMIT 20
-#ifdef ASSERT
-#define CG_BUILD_TIME_LIMIT 60.0
-#else
-#define CG_BUILD_TIME_LIMIT 30.0
-#endif
// Propagate GlobalEscape and ArgEscape escape states and check that
// we still have non-escaping objects. The method pushs on _worklist
@@ -1091,12 +1094,13 @@
// Now propagate references to all JavaObject nodes.
int java_objects_length = java_objects_worklist.length();
elapsedTimer time;
+ bool timeout = false;
int new_edges = 1;
int iterations = 0;
do {
while ((new_edges > 0) &&
- (iterations++ < CG_BUILD_ITER_LIMIT) &&
- (time.seconds() < CG_BUILD_TIME_LIMIT)) {
+ (iterations++ < CG_BUILD_ITER_LIMIT)) {
+ double start_time = time.seconds();
time.start();
new_edges = 0;
// Propagate references to phantom_object for nodes pushed on _worklist
@@ -1105,7 +1109,26 @@
for (int next = 0; next < java_objects_length; ++next) {
JavaObjectNode* ptn = java_objects_worklist.at(next);
new_edges += add_java_object_edges(ptn, true);
+
+#define SAMPLE_SIZE 4
+ if ((next % SAMPLE_SIZE) == 0) {
+ // Each 4 iterations calculate how much time it will take
+ // to complete graph construction.
+ time.stop();
+ double stop_time = time.seconds();
+ double time_per_iter = (stop_time - start_time) / (double)SAMPLE_SIZE;
+ double time_until_end = time_per_iter * (double)(java_objects_length - next);
+ if ((start_time + time_until_end) >= EscapeAnalysisTimeout) {
+ timeout = true;
+ break; // Timeout
+ }
+ start_time = stop_time;
+ time.start();
+ }
+#undef SAMPLE_SIZE
+
}
+ if (timeout) break;
if (new_edges > 0) {
// Update escape states on each iteration if graph was updated.
if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
@@ -1113,9 +1136,12 @@
}
}
time.stop();
+ if (time.seconds() >= EscapeAnalysisTimeout) {
+ timeout = true;
+ break;
+ }
}
- if ((iterations < CG_BUILD_ITER_LIMIT) &&
- (time.seconds() < CG_BUILD_TIME_LIMIT)) {
+ if ((iterations < CG_BUILD_ITER_LIMIT) && !timeout) {
time.start();
// Find fields which have unknown value.
int fields_length = oop_fields_worklist.length();
@@ -1128,18 +1154,21 @@
}
}
time.stop();
+ if (time.seconds() >= EscapeAnalysisTimeout) {
+ timeout = true;
+ break;
+ }
} else {
new_edges = 0; // Bailout
}
} while (new_edges > 0);
// Bailout if passed limits.
- if ((iterations >= CG_BUILD_ITER_LIMIT) ||
- (time.seconds() >= CG_BUILD_TIME_LIMIT)) {
+ if ((iterations >= CG_BUILD_ITER_LIMIT) || timeout) {
Compile* C = _compile;
if (C->log() != NULL) {
C->log()->begin_elem("connectionGraph_bailout reason='reached ");
- C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time");
+ C->log()->text("%s", timeout ? "time" : "iterations");
C->log()->end_elem(" limit'");
}
assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
@@ -1156,7 +1185,6 @@
#endif
#undef CG_BUILD_ITER_LIMIT
-#undef CG_BUILD_TIME_LIMIT
// Find fields initialized by NULL for non-escaping Allocations.
int non_escaped_length = non_escaped_worklist.length();
@@ -1280,8 +1308,8 @@
}
}
}
- while(_worklist.length() > 0) {
- PointsToNode* use = _worklist.pop();
+ for (int l = 0; l < _worklist.length(); l++) {
+ PointsToNode* use = _worklist.at(l);
if (PointsToNode::is_base_use(use)) {
// Add reference from jobj to field and from field to jobj (field's base).
use = PointsToNode::get_use_node(use)->as_Field();
@@ -1328,6 +1356,8 @@
add_field_uses_to_worklist(use->as_Field());
}
}
+ _worklist.clear();
+ _in_worklist.Reset();
return new_edges;
}
@@ -1906,7 +1936,7 @@
return;
}
Compile* C = _compile;
- ptadr = new (C->comp_arena()) LocalVarNode(C, n, es);
+ ptadr = new (C->comp_arena()) LocalVarNode(this, n, es);
_nodes.at_put(n->_idx, ptadr);
}
@@ -1917,7 +1947,7 @@
return;
}
Compile* C = _compile;
- ptadr = new (C->comp_arena()) JavaObjectNode(C, n, es);
+ ptadr = new (C->comp_arena()) JavaObjectNode(this, n, es);
_nodes.at_put(n->_idx, ptadr);
}
@@ -1933,7 +1963,7 @@
es = PointsToNode::GlobalEscape;
}
Compile* C = _compile;
- FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop);
+ FieldNode* field = new (C->comp_arena()) FieldNode(this, n, es, offset, is_oop);
_nodes.at_put(n->_idx, field);
}
@@ -1947,7 +1977,7 @@
return;
}
Compile* C = _compile;
- ptadr = new (C->comp_arena()) ArraycopyNode(C, n, es);
+ ptadr = new (C->comp_arena()) ArraycopyNode(this, n, es);
_nodes.at_put(n->_idx, ptadr);
// Add edge from arraycopy node to source object.
(void)add_edge(ptadr, src);
--- a/hotspot/src/share/vm/opto/escape.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/escape.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -125,6 +125,8 @@
class FieldNode;
class ArraycopyNode;
+class ConnectionGraph;
+
// ConnectionGraph nodes
class PointsToNode : public ResourceObj {
GrowableArray<PointsToNode*> _edges; // List of nodes this node points to
@@ -137,6 +139,7 @@
Node* const _node; // Ideal node corresponding to this PointsTo node.
const int _idx; // Cached ideal node's _idx
+ const uint _pidx; // Index of this node
public:
typedef enum {
@@ -165,17 +168,9 @@
} NodeFlags;
- PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type):
- _edges(C->comp_arena(), 2, 0, NULL),
- _uses (C->comp_arena(), 2, 0, NULL),
- _node(n),
- _idx(n->_idx),
- _type((u1)type),
- _escape((u1)es),
- _fields_escape((u1)es),
- _flags(ScalarReplaceable) {
- assert(n != NULL && es != UnknownEscape, "sanity");
- }
+ inline PointsToNode(ConnectionGraph* CG, Node* n, EscapeState es, NodeType type);
+
+ uint pidx() const { return _pidx; }
Node* ideal_node() const { return _node; }
int idx() const { return _idx; }
@@ -243,14 +238,14 @@
class LocalVarNode: public PointsToNode {
public:
- LocalVarNode(Compile *C, Node* n, EscapeState es):
- PointsToNode(C, n, es, LocalVar) {}
+ LocalVarNode(ConnectionGraph *CG, Node* n, EscapeState es):
+ PointsToNode(CG, n, es, LocalVar) {}
};
class JavaObjectNode: public PointsToNode {
public:
- JavaObjectNode(Compile *C, Node* n, EscapeState es):
- PointsToNode(C, n, es, JavaObject) {
+ JavaObjectNode(ConnectionGraph *CG, Node* n, EscapeState es):
+ PointsToNode(CG, n, es, JavaObject) {
if (es > NoEscape)
set_scalar_replaceable(false);
}
@@ -262,8 +257,8 @@
const bool _is_oop; // Field points to object
bool _has_unknown_base; // Has phantom_object base
public:
- FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop):
- PointsToNode(C, n, es, Field),
+ FieldNode(ConnectionGraph *CG, Node* n, EscapeState es, int offs, bool is_oop):
+ PointsToNode(CG, n, es, Field),
_offset(offs), _is_oop(is_oop),
_has_unknown_base(false) {}
@@ -284,8 +279,8 @@
class ArraycopyNode: public PointsToNode {
public:
- ArraycopyNode(Compile *C, Node* n, EscapeState es):
- PointsToNode(C, n, es, Arraycopy) {}
+ ArraycopyNode(ConnectionGraph *CG, Node* n, EscapeState es):
+ PointsToNode(CG, n, es, Arraycopy) {}
};
// Iterators for PointsTo node's edges:
@@ -323,11 +318,14 @@
class ConnectionGraph: public ResourceObj {
+ friend class PointsToNode;
private:
GrowableArray<PointsToNode*> _nodes; // Map from ideal nodes to
// ConnectionGraph nodes.
GrowableArray<PointsToNode*> _worklist; // Nodes to be processed
+ VectorSet _in_worklist;
+ uint _next_pidx;
bool _collecting; // Indicates whether escape information
// is still being collected. If false,
@@ -353,6 +351,8 @@
}
uint nodes_size() const { return _nodes.length(); }
+ uint next_pidx() { return _next_pidx++; }
+
// Add nodes to ConnectionGraph.
void add_local_var(Node* n, PointsToNode::EscapeState es);
void add_java_object(Node* n, PointsToNode::EscapeState es);
@@ -396,15 +396,26 @@
int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist);
// Put node on worklist if it is (or was) not there.
- void add_to_worklist(PointsToNode* pt) {
- _worklist.push(pt);
- return;
+ inline void add_to_worklist(PointsToNode* pt) {
+ PointsToNode* ptf = pt;
+ uint pidx_bias = 0;
+ if (PointsToNode::is_base_use(pt)) {
+ // Create a separate entry in _in_worklist for a marked base edge
+ // because _worklist may have an entry for a normal edge pointing
+ // to the same node. To separate them use _next_pidx as bias.
+ ptf = PointsToNode::get_use_node(pt)->as_Field();
+ pidx_bias = _next_pidx;
+ }
+ if (!_in_worklist.test_set(ptf->pidx() + pidx_bias)) {
+ _worklist.append(pt);
+ }
}
// Put on worklist all uses of this node.
- void add_uses_to_worklist(PointsToNode* pt) {
- for (UseIterator i(pt); i.has_next(); i.next())
- _worklist.push(i.get());
+ inline void add_uses_to_worklist(PointsToNode* pt) {
+ for (UseIterator i(pt); i.has_next(); i.next()) {
+ add_to_worklist(i.get());
+ }
}
// Put on worklist all field's uses and related field nodes.
@@ -517,8 +528,8 @@
}
// Helper functions
bool is_oop_field(Node* n, int offset, bool* unsafe);
- static Node* get_addp_base(Node *addp);
- static Node* find_second_addp(Node* addp, Node* n);
+ static Node* get_addp_base(Node *addp);
+ static Node* find_second_addp(Node* addp, Node* n);
// offset of a field reference
int address_offset(Node* adr, PhaseTransform *phase);
@@ -587,4 +598,17 @@
#endif
};
+inline PointsToNode::PointsToNode(ConnectionGraph *CG, Node* n, EscapeState es, NodeType type):
+ _edges(CG->_compile->comp_arena(), 2, 0, NULL),
+ _uses (CG->_compile->comp_arena(), 2, 0, NULL),
+ _node(n),
+ _idx(n->_idx),
+ _pidx(CG->next_pidx()),
+ _type((u1)type),
+ _escape((u1)es),
+ _fields_escape((u1)es),
+ _flags(ScalarReplaceable) {
+ assert(n != NULL && es != UnknownEscape, "sanity");
+}
+
#endif // SHARE_VM_OPTO_ESCAPE_HPP
--- a/hotspot/src/share/vm/opto/lcm.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/lcm.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -464,9 +464,7 @@
iop == Op_CreateEx || // Create-exception must start block
iop == Op_CheckCastPP
) {
- // select the node n
- // remove n from worklist and retain the order of remaining nodes
- worklist.remove((uint)i);
+ worklist.map(i,worklist.pop());
return n;
}
@@ -552,9 +550,7 @@
assert(idx >= 0, "index should be set");
Node *n = worklist[(uint)idx]; // Get the winner
- // select the node n
- // remove n from worklist and retain the order of remaining nodes
- worklist.remove((uint)idx);
+ worklist.map((uint)idx, worklist.pop()); // Compress worklist
return n;
}
--- a/hotspot/src/share/vm/opto/library_call.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/library_call.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -268,6 +268,7 @@
bool inline_fp_conversions(vmIntrinsics::ID id);
bool inline_number_methods(vmIntrinsics::ID id);
bool inline_reference_get();
+ bool inline_Class_cast();
bool inline_aescrypt_Block(vmIntrinsics::ID id);
bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id);
Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
@@ -869,6 +870,8 @@
case vmIntrinsics::_Reference_get: return inline_reference_get();
+ case vmIntrinsics::_Class_cast: return inline_Class_cast();
+
case vmIntrinsics::_aescrypt_encryptBlock:
case vmIntrinsics::_aescrypt_decryptBlock: return inline_aescrypt_Block(intrinsic_id());
@@ -3546,6 +3549,89 @@
return true;
}
+//-------------------------inline_Class_cast-------------------
+bool LibraryCallKit::inline_Class_cast() {
+ Node* mirror = argument(0); // Class
+ Node* obj = argument(1);
+ const TypeInstPtr* mirror_con = _gvn.type(mirror)->isa_instptr();
+ if (mirror_con == NULL) {
+ return false; // dead path (mirror->is_top()).
+ }
+ if (obj == NULL || obj->is_top()) {
+ return false; // dead path
+ }
+ const TypeOopPtr* tp = _gvn.type(obj)->isa_oopptr();
+
+ // First, see if Class.cast() can be folded statically.
+ // java_mirror_type() returns non-null for compile-time Class constants.
+ ciType* tm = mirror_con->java_mirror_type();
+ if (tm != NULL && tm->is_klass() &&
+ tp != NULL && tp->klass() != NULL) {
+ if (!tp->klass()->is_loaded()) {
+ // Don't use intrinsic when class is not loaded.
+ return false;
+ } else {
+ int static_res = C->static_subtype_check(tm->as_klass(), tp->klass());
+ if (static_res == Compile::SSC_always_true) {
+ // isInstance() is true - fold the code.
+ set_result(obj);
+ return true;
+ } else if (static_res == Compile::SSC_always_false) {
+ // Don't use intrinsic, have to throw ClassCastException.
+ // If the reference is null, the non-intrinsic bytecode will
+ // be optimized appropriately.
+ return false;
+ }
+ }
+ }
+
+ // Bailout intrinsic and do normal inlining if exception path is frequent.
+ if (too_many_traps(Deoptimization::Reason_intrinsic)) {
+ return false;
+ }
+
+ // Generate dynamic checks.
+ // Class.cast() is java implementation of _checkcast bytecode.
+ // Do checkcast (Parse::do_checkcast()) optimizations here.
+
+ mirror = null_check(mirror);
+ // If mirror is dead, only null-path is taken.
+ if (stopped()) {
+ return true;
+ }
+
+ // Not-subtype or the mirror's klass ptr is NULL (in case it is a primitive).
+ enum { _bad_type_path = 1, _prim_path = 2, PATH_LIMIT };
+ RegionNode* region = new RegionNode(PATH_LIMIT);
+ record_for_igvn(region);
+
+ // Now load the mirror's klass metaobject, and null-check it.
+ // If kls is null, we have a primitive mirror and
+ // nothing is an instance of a primitive type.
+ Node* kls = load_klass_from_mirror(mirror, false, region, _prim_path);
+
+ Node* res = top();
+ if (!stopped()) {
+ Node* bad_type_ctrl = top();
+ // Do checkcast optimizations.
+ res = gen_checkcast(obj, kls, &bad_type_ctrl);
+ region->init_req(_bad_type_path, bad_type_ctrl);
+ }
+ if (region->in(_prim_path) != top() ||
+ region->in(_bad_type_path) != top()) {
+ // Let Interpreter throw ClassCastException.
+ PreserveJVMState pjvms(this);
+ set_control(_gvn.transform(region));
+ uncommon_trap(Deoptimization::Reason_intrinsic,
+ Deoptimization::Action_maybe_recompile);
+ }
+ if (!stopped()) {
+ set_result(res);
+ }
+ return true;
+}
+
+
//--------------------------inline_native_subtype_check------------------------
// This intrinsic takes the JNI calls out of the heart of
// UnsafeFieldAccessorImpl.set, which improves Field.set, readObject, etc.
@@ -4611,6 +4697,10 @@
Node* dest_offset = argument(3); // type: int
Node* length = argument(4); // type: int
+ // Check for allocation before we add nodes that would confuse
+ // tightly_coupled_allocation()
+ AllocateArrayNode* alloc = tightly_coupled_allocation(dest, NULL);
+
// The following tests must be performed
// (1) src and dest are arrays.
// (2) src and dest arrays must have elements of the same BasicType
@@ -4784,7 +4874,6 @@
return true;
}
- AllocateArrayNode* alloc = tightly_coupled_allocation(dest, NULL);
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, src, src_offset, dest, dest_offset, length, alloc != NULL,
// Create LoadRange and LoadKlass nodes for use during macro expansion here
// so the compiler has a chance to eliminate them: during macro expansion,
--- a/hotspot/src/share/vm/opto/memnode.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/memnode.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1257,6 +1257,16 @@
result = new ConvI2LNode(phase->transform(result));
}
#endif
+ // Boxing/unboxing can be done from signed & unsigned loads (e.g. LoadUB -> ... -> LoadB pair).
+ // Need to preserve unboxing load type if it is unsigned.
+ switch(this->Opcode()) {
+ case Op_LoadUB:
+ result = new AndINode(phase->transform(result), phase->intcon(0xFF));
+ break;
+ case Op_LoadUS:
+ result = new AndINode(phase->transform(result), phase->intcon(0xFFFF));
+ break;
+ }
return result;
}
}
--- a/hotspot/src/share/vm/opto/mulnode.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/mulnode.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -610,7 +610,7 @@
// convert masks which would cause a sign extension of the integer
// value. This check includes UI2L masks (0x00000000FFFFFFFF) which
// would be optimized away later in Identity.
- if (op == Op_ConvI2L && (mask & CONST64(0xFFFFFFFF80000000)) == 0) {
+ if (op == Op_ConvI2L && (mask & UCONST64(0xFFFFFFFF80000000)) == 0) {
Node* andi = new AndINode(in1->in(1), phase->intcon(mask));
andi = phase->transform(andi);
return new ConvI2LNode(andi);
--- a/hotspot/src/share/vm/opto/output.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/opto/output.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1166,7 +1166,6 @@
// Have we run out of code space?
if ((cb->blob() == NULL) || (!CompileBroker::should_compile_new_jobs())) {
C->record_failure("CodeCache is full");
- CompileBroker::handle_full_code_cache(CodeBlobType::NonNMethod);
return NULL;
}
// Configure the code buffer.
@@ -1491,7 +1490,6 @@
cb->insts()->maybe_expand_to_ensure_remaining(MAX_inst_size);
if ((cb->blob() == NULL) || (!CompileBroker::should_compile_new_jobs())) {
C->record_failure("CodeCache is full");
- CompileBroker::handle_full_code_cache(CodeBlobType::NonNMethod);
return;
}
@@ -1648,7 +1646,6 @@
// One last check for failed CodeBuffer::expand:
if ((cb->blob() == NULL) || (!CompileBroker::should_compile_new_jobs())) {
C->record_failure("CodeCache is full");
- CompileBroker::handle_full_code_cache(CodeBlobType::NonNMethod);
return;
}
--- a/hotspot/src/share/vm/prims/jni.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/jni.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -951,8 +951,9 @@
// Optimized path if we have the bitvector form of signature
void iterate( uint64_t fingerprint ) {
- if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate();// Must be too many arguments
- else {
+ if (fingerprint == (uint64_t)CONST64(-1)) {
+ SignatureIterator::iterate(); // Must be too many arguments
+ } else {
_return_type = (BasicType)((fingerprint >> static_feature_size) &
result_feature_mask);
@@ -1022,8 +1023,9 @@
// Optimized path if we have the bitvector form of signature
void iterate( uint64_t fingerprint ) {
- if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate(); // Must be too many arguments
- else {
+ if (fingerprint == (uint64_t)CONST64(-1)) {
+ SignatureIterator::iterate(); // Must be too many arguments
+ } else {
_return_type = (BasicType)((fingerprint >> static_feature_size) &
result_feature_mask);
assert(fingerprint, "Fingerprint should not be 0");
--- a/hotspot/src/share/vm/prims/jvm.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/jvm.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -2583,7 +2583,14 @@
int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) {
// see bug 4399518, 4417214
if ((intptr_t)count <= 0) return -1;
- return vsnprintf(str, count, fmt, args);
+
+ int result = vsnprintf(str, count, fmt, args);
+ if ((result > 0 && (size_t)result >= count) || result == -1) {
+ str[count - 1] = '\0';
+ result = -1;
+ }
+
+ return result;
}
ATTRIBUTE_PRINTF(3, 0)
@@ -3271,8 +3278,10 @@
THROW_0(vmSymbols::java_lang_NullPointerException());
}
oop a = JNIHandles::resolve_non_null(arr);
- if (!a->is_array() || (type_array_only && !a->is_typeArray())) {
+ if (!a->is_array()) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array");
+ } else if (type_array_only && !a->is_typeArray()) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array of primitive type");
}
return arrayOop(a);
}
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -41,6 +41,7 @@
void JvmtiClassFileReconstituter::write_field_infos() {
HandleMark hm(thread());
Array<AnnotationArray*>* fields_anno = ikh()->fields_annotations();
+ Array<AnnotationArray*>* fields_type_anno = ikh()->fields_type_annotations();
// Compute the real number of Java fields
int java_fields = ikh()->java_fields_count();
@@ -55,6 +56,7 @@
// int offset = ikh()->field_offset( index );
int generic_signature_index = fs.generic_signature_index();
AnnotationArray* anno = fields_anno == NULL ? NULL : fields_anno->at(fs.index());
+ AnnotationArray* type_anno = fields_type_anno == NULL ? NULL : fields_type_anno->at(fs.index());
// JVMSpec| field_info {
// JVMSpec| u2 access_flags;
@@ -80,6 +82,9 @@
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
+ if (type_anno != NULL) {
+ ++attr_count; // has RuntimeVisibleTypeAnnotations attribute
+ }
write_u2(attr_count);
@@ -97,6 +102,9 @@
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
+ if (type_anno != NULL) {
+ write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);
+ }
}
}
@@ -537,6 +545,7 @@
AnnotationArray* anno = method->annotations();
AnnotationArray* param_anno = method->parameter_annotations();
AnnotationArray* default_anno = method->annotation_default();
+ AnnotationArray* type_anno = method->type_annotations();
// skip generated default interface methods
if (method->is_overpass()) {
@@ -572,6 +581,9 @@
if (param_anno != NULL) {
++attr_count; // has RuntimeVisibleParameterAnnotations attribute
}
+ if (type_anno != NULL) {
+ ++attr_count; // has RuntimeVisibleTypeAnnotations attribute
+ }
write_u2(attr_count);
if (const_method->code_size() > 0) {
@@ -596,6 +608,9 @@
if (param_anno != NULL) {
write_annotations_attribute("RuntimeVisibleParameterAnnotations", param_anno);
}
+ if (type_anno != NULL) {
+ write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);
+ }
}
// Write the class attributes portion of ClassFile structure
@@ -605,6 +620,7 @@
u2 inner_classes_length = inner_classes_attribute_length();
Symbol* generic_signature = ikh()->generic_signature();
AnnotationArray* anno = ikh()->class_annotations();
+ AnnotationArray* type_anno = ikh()->class_type_annotations();
int attr_count = 0;
if (generic_signature != NULL) {
@@ -622,6 +638,9 @@
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
+ if (type_anno != NULL) {
+ ++attr_count; // has RuntimeVisibleTypeAnnotations attribute
+ }
if (cpool()->operands() != NULL) {
++attr_count;
}
@@ -643,6 +662,9 @@
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
+ if (type_anno != NULL) {
+ write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);
+ }
if (cpool()->operands() != NULL) {
write_bootstrapmethod_attribute();
}
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -2263,6 +2263,8 @@
int result_length = instanceK_h->methods()->length();
jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID));
int index;
+ bool jmethodids_found = true;
+
if (JvmtiExport::can_maintain_original_method_order()) {
// Use the original method ordering indices stored in the class, so we can emit
// jmethodIDs in the order they appeared in the class file
@@ -2270,14 +2272,40 @@
Method* m = instanceK_h->methods()->at(index);
int original_index = instanceK_h->method_ordering()->at(index);
assert(original_index >= 0 && original_index < result_length, "invalid original method index");
- jmethodID id = m->jmethod_id();
+ jmethodID id;
+ if (jmethodids_found) {
+ id = m->find_jmethod_id_or_null();
+ if (id == NULL) {
+ // If we find an uninitialized value, make sure there is
+ // enough space for all the uninitialized values we might
+ // find.
+ instanceK_h->ensure_space_for_methodids(index);
+ jmethodids_found = false;
+ id = m->jmethod_id();
+ }
+ } else {
+ id = m->jmethod_id();
+ }
result_list[original_index] = id;
}
} else {
// otherwise just copy in any order
for (index = 0; index < result_length; index++) {
Method* m = instanceK_h->methods()->at(index);
- jmethodID id = m->jmethod_id();
+ jmethodID id;
+ if (jmethodids_found) {
+ id = m->find_jmethod_id_or_null();
+ if (id == NULL) {
+ // If we find an uninitialized value, make sure there is
+ // enough space for all the uninitialized values we might
+ // find.
+ instanceK_h->ensure_space_for_methodids(index);
+ jmethodids_found = false;
+ id = m->jmethod_id();
+ }
+ } else {
+ id = m->jmethod_id();
+ }
result_list[index] = id;
}
}
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1569,6 +1569,29 @@
return false;
}
+ // rewrite constant pool references in the class_type_annotations:
+ if (!rewrite_cp_refs_in_class_type_annotations(scratch_class, THREAD)) {
+ // propagate failure back to caller
+ return false;
+ }
+
+ // rewrite constant pool references in the fields_type_annotations:
+ if (!rewrite_cp_refs_in_fields_type_annotations(scratch_class, THREAD)) {
+ // propagate failure back to caller
+ return false;
+ }
+
+ // rewrite constant pool references in the methods_type_annotations:
+ if (!rewrite_cp_refs_in_methods_type_annotations(scratch_class, THREAD)) {
+ // propagate failure back to caller
+ return false;
+ }
+
+ // There can be type annotations in the Code part of a method_info attribute.
+ // These annotations are not accessible, even by reflection.
+ // Currently they are not even parsed by the ClassFileParser.
+ // If runtime access is added they will also need to be rewritten.
+
// rewrite source file name index:
u2 source_file_name_idx = scratch_class->source_file_name_index();
if (source_file_name_idx != 0) {
@@ -2239,6 +2262,588 @@
} // end rewrite_cp_refs_in_methods_default_annotations()
+// Rewrite constant pool references in a class_type_annotations field.
+bool VM_RedefineClasses::rewrite_cp_refs_in_class_type_annotations(
+ instanceKlassHandle scratch_class, TRAPS) {
+
+ AnnotationArray* class_type_annotations = scratch_class->class_type_annotations();
+ if (class_type_annotations == NULL || class_type_annotations->length() == 0) {
+ // no class_type_annotations so nothing to do
+ return true;
+ }
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("class_type_annotations length=%d", class_type_annotations->length()));
+
+ int byte_i = 0; // byte index into class_type_annotations
+ return rewrite_cp_refs_in_type_annotations_typeArray(class_type_annotations,
+ byte_i, "ClassFile", THREAD);
+} // end rewrite_cp_refs_in_class_type_annotations()
+
+
+// Rewrite constant pool references in a fields_type_annotations field.
+bool VM_RedefineClasses::rewrite_cp_refs_in_fields_type_annotations(
+ instanceKlassHandle scratch_class, TRAPS) {
+
+ Array<AnnotationArray*>* fields_type_annotations = scratch_class->fields_type_annotations();
+ if (fields_type_annotations == NULL || fields_type_annotations->length() == 0) {
+ // no fields_type_annotations so nothing to do
+ return true;
+ }
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("fields_type_annotations length=%d", fields_type_annotations->length()));
+
+ for (int i = 0; i < fields_type_annotations->length(); i++) {
+ AnnotationArray* field_type_annotations = fields_type_annotations->at(i);
+ if (field_type_annotations == NULL || field_type_annotations->length() == 0) {
+ // this field does not have any annotations so skip it
+ continue;
+ }
+
+ int byte_i = 0; // byte index into field_type_annotations
+ if (!rewrite_cp_refs_in_type_annotations_typeArray(field_type_annotations,
+ byte_i, "field_info", THREAD)) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("bad field_type_annotations at %d", i));
+ // propagate failure back to caller
+ return false;
+ }
+ }
+
+ return true;
+} // end rewrite_cp_refs_in_fields_type_annotations()
+
+
+// Rewrite constant pool references in a methods_type_annotations field.
+bool VM_RedefineClasses::rewrite_cp_refs_in_methods_type_annotations(
+ instanceKlassHandle scratch_class, TRAPS) {
+
+ for (int i = 0; i < scratch_class->methods()->length(); i++) {
+ Method* m = scratch_class->methods()->at(i);
+ AnnotationArray* method_type_annotations = m->constMethod()->type_annotations();
+
+ if (method_type_annotations == NULL || method_type_annotations->length() == 0) {
+ // this method does not have any annotations so skip it
+ continue;
+ }
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("methods type_annotations length=%d", method_type_annotations->length()));
+
+ int byte_i = 0; // byte index into method_type_annotations
+ if (!rewrite_cp_refs_in_type_annotations_typeArray(method_type_annotations,
+ byte_i, "method_info", THREAD)) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("bad method_type_annotations at %d", i));
+ // propagate failure back to caller
+ return false;
+ }
+ }
+
+ return true;
+} // end rewrite_cp_refs_in_methods_type_annotations()
+
+
+// Rewrite constant pool references in a type_annotations
+// field. This "structure" is adapted from the
+// RuntimeVisibleTypeAnnotations_attribute described in
+// section 4.7.20 of the Java SE 8 Edition of the VM spec:
+//
+// type_annotations_typeArray {
+// u2 num_annotations;
+// type_annotation annotations[num_annotations];
+// }
+//
+bool VM_RedefineClasses::rewrite_cp_refs_in_type_annotations_typeArray(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref,
+ const char * location_mesg, TRAPS) {
+
+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) {
+ // not enough room for num_annotations field
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for num_annotations field"));
+ return false;
+ }
+
+ u2 num_annotations = Bytes::get_Java_u2((address)
+ type_annotations_typeArray->adr_at(byte_i_ref));
+ byte_i_ref += 2;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("num_type_annotations=%d", num_annotations));
+
+ int calc_num_annotations = 0;
+ for (; calc_num_annotations < num_annotations; calc_num_annotations++) {
+ if (!rewrite_cp_refs_in_type_annotation_struct(type_annotations_typeArray,
+ byte_i_ref, location_mesg, THREAD)) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("bad type_annotation_struct at %d", calc_num_annotations));
+ // propagate failure back to caller
+ return false;
+ }
+ }
+ assert(num_annotations == calc_num_annotations, "sanity check");
+
+ if (byte_i_ref != type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("read wrong amount of bytes at end of processing "
+ "type_annotations_typeArray (%d of %d bytes were read)",
+ byte_i_ref, type_annotations_typeArray->length()));
+ return false;
+ }
+
+ return true;
+} // end rewrite_cp_refs_in_type_annotations_typeArray()
+
+
+// Rewrite constant pool references in a type_annotation
+// field. This "structure" is adapted from the
+// RuntimeVisibleTypeAnnotations_attribute described in
+// section 4.7.20 of the Java SE 8 Edition of the VM spec:
+//
+// type_annotation {
+// u1 target_type;
+// union {
+// type_parameter_target;
+// supertype_target;
+// type_parameter_bound_target;
+// empty_target;
+// method_formal_parameter_target;
+// throws_target;
+// localvar_target;
+// catch_target;
+// offset_target;
+// type_argument_target;
+// } target_info;
+// type_path target_path;
+// annotation anno;
+// }
+//
+bool VM_RedefineClasses::rewrite_cp_refs_in_type_annotation_struct(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref,
+ const char * location_mesg, TRAPS) {
+
+ if (!skip_type_annotation_target(type_annotations_typeArray,
+ byte_i_ref, location_mesg, THREAD)) {
+ return false;
+ }
+
+ if (!skip_type_annotation_type_path(type_annotations_typeArray,
+ byte_i_ref, THREAD)) {
+ return false;
+ }
+
+ if (!rewrite_cp_refs_in_annotation_struct(type_annotations_typeArray,
+ byte_i_ref, THREAD)) {
+ return false;
+ }
+
+ return true;
+} // end rewrite_cp_refs_in_type_annotation_struct()
+
+
+// Read, verify and skip over the target_type and target_info part
+// so that rewriting can continue in the later parts of the struct.
+//
+// u1 target_type;
+// union {
+// type_parameter_target;
+// supertype_target;
+// type_parameter_bound_target;
+// empty_target;
+// method_formal_parameter_target;
+// throws_target;
+// localvar_target;
+// catch_target;
+// offset_target;
+// type_argument_target;
+// } target_info;
+//
+bool VM_RedefineClasses::skip_type_annotation_target(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref,
+ const char * location_mesg, TRAPS) {
+
+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) {
+ // not enough room for a target_type let alone the rest of a type_annotation
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a target_type"));
+ return false;
+ }
+
+ u1 target_type = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("target_type=0x%.2x", target_type));
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("location=%s", location_mesg));
+
+ // Skip over target_info
+ switch (target_type) {
+ case 0x00:
+ // kind: type parameter declaration of generic class or interface
+ // location: ClassFile
+ case 0x01:
+ // kind: type parameter declaration of generic method or constructor
+ // location: method_info
+
+ {
+ // struct:
+ // type_parameter_target {
+ // u1 type_parameter_index;
+ // }
+ //
+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a type_parameter_target"));
+ return false;
+ }
+
+ u1 type_parameter_index = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("type_parameter_target: type_parameter_index=%d",
+ type_parameter_index));
+ } break;
+
+ case 0x10:
+ // kind: type in extends clause of class or interface declaration
+ // (including the direct superclass of an anonymous class declaration),
+ // or in implements clause of interface declaration
+ // location: ClassFile
+
+ {
+ // struct:
+ // supertype_target {
+ // u2 supertype_index;
+ // }
+ //
+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a supertype_target"));
+ return false;
+ }
+
+ u2 supertype_index = Bytes::get_Java_u2((address)
+ type_annotations_typeArray->adr_at(byte_i_ref));
+ byte_i_ref += 2;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("supertype_target: supertype_index=%d", supertype_index));
+ } break;
+
+ case 0x11:
+ // kind: type in bound of type parameter declaration of generic class or interface
+ // location: ClassFile
+ case 0x12:
+ // kind: type in bound of type parameter declaration of generic method or constructor
+ // location: method_info
+
+ {
+ // struct:
+ // type_parameter_bound_target {
+ // u1 type_parameter_index;
+ // u1 bound_index;
+ // }
+ //
+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a type_parameter_bound_target"));
+ return false;
+ }
+
+ u1 type_parameter_index = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+ u1 bound_index = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("type_parameter_bound_target: type_parameter_index=%d, bound_index=%d",
+ type_parameter_index, bound_index));
+ } break;
+
+ case 0x13:
+ // kind: type in field declaration
+ // location: field_info
+ case 0x14:
+ // kind: return type of method, or type of newly constructed object
+ // location: method_info
+ case 0x15:
+ // kind: receiver type of method or constructor
+ // location: method_info
+
+ {
+ // struct:
+ // empty_target {
+ // }
+ //
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("empty_target"));
+ } break;
+
+ case 0x16:
+ // kind: type in formal parameter declaration of method, constructor, or lambda expression
+ // location: method_info
+
+ {
+ // struct:
+ // formal_parameter_target {
+ // u1 formal_parameter_index;
+ // }
+ //
+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a formal_parameter_target"));
+ return false;
+ }
+
+ u1 formal_parameter_index = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("formal_parameter_target: formal_parameter_index=%d",
+ formal_parameter_index));
+ } break;
+
+ case 0x17:
+ // kind: type in throws clause of method or constructor
+ // location: method_info
+
+ {
+ // struct:
+ // throws_target {
+ // u2 throws_type_index
+ // }
+ //
+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a throws_target"));
+ return false;
+ }
+
+ u2 throws_type_index = Bytes::get_Java_u2((address)
+ type_annotations_typeArray->adr_at(byte_i_ref));
+ byte_i_ref += 2;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("throws_target: throws_type_index=%d", throws_type_index));
+ } break;
+
+ case 0x40:
+ // kind: type in local variable declaration
+ // location: Code
+ case 0x41:
+ // kind: type in resource variable declaration
+ // location: Code
+
+ {
+ // struct:
+ // localvar_target {
+ // u2 table_length;
+ // struct {
+ // u2 start_pc;
+ // u2 length;
+ // u2 index;
+ // } table[table_length];
+ // }
+ //
+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) {
+ // not enough room for a table_length let alone the rest of a localvar_target
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a localvar_target table_length"));
+ return false;
+ }
+
+ u2 table_length = Bytes::get_Java_u2((address)
+ type_annotations_typeArray->adr_at(byte_i_ref));
+ byte_i_ref += 2;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("localvar_target: table_length=%d", table_length));
+
+ int table_struct_size = 2 + 2 + 2; // 3 u2 variables per table entry
+ int table_size = table_length * table_struct_size;
+
+ if ((byte_i_ref + table_size) > type_annotations_typeArray->length()) {
+ // not enough room for a table
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a table array of length %d", table_length));
+ return false;
+ }
+
+ // Skip over table
+ byte_i_ref += table_size;
+ } break;
+
+ case 0x42:
+ // kind: type in exception parameter declaration
+ // location: Code
+
+ {
+ // struct:
+ // catch_target {
+ // u2 exception_table_index;
+ // }
+ //
+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a catch_target"));
+ return false;
+ }
+
+ u2 exception_table_index = Bytes::get_Java_u2((address)
+ type_annotations_typeArray->adr_at(byte_i_ref));
+ byte_i_ref += 2;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("catch_target: exception_table_index=%d", exception_table_index));
+ } break;
+
+ case 0x43:
+ // kind: type in instanceof expression
+ // location: Code
+ case 0x44:
+ // kind: type in new expression
+ // location: Code
+ case 0x45:
+ // kind: type in method reference expression using ::new
+ // location: Code
+ case 0x46:
+ // kind: type in method reference expression using ::Identifier
+ // location: Code
+
+ {
+ // struct:
+ // offset_target {
+ // u2 offset;
+ // }
+ //
+ if ((byte_i_ref + 2) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a offset_target"));
+ return false;
+ }
+
+ u2 offset = Bytes::get_Java_u2((address)
+ type_annotations_typeArray->adr_at(byte_i_ref));
+ byte_i_ref += 2;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("offset_target: offset=%d", offset));
+ } break;
+
+ case 0x47:
+ // kind: type in cast expression
+ // location: Code
+ case 0x48:
+ // kind: type argument for generic constructor in new expression or
+ // explicit constructor invocation statement
+ // location: Code
+ case 0x49:
+ // kind: type argument for generic method in method invocation expression
+ // location: Code
+ case 0x4A:
+ // kind: type argument for generic constructor in method reference expression using ::new
+ // location: Code
+ case 0x4B:
+ // kind: type argument for generic method in method reference expression using ::Identifier
+ // location: Code
+
+ {
+ // struct:
+ // type_argument_target {
+ // u2 offset;
+ // u1 type_argument_index;
+ // }
+ //
+ if ((byte_i_ref + 3) > type_annotations_typeArray->length()) {
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a type_argument_target"));
+ return false;
+ }
+
+ u2 offset = Bytes::get_Java_u2((address)
+ type_annotations_typeArray->adr_at(byte_i_ref));
+ byte_i_ref += 2;
+ u1 type_argument_index = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("type_argument_target: offset=%d, type_argument_index=%d",
+ offset, type_argument_index));
+ } break;
+
+ default:
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("unknown target_type"));
+#ifdef ASSERT
+ ShouldNotReachHere();
+#endif
+ return false;
+ }
+
+ return true;
+} // end skip_type_annotation_target()
+
+
+// Read, verify and skip over the type_path part so that rewriting
+// can continue in the later parts of the struct.
+//
+// type_path {
+// u1 path_length;
+// {
+// u1 type_path_kind;
+// u1 type_argument_index;
+// } path[path_length];
+// }
+//
+bool VM_RedefineClasses::skip_type_annotation_type_path(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, TRAPS) {
+
+ if ((byte_i_ref + 1) > type_annotations_typeArray->length()) {
+ // not enough room for a path_length let alone the rest of the type_path
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for a type_path"));
+ return false;
+ }
+
+ u1 path_length = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("type_path: path_length=%d", path_length));
+
+ int calc_path_length = 0;
+ for (; calc_path_length < path_length; calc_path_length++) {
+ if ((byte_i_ref + 1 + 1) > type_annotations_typeArray->length()) {
+ // not enough room for a path
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("length() is too small for path entry %d of %d",
+ calc_path_length, path_length));
+ return false;
+ }
+
+ u1 type_path_kind = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+ u1 type_argument_index = type_annotations_typeArray->at(byte_i_ref);
+ byte_i_ref += 1;
+
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("type_path: path[%d]: type_path_kind=%d, type_argument_index=%d",
+ calc_path_length, type_path_kind, type_argument_index));
+
+ if (type_path_kind > 3 || (type_path_kind != 3 && type_argument_index != 0)) {
+ // not enough room for a path
+ RC_TRACE_WITH_THREAD(0x02000000, THREAD,
+ ("inconsistent type_path values"));
+ return false;
+ }
+ }
+ assert(path_length == calc_path_length, "sanity check");
+
+ return true;
+} // end skip_type_annotation_type_path()
+
+
// Rewrite constant pool references in the method's stackmap table.
// These "structures" are adapted from the StackMapTable_attribute that
// is described in section 4.8.4 of the 6.0 version of the VM spec
@@ -3223,23 +3828,6 @@
void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class,
instanceKlassHandle scratch_class) {
- // Since there is currently no rewriting of type annotations indexes
- // into the CP, we null out type annotations on scratch_class before
- // we swap annotations with the_class rather than facing the
- // possibility of shipping annotations with broken indexes to
- // Java-land.
- ClassLoaderData* loader_data = scratch_class->class_loader_data();
- AnnotationArray* new_class_type_annotations = scratch_class->class_type_annotations();
- if (new_class_type_annotations != NULL) {
- MetadataFactory::free_array<u1>(loader_data, new_class_type_annotations);
- scratch_class->annotations()->set_class_type_annotations(NULL);
- }
- Array<AnnotationArray*>* new_field_type_annotations = scratch_class->fields_type_annotations();
- if (new_field_type_annotations != NULL) {
- Annotations::free_contents(loader_data, new_field_type_annotations);
- scratch_class->annotations()->set_fields_type_annotations(NULL);
- }
-
// Swap annotation fields values
Annotations* old_annotations = the_class->annotations();
the_class->set_annotations(scratch_class->annotations());
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -452,6 +452,17 @@
instanceKlassHandle scratch_class, TRAPS);
bool rewrite_cp_refs_in_element_value(
AnnotationArray* class_annotations, int &byte_i_ref, TRAPS);
+ bool rewrite_cp_refs_in_type_annotations_typeArray(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref,
+ const char * location_mesg, TRAPS);
+ bool rewrite_cp_refs_in_type_annotation_struct(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref,
+ const char * location_mesg, TRAPS);
+ bool skip_type_annotation_target(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref,
+ const char * location_mesg, TRAPS);
+ bool skip_type_annotation_type_path(
+ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, TRAPS);
bool rewrite_cp_refs_in_fields_annotations(
instanceKlassHandle scratch_class, TRAPS);
void rewrite_cp_refs_in_method(methodHandle method,
@@ -463,6 +474,12 @@
instanceKlassHandle scratch_class, TRAPS);
bool rewrite_cp_refs_in_methods_parameter_annotations(
instanceKlassHandle scratch_class, TRAPS);
+ bool rewrite_cp_refs_in_class_type_annotations(
+ instanceKlassHandle scratch_class, TRAPS);
+ bool rewrite_cp_refs_in_fields_type_annotations(
+ instanceKlassHandle scratch_class, TRAPS);
+ bool rewrite_cp_refs_in_methods_type_annotations(
+ instanceKlassHandle scratch_class, TRAPS);
void rewrite_cp_refs_in_stack_map_table(methodHandle method, TRAPS);
void rewrite_cp_refs_in_verification_type_info(
address& stackmap_addr_ref, address stackmap_end, u2 frame_i,
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -36,6 +36,7 @@
#include "runtime/reflection.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/exceptions.hpp"
/*
@@ -55,26 +56,30 @@
bool MethodHandles::_enabled = false; // set true after successful native linkage
MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL;
-//------------------------------------------------------------------------------
-// MethodHandles::generate_adapters
-//
-void MethodHandles::generate_adapters() {
- if (SystemDictionary::MethodHandle_klass() == NULL) return;
+
+/**
+ * Generates method handle adapters. Returns 'false' if memory allocation
+ * failed and true otherwise.
+ */
+bool MethodHandles::generate_adapters() {
+ if (SystemDictionary::MethodHandle_klass() == NULL) {
+ return true;
+ }
assert(_adapter_code == NULL, "generate only once");
ResourceMark rm;
TraceTime timer("MethodHandles adapters generation", TraceStartupTime);
_adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size);
- if (_adapter_code == NULL)
- vm_exit_out_of_memory(adapter_code_size, OOM_MALLOC_ERROR,
- "CodeCache: no room for MethodHandles adapters");
- {
- CodeBuffer code(_adapter_code);
- MethodHandlesAdapterGenerator g(&code);
- g.generate();
- code.log_section_sizes("MethodHandlesAdapterBlob");
+ if (_adapter_code == NULL) {
+ return false;
}
+
+ CodeBuffer code(_adapter_code);
+ MethodHandlesAdapterGenerator g(&code);
+ g.generate();
+ code.log_section_sizes("MethodHandlesAdapterBlob");
+ return true;
}
//------------------------------------------------------------------------------
@@ -1401,7 +1406,9 @@
}
if (enable_MH) {
- MethodHandles::generate_adapters();
+ if (MethodHandles::generate_adapters() == false) {
+ THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), "Out of space in CodeCache for method handle adapters");
+ }
MethodHandles::set_enabled(true);
}
}
--- a/hotspot/src/share/vm/prims/methodHandles.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -69,7 +69,7 @@
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
// Generate MethodHandles adapters.
- static void generate_adapters();
+ static bool generate_adapters();
// Called from MethodHandlesAdapterGenerator.
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid);
--- a/hotspot/src/share/vm/prims/unsafe.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -802,8 +802,7 @@
static inline void throw_new(JNIEnv *env, const char *ename) {
char buf[100];
- strcpy(buf, "java/lang/");
- strcat(buf, ename);
+ jio_snprintf(buf, 100, "%s%s", "java/lang/", ename);
jclass cls = env->FindClass(buf);
if (env->ExceptionCheck()) {
env->ExceptionClear();
--- a/hotspot/src/share/vm/prims/whitebox.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -282,7 +282,7 @@
// NMT picks it up correctly
WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
jlong addr = 0;
- addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
+ addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
return addr;
WB_END
@@ -291,7 +291,7 @@
WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
address pc = (address)(size_t)pseudo_stack;
NativeCallStack stack(&pc, 1);
- return (jlong)os::malloc(size, mtTest, stack);
+ return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
WB_END
// Free the memory allocated by NMTAllocTest
@@ -326,15 +326,6 @@
return MemTracker::tracking_level() == NMT_detail;
WB_END
-WB_ENTRY(void, WB_NMTOverflowHashBucket(JNIEnv* env, jobject o, jlong num))
- address pc = (address)1;
- for (jlong index = 0; index < num; index ++) {
- NativeCallStack stack(&pc, 1);
- os::malloc(0, mtTest, stack);
- pc += MallocSiteTable::hash_buckets();
- }
-WB_END
-
WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env))
// Test that we can downgrade NMT levels but not upgrade them.
if (MemTracker::tracking_level() == NMT_off) {
@@ -365,6 +356,12 @@
return MemTracker::tracking_level() == NMT_minimal;
}
WB_END
+
+WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
+ int hash_size = MallocSiteTable::hash_buckets();
+ assert(hash_size > 0, "NMT hash_size should be > 0");
+ return (jint)hash_size;
+WB_END
#endif // INCLUDE_NMT
static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
@@ -386,19 +383,10 @@
CHECK_JNI_EXCEPTION_(env, result);
MutexLockerEx mu(Compile_lock);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
- nmethod* code;
if (is_osr) {
- int bci = InvocationEntryBci;
- while ((code = mh->lookup_osr_nmethod_for(bci, CompLevel_none, false)) != NULL) {
- code->mark_for_deoptimization();
- ++result;
- bci = code->osr_entry_bci() + 1;
- }
- } else {
- code = mh->code();
- }
- if (code != NULL) {
- code->mark_for_deoptimization();
+ result += mh->mark_osr_nmethods();
+ } else if (mh->code() != NULL) {
+ mh->code()->mark_for_deoptimization();
++result;
}
result += CodeCache::mark_for_deoptimization(mh());
@@ -518,16 +506,6 @@
static AlwaysFalseClosure always_false;
-class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation {
- public:
- VM_WhiteBoxCleanMethodData(MethodData* mdo) : _mdo(mdo) { }
- void doit() {
- _mdo->clean_method_data(&always_false);
- }
- private:
- MethodData* _mdo;
-};
-
WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION(env);
@@ -543,8 +521,8 @@
for (int i = 0; i < arg_count; i++) {
mdo->set_arg_modified(i, 0);
}
- VM_WhiteBoxCleanMethodData op(mdo);
- VMThread::execute(&op);
+ MutexLockerEx mu(mdo->extra_data_lock());
+ mdo->clean_method_data(&always_false);
}
mh->clear_not_c1_compilable();
@@ -566,13 +544,13 @@
WB_END
template <typename T>
-static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*)) {
+static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*, bool, bool)) {
if (name == NULL) {
return false;
}
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
const char* flag_name = env->GetStringUTFChars(name, NULL);
- bool result = (*TAt)(flag_name, value);
+ bool result = (*TAt)(flag_name, value, true, true);
env->ReleaseStringUTFChars(name, flag_name);
return result;
}
@@ -619,6 +597,24 @@
return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
}
+static Flag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
+ ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
+ const char* flag_name = env->GetStringUTFChars(name, NULL);
+ Flag* result = Flag::find_flag(flag_name, strlen(flag_name), true, true);
+ env->ReleaseStringUTFChars(name, flag_name);
+ return result;
+}
+
+WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
+ Flag* flag = getVMFlag(thread, env, name);
+ return (flag != NULL) && flag->is_constant_in_binary();
+WB_END
+
+WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
+ Flag* flag = getVMFlag(thread, env, name);
+ return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
+WB_END
+
WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
bool result;
if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
@@ -794,20 +790,24 @@
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
- result = env->NewObjectArray(2, clazz, NULL);
+ result = env->NewObjectArray(3, clazz, NULL);
if (result == NULL) {
return result;
}
- jobject obj = integerBox(thread, env, code->comp_level());
+ jobject level = integerBox(thread, env, code->comp_level());
CHECK_JNI_EXCEPTION_(env, NULL);
- env->SetObjectArrayElement(result, 0, obj);
+ env->SetObjectArrayElement(result, 0, level);
jbyteArray insts = env->NewByteArray(insts_size);
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
env->SetObjectArrayElement(result, 1, insts);
+ jobject id = integerBox(thread, env, code->compile_id());
+ CHECK_JNI_EXCEPTION_(env, NULL);
+ env->SetObjectArrayElement(result, 2, id);
+
return result;
WB_END
@@ -989,9 +989,9 @@
{CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory },
{CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory },
{CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory },
- {CC"NMTOverflowHashBucket", CC"(J)V", (void*)&WB_NMTOverflowHashBucket},
{CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported},
{CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel},
+ {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize },
#endif // INCLUDE_NMT
{CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
{CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I",
@@ -1018,6 +1018,8 @@
CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
{CC"clearMethodState",
CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
+ {CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
+ {CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
{CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
{CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
{CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -54,7 +54,7 @@
#endif // INCLUDE_ALL_GCS
// Note: This is a special bug reporting site for the JVM
-#define DEFAULT_VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/crash.jsp"
+#define DEFAULT_VENDOR_URL_BUG "http://bugreport.java.com/bugreport/crash.jsp"
#define DEFAULT_JAVA_LAUNCHER "generic"
// Disable options not supported in this release, with a warning if they
@@ -306,6 +306,9 @@
{ "ReflectionWrapResolutionErrors",JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "VerifyReflectionBytecodes", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "AutoShutdownNMT", JDK_Version::jdk(9), JDK_Version::jdk(10) },
+ { "NmethodSweepFraction", JDK_Version::jdk(9), JDK_Version::jdk(10) },
+ { "NmethodSweepCheckInterval", JDK_Version::jdk(9), JDK_Version::jdk(10) },
+ { "CodeCacheMinimumFreeSpace", JDK_Version::jdk(9), JDK_Version::jdk(10) },
#ifndef ZERO
{ "UseFastAccessorMethods", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "UseFastEmptyMethods", JDK_Version::jdk(9), JDK_Version::jdk(10) },
@@ -2528,7 +2531,7 @@
// Check lower bounds of the code cache
// Template Interpreter code is approximately 3X larger in debug builds.
- uint min_code_cache_size = (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3)) + CodeCacheMinimumFreeSpace;
+ uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
if (InitialCodeCacheSize < (uintx)os::vm_page_size()) {
jio_fprintf(defaultStream::error_stream(),
"Invalid InitialCodeCacheSize=%dK. Must be at least %dK.\n", InitialCodeCacheSize/K,
@@ -2564,10 +2567,11 @@
status = false;
}
- status &= verify_interval(NmethodSweepFraction, 1, ReservedCodeCacheSize/K, "NmethodSweepFraction");
status &= verify_interval(NmethodSweepActivity, 0, 2000, "NmethodSweepActivity");
status &= verify_interval(CodeCacheMinBlockLength, 1, 100, "CodeCacheMinBlockLength");
status &= verify_interval(CodeCacheSegmentSize, 1, 1024, "CodeCacheSegmentSize");
+ status &= verify_interval(StartAggressiveSweepingAt, 0, 100, "StartAggressiveSweepingAt");
+
int min_number_of_compiler_threads = get_min_number_of_compiler_threads();
// The default CICompilerCount's value is CI_COMPILER_COUNT.
@@ -3992,12 +3996,6 @@
#endif
#endif
- // Set NmethodSweepFraction after the size of the code cache is adapted (in case of tiered)
- if (FLAG_IS_DEFAULT(NmethodSweepFraction)) {
- FLAG_SET_DEFAULT(NmethodSweepFraction, 1 + ReservedCodeCacheSize / (16 * M));
- }
-
-
// Set heap size based on available physical memory
set_heap_size();
@@ -4065,13 +4063,6 @@
}
#ifndef PRODUCT
- if (CompileTheWorld) {
- // Force NmethodSweeper to sweep whole CodeCache each time.
- if (FLAG_IS_DEFAULT(NmethodSweepFraction)) {
- NmethodSweepFraction = 1;
- }
- }
-
if (!LogVMOutput && FLAG_IS_DEFAULT(LogVMOutput)) {
if (use_vm_log()) {
LogVMOutput = true;
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1173,7 +1173,7 @@
void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) {
// in case of an unresolved klass entry, load the class.
if (constant_pool->tag_at(index).is_unresolved_klass()) {
- Klass* tk = constant_pool->klass_at(index, CHECK);
+ Klass* tk = constant_pool->klass_at_ignore_error(index, CHECK);
return;
}
--- a/hotspot/src/share/vm/runtime/globals.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/globals.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -28,6 +28,7 @@
#include "runtime/arguments.hpp"
#include "runtime/globals.hpp"
#include "runtime/globals_extension.hpp"
+#include "runtime/os.hpp"
#include "utilities/ostream.hpp"
#include "utilities/macros.hpp"
#include "utilities/top.hpp"
@@ -634,8 +635,8 @@
e.commit();
}
-bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value) {
- Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
+ Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
if (result == NULL) return false;
if (!result->is_bool()) return false;
*value = result->get_bool();
@@ -662,8 +663,8 @@
faddr->set_origin(origin);
}
-bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value) {
- Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
+ Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
if (result == NULL) return false;
if (!result->is_intx()) return false;
*value = result->get_intx();
@@ -690,8 +691,8 @@
faddr->set_origin(origin);
}
-bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value) {
- Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
+ Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
if (result == NULL) return false;
if (!result->is_uintx()) return false;
*value = result->get_uintx();
@@ -718,8 +719,8 @@
faddr->set_origin(origin);
}
-bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value) {
- Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
+ Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
if (result == NULL) return false;
if (!result->is_uint64_t()) return false;
*value = result->get_uint64_t();
@@ -746,8 +747,8 @@
faddr->set_origin(origin);
}
-bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value) {
- Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
+ Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
if (result == NULL) return false;
if (!result->is_size_t()) return false;
*value = result->get_size_t();
@@ -774,8 +775,8 @@
faddr->set_origin(origin);
}
-bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) {
- Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
+ Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
if (result == NULL) return false;
if (!result->is_double()) return false;
*value = result->get_double();
@@ -802,8 +803,8 @@
faddr->set_origin(origin);
}
-bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value) {
- Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
+ Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
if (result == NULL) return false;
if (!result->is_ccstr()) return false;
*value = result->get_ccstr();
@@ -818,15 +819,12 @@
trace_flag_changed<EventStringFlagChanged, const char*>(name, old_value, *value, origin);
char* new_value = NULL;
if (*value != NULL) {
- new_value = NEW_C_HEAP_ARRAY(char, strlen(*value)+1, mtInternal);
- strcpy(new_value, *value);
+ new_value = os::strdup_check_oom(*value);
}
result->set_ccstr(new_value);
if (result->is_default() && old_value != NULL) {
// Prior value is NOT heap allocated, but was a literal constant.
- char* old_value_to_free = NEW_C_HEAP_ARRAY(char, strlen(old_value)+1, mtInternal);
- strcpy(old_value_to_free, old_value);
- old_value = old_value_to_free;
+ old_value = os::strdup_check_oom(old_value);
}
*value = old_value;
result->set_origin(origin);
@@ -838,8 +836,7 @@
guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
ccstr old_value = faddr->get_ccstr();
trace_flag_changed<EventStringFlagChanged, const char*>(faddr->_name, old_value, value, origin);
- char* new_value = NEW_C_HEAP_ARRAY(char, strlen(value)+1, mtInternal);
- strcpy(new_value, value);
+ char* new_value = os::strdup_check_oom(value);
faddr->set_ccstr(new_value);
if (!faddr->is_default() && old_value != NULL) {
// Prior value is heap allocated so free it.
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -379,38 +379,38 @@
class CommandLineFlags {
public:
- static bool boolAt(const char* name, size_t len, bool* value);
- static bool boolAt(const char* name, bool* value) { return boolAt(name, strlen(name), value); }
+ static bool boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false);
+ static bool boolAt(const char* name, bool* value, bool allow_locked = false, bool return_flag = false) { return boolAt(name, strlen(name), value, allow_locked, return_flag); }
static bool boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin);
static bool boolAtPut(const char* name, bool* value, Flag::Flags origin) { return boolAtPut(name, strlen(name), value, origin); }
- static bool intxAt(const char* name, size_t len, intx* value);
- static bool intxAt(const char* name, intx* value) { return intxAt(name, strlen(name), value); }
+ static bool intxAt(const char* name, size_t len, intx* value, bool allow_locked = false, bool return_flag = false);
+ static bool intxAt(const char* name, intx* value, bool allow_locked = false, bool return_flag = false) { return intxAt(name, strlen(name), value, allow_locked, return_flag); }
static bool intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin);
static bool intxAtPut(const char* name, intx* value, Flag::Flags origin) { return intxAtPut(name, strlen(name), value, origin); }
- static bool uintxAt(const char* name, size_t len, uintx* value);
- static bool uintxAt(const char* name, uintx* value) { return uintxAt(name, strlen(name), value); }
+ static bool uintxAt(const char* name, size_t len, uintx* value, bool allow_locked = false, bool return_flag = false);
+ static bool uintxAt(const char* name, uintx* value, bool allow_locked = false, bool return_flag = false) { return uintxAt(name, strlen(name), value, allow_locked, return_flag); }
static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
- static bool size_tAt(const char* name, size_t len, size_t* value);
- static bool size_tAt(const char* name, size_t* value) { return size_tAt(name, strlen(name), value); }
+ static bool size_tAt(const char* name, size_t len, size_t* value, bool allow_locked = false, bool return_flag = false);
+ static bool size_tAt(const char* name, size_t* value, bool allow_locked = false, bool return_flag = false) { return size_tAt(name, strlen(name), value, allow_locked, return_flag); }
static bool size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin);
static bool size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); }
- static bool uint64_tAt(const char* name, size_t len, uint64_t* value);
- static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
+ static bool uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked = false, bool return_flag = false);
+ static bool uint64_tAt(const char* name, uint64_t* value, bool allow_locked = false, bool return_flag = false) { return uint64_tAt(name, strlen(name), value, allow_locked, return_flag); }
static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
static bool uint64_tAtPut(const char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
- static bool doubleAt(const char* name, size_t len, double* value);
- static bool doubleAt(const char* name, double* value) { return doubleAt(name, strlen(name), value); }
+ static bool doubleAt(const char* name, size_t len, double* value, bool allow_locked = false, bool return_flag = false);
+ static bool doubleAt(const char* name, double* value, bool allow_locked = false, bool return_flag = false) { return doubleAt(name, strlen(name), value, allow_locked, return_flag); }
static bool doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin);
static bool doubleAtPut(const char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); }
- static bool ccstrAt(const char* name, size_t len, ccstr* value);
- static bool ccstrAt(const char* name, ccstr* value) { return ccstrAt(name, strlen(name), value); }
+ static bool ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked = false, bool return_flag = false);
+ static bool ccstrAt(const char* name, ccstr* value, bool allow_locked = false, bool return_flag = false) { return ccstrAt(name, strlen(name), value, allow_locked, return_flag); }
// Contract: Flag will make private copy of the incoming value.
// Outgoing value is always malloc-ed, and caller MUST call free.
static bool ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin);
@@ -2066,9 +2066,6 @@
"Provide more detailed and expensive TLAB statistics " \
"(with PrintTLAB)") \
\
- EMBEDDED_ONLY(product(bool, LowMemoryProtection, true, \
- "Enable LowMemoryProtection")) \
- \
product_pd(bool, NeverActAsServerClassMachine, \
"Never act like a server-class machine") \
\
@@ -2984,12 +2981,6 @@
product(intx, SafepointTimeoutDelay, 10000, \
"Delay in milliseconds for option SafepointTimeout") \
\
- product(intx, NmethodSweepFraction, 16, \
- "Number of invocations of sweeper to cover all nmethods") \
- \
- product(intx, NmethodSweepCheckInterval, 5, \
- "Compilers wake up every n seconds to possibly sweep nmethods") \
- \
product(intx, NmethodSweepActivity, 10, \
"Removes cold nmethods from code cache if > 0. Higher values " \
"result in more aggressive sweeping") \
@@ -3378,9 +3369,6 @@
product_pd(uintx, NonNMethodCodeHeapSize, \
"Size of code heap with non-nmethods (in bytes)") \
\
- product(uintx, CodeCacheMinimumFreeSpace, 500*K, \
- "When less than X space left, we stop compiling") \
- \
product_pd(uintx, CodeCacheExpansionSize, \
"Code cache expansion size (in bytes)") \
\
@@ -3393,6 +3381,11 @@
product(bool, UseCodeCacheFlushing, true, \
"Remove cold/old nmethods from the code cache") \
\
+ product(uintx, StartAggressiveSweepingAt, 10, \
+ "Start aggressive sweeping if X[%] of the code cache is free." \
+ "Segmented code cache: X[%] of the non-profiled heap." \
+ "Non-segmented code cache: X[%] of the total code cache") \
+ \
/* interpreter debugging */ \
develop(intx, BinarySwitchThreshold, 5, \
"Minimal number of lookupswitch entries for rewriting to binary " \
--- a/hotspot/src/share/vm/runtime/interfaceSupport.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/interfaceSupport.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -187,19 +187,22 @@
# endif
-
+// invocation counter for InterfaceSupport::deoptimizeAll/zombieAll functions
int deoptimizeAllCounter = 0;
int zombieAllCounter = 0;
-
void InterfaceSupport::zombieAll() {
- if (is_init_completed() && zombieAllCounter > ZombieALotInterval) {
+ // This method is called by all threads when a thread make
+ // transition to VM state (for example, runtime calls).
+ // Divide number of calls by number of threads to avoid
+ // dependence of ZombieAll events frequency on number of threads.
+ int value = zombieAllCounter / Threads::number_of_threads();
+ if (is_init_completed() && value > ZombieALotInterval) {
zombieAllCounter = 0;
VM_ZombieAll op;
VMThread::execute(&op);
- } else {
- zombieAllCounter++;
}
+ zombieAllCounter++;
}
void InterfaceSupport::unlinkSymbols() {
@@ -208,12 +211,17 @@
}
void InterfaceSupport::deoptimizeAll() {
- if (is_init_completed() ) {
- if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) {
+ // This method is called by all threads when a thread make
+ // transition to VM state (for example, runtime calls).
+ // Divide number of calls by number of threads to avoid
+ // dependence of DeoptimizeAll events frequency on number of threads.
+ int value = deoptimizeAllCounter / Threads::number_of_threads();
+ if (is_init_completed()) {
+ if (DeoptimizeALot && value > DeoptimizeALotInterval) {
deoptimizeAllCounter = 0;
VM_DeoptimizeAll op;
VMThread::execute(&op);
- } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) {
+ } else if (DeoptimizeRandom && (value & 0x1F) == (os::random() & 0x1F)) {
VM_DeoptimizeAll op;
VMThread::execute(&op);
}
--- a/hotspot/src/share/vm/runtime/java.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/java.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -705,25 +705,35 @@
}
void JDK_Version::to_string(char* buffer, size_t buflen) const {
+ assert(buffer && buflen > 0, "call with useful buffer");
size_t index = 0;
+
if (!is_valid()) {
jio_snprintf(buffer, buflen, "%s", "(uninitialized)");
} else if (is_partially_initialized()) {
jio_snprintf(buffer, buflen, "%s", "(uninitialized) pre-1.6.0");
} else {
- index += jio_snprintf(
+ int rc = jio_snprintf(
&buffer[index], buflen - index, "%d.%d", _major, _minor);
+ if (rc == -1) return;
+ index += rc;
if (_micro > 0) {
- index += jio_snprintf(&buffer[index], buflen - index, ".%d", _micro);
+ rc = jio_snprintf(&buffer[index], buflen - index, ".%d", _micro);
}
if (_update > 0) {
- index += jio_snprintf(&buffer[index], buflen - index, "_%02d", _update);
+ rc = jio_snprintf(&buffer[index], buflen - index, "_%02d", _update);
+ if (rc == -1) return;
+ index += rc;
}
if (_special > 0) {
- index += jio_snprintf(&buffer[index], buflen - index, "%c", _special);
+ rc = jio_snprintf(&buffer[index], buflen - index, "%c", _special);
+ if (rc == -1) return;
+ index += rc;
}
if (_build > 0) {
- index += jio_snprintf(&buffer[index], buflen - index, "-b%02d", _build);
+ rc = jio_snprintf(&buffer[index], buflen - index, "-b%02d", _build);
+ if (rc == -1) return;
+ index += rc;
}
}
}
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -61,7 +61,7 @@
Mutex* StringTable_lock = NULL;
Monitor* StringDedupQueue_lock = NULL;
Mutex* StringDedupTable_lock = NULL;
-Mutex* CodeCache_lock = NULL;
+Monitor* CodeCache_lock = NULL;
Mutex* MethodData_lock = NULL;
Mutex* RetData_lock = NULL;
Monitor* VMOperationQueue_lock = NULL;
@@ -205,7 +205,7 @@
}
def(ParGCRareEvent_lock , Mutex , leaf , true );
def(DerivedPointerTableGC_lock , Mutex, leaf, true );
- def(CodeCache_lock , Mutex , special, true );
+ def(CodeCache_lock , Monitor, special, true );
def(Interrupt_lock , Monitor, special, true ); // used for interrupt processing
def(RawMonitor_lock , Mutex, special, true );
def(OopMapCacheAlloc_lock , Mutex, leaf, true ); // used for oop_map_cache allocation.
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -53,7 +53,7 @@
extern Mutex* StringTable_lock; // a lock on the interned string table
extern Monitor* StringDedupQueue_lock; // a lock on the string deduplication queue
extern Mutex* StringDedupTable_lock; // a lock on the string deduplication table
-extern Mutex* CodeCache_lock; // a lock on the CodeCache, rank is special, use MutexLockerEx
+extern Monitor* CodeCache_lock; // a lock on the CodeCache, rank is special, use MutexLockerEx
extern Mutex* MethodData_lock; // a lock on installation of method data
extern Mutex* RetData_lock; // a lock on installation of RetData inside method data
extern Mutex* DerivedPointerTableGC_lock; // a lock to protect the derived pointer table
--- a/hotspot/src/share/vm/runtime/os.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/os.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -571,17 +571,6 @@
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
-#if INCLUDE_NMT
- // NMT can not track malloc allocation size > MAX_MALLOC_SIZE, which is
- // (1GB - 1) on 32-bit system. It is not an issue on 64-bit system, where
- // MAX_MALLOC_SIZE = ((1 << 62) - 1).
- // VM code does not have such large malloc allocation. However, it can come
- // Unsafe call.
- if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
- return NULL;
- }
-#endif
-
#ifdef ASSERT
// checking for the WatcherThread and crash_protection first
// since os::malloc can be called when the libjvm.{dll,so} is
@@ -652,12 +641,6 @@
}
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
-#if INCLUDE_NMT
- // See comments in os::malloc() above
- if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
- return NULL;
- }
-#endif
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
--- a/hotspot/src/share/vm/runtime/os.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/os.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -158,7 +158,6 @@
static void init_globals(void) { // Called from init_globals() in init.cpp
init_globals_ext();
}
- static void init_3(void); // Called at the end of vm init
// File names are case-insensitive on windows only
// Override me as needed
@@ -680,28 +679,10 @@
// SocketInterface (ex HPI SocketInterface )
static int socket(int domain, int type, int protocol);
static int socket_close(int fd);
- static int socket_shutdown(int fd, int howto);
static int recv(int fd, char* buf, size_t nBytes, uint flags);
static int send(int fd, char* buf, size_t nBytes, uint flags);
static int raw_send(int fd, char* buf, size_t nBytes, uint flags);
- static int timeout(int fd, long timeout);
- static int listen(int fd, int count);
static int connect(int fd, struct sockaddr* him, socklen_t len);
- static int bind(int fd, struct sockaddr* him, socklen_t len);
- static int accept(int fd, struct sockaddr* him, socklen_t* len);
- static int recvfrom(int fd, char* buf, size_t nbytes, uint flags,
- struct sockaddr* from, socklen_t* fromlen);
- static int get_sock_name(int fd, struct sockaddr* him, socklen_t* len);
- static int sendto(int fd, char* buf, size_t len, uint flags,
- struct sockaddr* to, socklen_t tolen);
- static int socket_available(int fd, jint* pbytes);
-
- static int get_sock_opt(int fd, int level, int optname,
- char* optval, socklen_t* optlen);
- static int set_sock_opt(int fd, int level, int optname,
- const char* optval, socklen_t optlen);
- static int get_host_name(char* name, int namelen);
-
static struct hostent* get_host_by_name(char* name);
// Support for signals (see JVM_RaiseSignal, JVM_RegisterSignal)
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -2421,8 +2421,6 @@
// CodeCache is full, disable compilation
// Ought to log this but compile log is only per compile thread
// and we're some non descript Java thread.
- MutexUnlocker mu(AdapterHandlerLibrary_lock);
- CompileBroker::handle_full_code_cache(CodeBlobType::NonNMethod);
return NULL; // Out of CodeCache space
}
entry->relocate(new_adapter->content_begin());
@@ -2594,9 +2592,6 @@
CompileTask::print_compilation(tty, nm, method->is_static() ? "(static)" : "");
}
nm->post_compiled_method_load_event();
- } else {
- // CodeCache is full, disable compilation
- CompileBroker::handle_full_code_cache(CodeBlobType::MethodNonProfiled);
}
}
--- a/hotspot/src/share/vm/runtime/signature.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/signature.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -158,7 +158,7 @@
uint64_t saved_fingerprint = fingerprint;
// Check for too many arguments
- if ( fingerprint == UCONST64(-1) ) {
+ if (fingerprint == (uint64_t)CONST64(-1)) {
SignatureIterator::iterate_parameters();
return;
}
--- a/hotspot/src/share/vm/runtime/signature.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/signature.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -243,7 +243,7 @@
}
if (mh->size_of_parameters() > max_size_of_parameters ) {
- _fingerprint = UCONST64(-1);
+ _fingerprint = (uint64_t)CONST64(-1);
mh->constMethod()->set_fingerprint(_fingerprint);
return _fingerprint;
}
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -196,7 +196,6 @@
// Don't trigger other compiles in testing mode
return NULL;
}
- nmethod *osr_nm = NULL;
handle_counter_overflow(method());
if (method() != inlinee()) {
@@ -210,14 +209,16 @@
if (bci == InvocationEntryBci) {
method_invocation_event(method, inlinee, comp_level, nm, thread);
} else {
+ // method == inlinee if the event originated in the main method
method_back_branch_event(method, inlinee, bci, comp_level, nm, thread);
- // method == inlinee if the event originated in the main method
- int highest_level = inlinee->highest_osr_comp_level();
- if (highest_level > comp_level) {
- osr_nm = inlinee->lookup_osr_nmethod_for(bci, highest_level, false);
+ // Check if event led to a higher level OSR compilation
+ nmethod* osr_nm = inlinee->lookup_osr_nmethod_for(bci, comp_level, false);
+ if (osr_nm != NULL && osr_nm->comp_level() > comp_level) {
+ // Perform OSR with new nmethod
+ return osr_nm;
}
}
- return osr_nm;
+ return NULL;
}
// Check if the method can be compiled, change level if necessary
--- a/hotspot/src/share/vm/runtime/sweeper.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -52,7 +52,6 @@
class SweeperRecord {
public:
int traversal;
- int invocation;
int compile_id;
long traversal_mark;
int state;
@@ -62,10 +61,9 @@
int line;
void print() {
- tty->print_cr("traversal = %d invocation = %d compile_id = %d %s uep = " PTR_FORMAT " vep = "
+ tty->print_cr("traversal = %d compile_id = %d %s uep = " PTR_FORMAT " vep = "
PTR_FORMAT " state = %d traversal_mark %d line = %d",
traversal,
- invocation,
compile_id,
kind == NULL ? "" : kind,
uep,
@@ -117,7 +115,6 @@
if (_records != NULL) {
_records[_sweep_index].traversal = _traversals;
_records[_sweep_index].traversal_mark = nm->_stack_traversal_mark;
- _records[_sweep_index].invocation = _sweep_fractions_left;
_records[_sweep_index].compile_id = nm->compile_id();
_records[_sweep_index].kind = nm->compile_kind();
_records[_sweep_index].state = nm->_state;
@@ -127,6 +124,14 @@
_sweep_index = (_sweep_index + 1) % SweeperLogEntries;
}
}
+
+void NMethodSweeper::init_sweeper_log() {
+ if (LogSweeper && _records == NULL) {
+ // Create the ring buffer for the logging code
+ _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries, mtGC);
+ memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
+ }
+}
#else
#define SWEEP(nm)
#endif
@@ -142,8 +147,6 @@
int NMethodSweeper::_marked_for_reclamation_count = 0; // Nof. nmethods marked for reclaim in current sweep
volatile bool NMethodSweeper::_should_sweep = true; // Indicates if we should invoke the sweeper
-volatile int NMethodSweeper::_sweep_fractions_left = 0; // Nof. invocations left until we are completed with this pass
-volatile int NMethodSweeper::_sweep_started = 0; // Flag to control conc sweeper
volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from:
// 1) alive -> not_entrant
// 2) not_entrant -> zombie
@@ -190,13 +193,15 @@
}
return _hotness_counter_reset_val;
}
-bool NMethodSweeper::sweep_in_progress() {
- return !_current.end();
+bool NMethodSweeper::wait_for_stack_scanning() {
+ return _current.end();
}
-// Scans the stacks of all Java threads and marks activations of not-entrant methods.
-// No need to synchronize access, since 'mark_active_nmethods' is always executed at a
-// safepoint.
+/**
+ * Scans the stacks of all Java threads and marks activations of not-entrant methods.
+ * No need to synchronize access, since 'mark_active_nmethods' is always executed at a
+ * safepoint.
+ */
void NMethodSweeper::mark_active_nmethods() {
assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
// If we do not want to reclaim not-entrant or zombie methods there is no need
@@ -210,9 +215,8 @@
// Check for restart
assert(CodeCache::find_blob_unsafe(_current.method()) == _current.method(), "Sweeper nmethod cached state invalid");
- if (!sweep_in_progress()) {
+ if (wait_for_stack_scanning()) {
_seen = 0;
- _sweep_fractions_left = NmethodSweepFraction;
_current = NMethodIterator();
// Initialize to first nmethod
_current.next();
@@ -231,6 +235,64 @@
OrderAccess::storestore();
}
+
+/**
+ * This function triggers a VM operation that does stack scanning of active
+ * methods. Stack scanning is mandatory for the sweeper to make progress.
+ */
+void NMethodSweeper::do_stack_scanning() {
+ assert(!CodeCache_lock->owned_by_self(), "just checking");
+ if (wait_for_stack_scanning()) {
+ VM_MarkActiveNMethods op;
+ VMThread::execute(&op);
+ _should_sweep = true;
+ }
+}
+
+void NMethodSweeper::sweeper_loop() {
+ bool timeout;
+ while (true) {
+ {
+ ThreadBlockInVM tbivm(JavaThread::current());
+ MutexLockerEx waiter(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ const long wait_time = 60*60*24 * 1000;
+ timeout = CodeCache_lock->wait(Mutex::_no_safepoint_check_flag, wait_time);
+ }
+ if (!timeout) {
+ possibly_sweep();
+ }
+ }
+}
+
+/**
+ * Wakes up the sweeper thread to possibly sweep.
+ */
+void NMethodSweeper::notify(int code_blob_type) {
+ // Makes sure that we do not invoke the sweeper too often during startup.
+ double start_threshold = 100.0 / (double)StartAggressiveSweepingAt;
+ double aggressive_sweep_threshold = MIN2(start_threshold, 1.1);
+ if (CodeCache::reverse_free_ratio(code_blob_type) >= aggressive_sweep_threshold) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ CodeCache_lock->notify();
+ }
+}
+
+/**
+ * Handle a safepoint request
+ */
+void NMethodSweeper::handle_safepoint_request() {
+ if (SafepointSynchronize::is_synchronizing()) {
+ if (PrintMethodFlushing && Verbose) {
+ tty->print_cr("### Sweep at %d out of %d, yielding to safepoint", _seen, CodeCache::nof_nmethods());
+ }
+ MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+
+ JavaThread* thread = JavaThread::current();
+ ThreadBlockInVM tbivm(thread);
+ thread->java_suspend_self();
+ }
+}
+
/**
* This function invokes the sweeper if at least one of the three conditions is met:
* (1) The code cache is getting full
@@ -239,11 +301,6 @@
*/
void NMethodSweeper::possibly_sweep() {
assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
- // Only compiler threads are allowed to sweep
- if (!MethodFlushing || !sweep_in_progress() || !Thread::current()->is_Compiler_thread()) {
- return;
- }
-
// If there was no state change while nmethod sweeping, 'should_sweep' will be false.
// This is one of the two places where should_sweep can be set to true. The general
// idea is as follows: If there is enough free space in the code cache, there is no
@@ -280,46 +337,37 @@
}
}
- if (_should_sweep && _sweep_fractions_left > 0) {
- // Only one thread at a time will sweep
- jint old = Atomic::cmpxchg( 1, &_sweep_started, 0 );
- if (old != 0) {
- return;
- }
-#ifdef ASSERT
- if (LogSweeper && _records == NULL) {
- // Create the ring buffer for the logging code
- _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries, mtGC);
- memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
- }
-#endif
+ // Force stack scanning if there is only 10% free space in the code cache.
+ // We force stack scanning only non-profiled code heap gets full, since critical
+ // allocation go to the non-profiled heap and we must be make sure that there is
+ // enough space.
+ double free_percent = 1 / CodeCache::reverse_free_ratio(CodeBlobType::MethodNonProfiled) * 100;
+ if (free_percent <= StartAggressiveSweepingAt) {
+ do_stack_scanning();
+ }
- if (_sweep_fractions_left > 0) {
- sweep_code_cache();
- _sweep_fractions_left--;
- }
+ if (_should_sweep) {
+ init_sweeper_log();
+ sweep_code_cache();
+ }
- // We are done with sweeping the code cache once.
- if (_sweep_fractions_left == 0) {
- _total_nof_code_cache_sweeps++;
- _last_sweep = _time_counter;
- // Reset flag; temporarily disables sweeper
- _should_sweep = false;
- // If there was enough state change, 'possibly_enable_sweeper()'
- // sets '_should_sweep' to true
- possibly_enable_sweeper();
- // Reset _bytes_changed only if there was enough state change. _bytes_changed
- // can further increase by calls to 'report_state_change'.
- if (_should_sweep) {
- _bytes_changed = 0;
- }
- }
- // Release work, because another compiler thread could continue.
- OrderAccess::release_store((int*)&_sweep_started, 0);
+ // We are done with sweeping the code cache once.
+ _total_nof_code_cache_sweeps++;
+ _last_sweep = _time_counter;
+ // Reset flag; temporarily disables sweeper
+ _should_sweep = false;
+ // If there was enough state change, 'possibly_enable_sweeper()'
+ // sets '_should_sweep' to true
+ possibly_enable_sweeper();
+ // Reset _bytes_changed only if there was enough state change. _bytes_changed
+ // can further increase by calls to 'report_state_change'.
+ if (_should_sweep) {
+ _bytes_changed = 0;
}
}
void NMethodSweeper::sweep_code_cache() {
+ ResourceMark rm;
Ticks sweep_start_counter = Ticks::now();
_flushed_count = 0;
@@ -327,25 +375,10 @@
_marked_for_reclamation_count = 0;
if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _sweep_fractions_left);
- }
-
- if (!CompileBroker::should_compile_new_jobs()) {
- // If we have turned off compilations we might as well do full sweeps
- // in order to reach the clean state faster. Otherwise the sleeping compiler
- // threads will slow down sweeping.
- _sweep_fractions_left = 1;
+ tty->print_cr("### Sweep at %d out of %d", _seen, CodeCache::nof_nmethods());
}
- // We want to visit all nmethods after NmethodSweepFraction
- // invocations so divide the remaining number of nmethods by the
- // remaining number of invocations. This is only an estimate since
- // the number of nmethods changes during the sweep so the final
- // stage must iterate until it there are no more nmethods.
- int todo = (CodeCache::nof_nmethods() - _seen) / _sweep_fractions_left;
int swept_count = 0;
-
-
assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here");
assert(!CodeCache_lock->owned_by_self(), "just checking");
@@ -354,19 +387,9 @@
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
// The last invocation iterates until there are no more nmethods
- while ((swept_count < todo || _sweep_fractions_left == 1) && !_current.end()) {
+ while (!_current.end()) {
swept_count++;
- if (SafepointSynchronize::is_synchronizing()) { // Safepoint request
- if (PrintMethodFlushing && Verbose) {
- tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _sweep_fractions_left);
- }
- MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-
- assert(Thread::current()->is_Java_thread(), "should be java thread");
- JavaThread* thread = (JavaThread*)Thread::current();
- ThreadBlockInVM tbivm(thread);
- thread->java_suspend_self();
- }
+ handle_safepoint_request();
// Since we will give up the CodeCache_lock, always skip ahead
// to the next nmethod. Other blobs can be deleted by other
// threads but nmethods are only reclaimed by the sweeper.
@@ -382,7 +405,7 @@
}
}
- assert(_sweep_fractions_left > 1 || _current.end(), "must have scanned the whole cache");
+ assert(_current.end(), "must have scanned the whole cache");
const Ticks sweep_end_counter = Ticks::now();
const Tickspan sweep_time = sweep_end_counter - sweep_start_counter;
@@ -397,7 +420,6 @@
event.set_starttime(sweep_start_counter);
event.set_endtime(sweep_end_counter);
event.set_sweepIndex(_traversals);
- event.set_sweepFractionIndex(NmethodSweepFraction - _sweep_fractions_left + 1);
event.set_sweptCount(swept_count);
event.set_flushedCount(_flushed_count);
event.set_markedCount(_marked_for_reclamation_count);
@@ -407,15 +429,12 @@
#ifdef ASSERT
if(PrintMethodFlushing) {
- tty->print_cr("### sweeper: sweep time(%d): "
- INT64_FORMAT, _sweep_fractions_left, (jlong)sweep_time.value());
+ tty->print_cr("### sweeper: sweep time(%d): ", (jlong)sweep_time.value());
}
#endif
- if (_sweep_fractions_left == 1) {
- _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep);
- log_sweep("finished");
- }
+ _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep);
+ log_sweep("finished");
// Sweeper is the only case where memory is released, check here if it
// is time to restart the compiler. Only checking if there is a certain
@@ -459,10 +478,12 @@
class NMethodMarker: public StackObj {
private:
- CompilerThread* _thread;
+ CodeCacheSweeperThread* _thread;
public:
NMethodMarker(nmethod* nm) {
- _thread = CompilerThread::current();
+ JavaThread* current = JavaThread::current();
+ assert (current->is_Code_cache_sweeper_thread(), "Must be");
+ _thread = (CodeCacheSweeperThread*)JavaThread::current();
if (!nm->is_zombie() && !nm->is_unloaded()) {
// Only expose live nmethods for scanning
_thread->set_scanned_nmethod(nm);
@@ -473,7 +494,7 @@
}
};
-void NMethodSweeper::release_nmethod(nmethod *nm) {
+void NMethodSweeper::release_nmethod(nmethod* nm) {
// Clean up any CompiledICHolders
{
ResourceMark rm;
@@ -490,7 +511,7 @@
nm->flush();
}
-int NMethodSweeper::process_nmethod(nmethod *nm) {
+int NMethodSweeper::process_nmethod(nmethod* nm) {
assert(!CodeCache_lock->owned_by_self(), "just checking");
int freed_memory = 0;
--- a/hotspot/src/share/vm/runtime/sweeper.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/sweeper.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -49,9 +49,7 @@
// remove the nmethod, all inline caches (IC) that point to the the nmethod must be
// cleared. After that, the nmethod can be evicted from the code cache. Each nmethod's
// state change happens during separate sweeps. It may take at least 3 sweeps before an
-// nmethod's space is freed. Sweeping is currently done by compiler threads between
-// compilations or at least each 5 sec (NmethodSweepCheckInterval) when the code cache
-// is full.
+// nmethod's space is freed.
class NMethodSweeper : public AllStatic {
static long _traversals; // Stack scan count, also sweep ID.
@@ -64,7 +62,6 @@
static int _zombified_count; // Nof. nmethods made zombie in current sweep
static int _marked_for_reclamation_count; // Nof. nmethods marked for reclaim in current sweep
- static volatile int _sweep_fractions_left; // Nof. invocations left until we are completed with this pass
static volatile int _sweep_started; // Flag to control conc sweeper
static volatile bool _should_sweep; // Indicates if we should invoke the sweeper
static volatile int _bytes_changed; // Counts the total nmethod size if the nmethod changed from:
@@ -85,8 +82,12 @@
static int process_nmethod(nmethod *nm);
static void release_nmethod(nmethod* nm);
- static bool sweep_in_progress();
+ static void init_sweeper_log() NOT_DEBUG_RETURN;
+ static bool wait_for_stack_scanning();
static void sweep_code_cache();
+ static void handle_safepoint_request();
+ static void do_stack_scanning();
+ static void possibly_sweep();
public:
static long traversal_count() { return _traversals; }
@@ -106,7 +107,8 @@
#endif
static void mark_active_nmethods(); // Invoked at the end of each safepoint
- static void possibly_sweep(); // Compiler threads call this to sweep
+ static void sweeper_loop();
+ static void notify(int code_blob_type); // Possibly start the sweeper thread.
static int hotness_counter_reset_val();
static void report_state_change(nmethod* nm);
--- a/hotspot/src/share/vm/runtime/thread.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/thread.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -66,6 +66,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp"
+#include "runtime/sweeper.hpp"
#include "runtime/task.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/threadCritical.hpp"
@@ -1553,6 +1554,7 @@
// Remove this ifdef when C1 is ported to the compiler interface.
static void compiler_thread_entry(JavaThread* thread, TRAPS);
+static void sweeper_thread_entry(JavaThread* thread, TRAPS);
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
Thread()
@@ -3172,6 +3174,10 @@
CompileBroker::compiler_thread_loop();
}
+static void sweeper_thread_entry(JavaThread* thread, TRAPS) {
+ NMethodSweeper::sweeper_loop();
+}
+
// Create a CompilerThread
CompilerThread::CompilerThread(CompileQueue* queue,
CompilerCounters* counters)
@@ -3182,7 +3188,6 @@
_queue = queue;
_counters = counters;
_buffer_blob = NULL;
- _scanned_nmethod = NULL;
_compiler = NULL;
#ifndef PRODUCT
@@ -3190,7 +3195,12 @@
#endif
}
-void CompilerThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
+// Create sweeper thread
+CodeCacheSweeperThread::CodeCacheSweeperThread()
+: JavaThread(&sweeper_thread_entry) {
+ _scanned_nmethod = NULL;
+}
+void CodeCacheSweeperThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
JavaThread::oops_do(f, cld_f, cf);
if (_scanned_nmethod != NULL && cf != NULL) {
// Safepoints can occur when the sweeper is scanning an nmethod so
@@ -3607,9 +3617,6 @@
}
}
- // Give os specific code one last chance to start
- os::init_3();
-
create_vm_timer.end();
#ifdef ASSERT
_vm_complete = true;
@@ -3632,7 +3639,7 @@
if (!agent->valid()) {
char buffer[JVM_MAXPATHLEN];
- char ebuf[1024];
+ char ebuf[1024] = "";
const char *name = agent->name();
const char *msg = "Could not find agent library ";
--- a/hotspot/src/share/vm/runtime/thread.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/thread.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -311,6 +311,7 @@
virtual bool is_VM_thread() const { return false; }
virtual bool is_Java_thread() const { return false; }
virtual bool is_Compiler_thread() const { return false; }
+ virtual bool is_Code_cache_sweeper_thread() const { return false; }
virtual bool is_hidden_from_external_view() const { return false; }
virtual bool is_jvmti_agent_thread() const { return false; }
// True iff the thread can perform GC operations at a safepoint.
@@ -1755,6 +1756,27 @@
return (CompilerThread*)this;
}
+// Dedicated thread to sweep the code cache
+class CodeCacheSweeperThread : public JavaThread {
+ nmethod* _scanned_nmethod; // nmethod being scanned by the sweeper
+ public:
+ CodeCacheSweeperThread();
+ // Track the nmethod currently being scanned by the sweeper
+ void set_scanned_nmethod(nmethod* nm) {
+ assert(_scanned_nmethod == NULL || nm == NULL, "should reset to NULL before writing a new value");
+ _scanned_nmethod = nm;
+ }
+
+ // Hide sweeper thread from external view.
+ bool is_hidden_from_external_view() const { return true; }
+
+ bool is_Code_cache_sweeper_thread() const { return true; }
+ // GC support
+ // Apply "f->do_oop" to all root oops in "this".
+ // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames
+ void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+};
+
// A thread used for Compilation.
class CompilerThread : public JavaThread {
friend class VMStructs;
@@ -1767,7 +1789,6 @@
CompileQueue* _queue;
BufferBlob* _buffer_blob;
- nmethod* _scanned_nmethod; // nmethod being scanned by the sweeper
AbstractCompiler* _compiler;
public:
@@ -1801,28 +1822,17 @@
_log = log;
}
- // GC support
- // Apply "f->do_oop" to all root oops in "this".
- // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames
- void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
-
#ifndef PRODUCT
private:
IdealGraphPrinter *_ideal_graph_printer;
public:
- IdealGraphPrinter *ideal_graph_printer() { return _ideal_graph_printer; }
- void set_ideal_graph_printer(IdealGraphPrinter *n) { _ideal_graph_printer = n; }
+ IdealGraphPrinter *ideal_graph_printer() { return _ideal_graph_printer; }
+ void set_ideal_graph_printer(IdealGraphPrinter *n) { _ideal_graph_printer = n; }
#endif
// Get/set the thread's current task
- CompileTask* task() { return _task; }
- void set_task(CompileTask* task) { _task = task; }
-
- // Track the nmethod currently being scanned by the sweeper
- void set_scanned_nmethod(nmethod* nm) {
- assert(_scanned_nmethod == NULL || nm == NULL, "should reset to NULL before writing a new value");
- _scanned_nmethod = nm;
- }
+ CompileTask* task() { return _task; }
+ void set_task(CompileTask* task) { _task = task; }
};
inline CompilerThread* CompilerThread::current() {
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1594,6 +1594,7 @@
declare_type(JvmtiAgentThread, JavaThread) \
declare_type(ServiceThread, JavaThread) \
declare_type(CompilerThread, JavaThread) \
+ declare_type(CodeCacheSweeperThread, JavaThread) \
declare_toplevel_type(OSThread) \
declare_toplevel_type(JavaFrameAnchor) \
\
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -111,6 +111,9 @@
CodeCache::make_marked_nmethods_zombies();
}
+void VM_MarkActiveNMethods::doit() {
+ NMethodSweeper::mark_active_nmethods();
+}
VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id) {
_thread = thread;
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -100,6 +100,7 @@
template(RotateGCLog) \
template(WhiteBoxOperation) \
template(ClassLoaderStatsOperation) \
+ template(MarkActiveNMethods) \
template(PrintCompileQueue) \
template(PrintCodeList) \
template(PrintCodeCache) \
@@ -252,6 +253,13 @@
bool allow_nested_vm_operations() const { return true; }
};
+class VM_MarkActiveNMethods: public VM_Operation {
+ public:
+ VM_MarkActiveNMethods() {}
+ VMOp_Type type() const { return VMOp_MarkActiveNMethods; }
+ void doit();
+ bool allow_nested_vm_operations() const { return true; }
+};
// Deopt helper that can deoptimize frames in threads other than the
// current thread. Only used through Deoptimization::deoptimize_frame.
--- a/hotspot/src/share/vm/services/jmm.h Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/jmm.h Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -143,7 +143,8 @@
JMM_VMGLOBAL_TYPE_UNKNOWN = 0,
JMM_VMGLOBAL_TYPE_JBOOLEAN = 1,
JMM_VMGLOBAL_TYPE_JSTRING = 2,
- JMM_VMGLOBAL_TYPE_JLONG = 3
+ JMM_VMGLOBAL_TYPE_JLONG = 3,
+ JMM_VMGLOBAL_TYPE_JDOUBLE = 4
} jmmVMGlobalType;
typedef enum {
--- a/hotspot/src/share/vm/services/mallocTracker.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/mallocTracker.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -72,7 +72,7 @@
MallocMemorySummary::record_free(size(), flags());
MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader));
- if (tracking_level() == NMT_detail) {
+ if (MemTracker::tracking_level() == NMT_detail) {
MallocSiteTable::deallocation_at(size(), _bucket_idx, _pos_idx);
}
}
@@ -128,36 +128,18 @@
}
// Uses placement global new operator to initialize malloc header
- switch(level) {
- case NMT_off:
- return malloc_base;
- case NMT_minimal: {
- MallocHeader* hdr = ::new (malloc_base) MallocHeader();
- break;
- }
- case NMT_summary: {
- assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT");
- header = ::new (malloc_base) MallocHeader(size, flags);
- break;
- }
- case NMT_detail: {
- assert(size <= MAX_MALLOC_SIZE, "malloc size overrun for NMT");
- header = ::new (malloc_base) MallocHeader(size, flags, stack);
- break;
- }
- default:
- ShouldNotReachHere();
+
+ if (level == NMT_off) {
+ return malloc_base;
}
+
+ header = ::new (malloc_base)MallocHeader(size, flags, stack, level);
memblock = (void*)((char*)malloc_base + sizeof(MallocHeader));
// The alignment check: 8 bytes alignment for 32 bit systems.
// 16 bytes alignment for 64-bit systems.
assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check");
- // Sanity check
- assert(get_memory_tracking_level(memblock) == level,
- "Wrong tracking level");
-
#ifdef ASSERT
if (level > NMT_minimal) {
// Read back
--- a/hotspot/src/share/vm/services/mallocTracker.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/mallocTracker.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -239,68 +239,46 @@
class MallocHeader VALUE_OBJ_CLASS_SPEC {
#ifdef _LP64
- size_t _size : 62;
- size_t _level : 2;
+ size_t _size : 64;
size_t _flags : 8;
size_t _pos_idx : 16;
size_t _bucket_idx: 40;
#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40)
#define MAX_BUCKET_LENGTH ((size_t)(1 << 16))
-#define MAX_MALLOC_SIZE (((size_t)1 << 62) - 1)
#else
- size_t _size : 30;
- size_t _level : 2;
+ size_t _size : 32;
size_t _flags : 8;
size_t _pos_idx : 8;
size_t _bucket_idx: 16;
#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16))
#define MAX_BUCKET_LENGTH ((size_t)(1 << 8))
-// Max malloc size = 1GB - 1 on 32 bit system, such has total 4GB memory
-#define MAX_MALLOC_SIZE ((size_t)(1 << 30) - 1)
#endif // _LP64
public:
- // Summary tracking header
- MallocHeader(size_t size, MEMFLAGS flags) {
- assert(sizeof(MallocHeader) == sizeof(void*) * 2,
- "Wrong header size");
-
- _level = NMT_summary;
- _flags = flags;
- set_size(size);
- MallocMemorySummary::record_malloc(size, flags);
- MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader));
- }
- // Detail tracking header
- MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack) {
+ MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) {
assert(sizeof(MallocHeader) == sizeof(void*) * 2,
"Wrong header size");
- _level = NMT_detail;
+ if (level == NMT_minimal) {
+ return;
+ }
+
_flags = flags;
set_size(size);
- size_t bucket_idx;
- size_t pos_idx;
- if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) {
- assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index");
- assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index");
- _bucket_idx = bucket_idx;
- _pos_idx = pos_idx;
+ if (level == NMT_detail) {
+ size_t bucket_idx;
+ size_t pos_idx;
+ if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) {
+ assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index");
+ assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index");
+ _bucket_idx = bucket_idx;
+ _pos_idx = pos_idx;
+ }
}
+
MallocMemorySummary::record_malloc(size, flags);
MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader));
}
- // Minimal tracking header
- MallocHeader() {
- assert(sizeof(MallocHeader) == sizeof(void*) * 2,
- "Wrong header size");
-
- _level = (unsigned short)NMT_minimal;
- }
-
- inline NMT_TrackingLevel tracking_level() const {
- return (NMT_TrackingLevel)_level;
- }
inline size_t size() const { return _size; }
inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; }
@@ -311,7 +289,6 @@
private:
inline void set_size(size_t size) {
- assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?");
_size = size;
}
bool record_malloc_site(const NativeCallStack& stack, size_t size,
@@ -347,10 +324,6 @@
// Record free on specified memory block
static void* record_free(void* memblock);
- // Get tracking level of specified memory block
- static inline NMT_TrackingLevel get_memory_tracking_level(void* memblock);
-
-
// Offset memory address to header address
static inline void* get_base(void* memblock);
static inline void* get_base(void* memblock, NMT_TrackingLevel level) {
@@ -361,16 +334,12 @@
// Get memory size
static inline size_t get_size(void* memblock) {
MallocHeader* header = malloc_header(memblock);
- assert(header->tracking_level() >= NMT_summary,
- "Wrong tracking level");
return header->size();
}
// Get memory type
static inline MEMFLAGS get_flags(void* memblock) {
MallocHeader* header = malloc_header(memblock);
- assert(header->tracking_level() >= NMT_summary,
- "Wrong tracking level");
return header->flags();
}
@@ -394,7 +363,6 @@
static inline MallocHeader* malloc_header(void *memblock) {
assert(memblock != NULL, "NULL pointer");
MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader));
- assert(header->tracking_level() >= NMT_minimal, "Bad header");
return header;
}
};
--- a/hotspot/src/share/vm/services/mallocTracker.inline.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/mallocTracker.inline.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -28,13 +28,6 @@
#include "services/mallocTracker.hpp"
#include "services/memTracker.hpp"
-inline NMT_TrackingLevel MallocTracker::get_memory_tracking_level(void* memblock) {
- assert(memblock != NULL, "Sanity check");
- if (MemTracker::tracking_level() == NMT_off) return NMT_off;
- MallocHeader* header = malloc_header(memblock);
- return header->tracking_level();
-}
-
inline void* MallocTracker::get_base(void* memblock){
return get_base(memblock, MemTracker::tracking_level());
}
--- a/hotspot/src/share/vm/services/management.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/management.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -1333,7 +1333,7 @@
GrowableArray<oop>* locked_monitors = frame->locked_monitors();
for (j = 0; j < len; j++) {
oop monitor = locked_monitors->at(j);
- assert(monitor != NULL && monitor->is_instance(), "must be a Java object");
+ assert(monitor != NULL, "must be a Java object");
monitors_array->obj_at_put(count, monitor);
depths_array->int_at_put(count, depth);
count++;
@@ -1343,7 +1343,7 @@
GrowableArray<oop>* jni_locked_monitors = stacktrace->jni_locked_monitors();
for (j = 0; j < jni_locked_monitors->length(); j++) {
oop object = jni_locked_monitors->at(j);
- assert(object != NULL && object->is_instance(), "must be a Java object");
+ assert(object != NULL, "must be a Java object");
monitors_array->obj_at_put(count, object);
// Monitor locked via JNI MonitorEnter call doesn't have stack depth info
depths_array->int_at_put(count, -1);
@@ -1572,6 +1572,9 @@
} else if (flag->is_uint64_t()) {
global->value.j = (jlong)flag->get_uint64_t();
global->type = JMM_VMGLOBAL_TYPE_JLONG;
+ } else if (flag->is_double()) {
+ global->value.d = (jdouble)flag->get_double();
+ global->type = JMM_VMGLOBAL_TYPE_JDOUBLE;
} else if (flag->is_size_t()) {
global->value.j = (jlong)flag->get_size_t();
global->type = JMM_VMGLOBAL_TYPE_JLONG;
--- a/hotspot/src/share/vm/services/runtimeService.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/runtimeService.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -38,6 +38,7 @@
PerfCounter* RuntimeService::_total_safepoints = NULL;
PerfCounter* RuntimeService::_safepoint_time_ticks = NULL;
PerfCounter* RuntimeService::_application_time_ticks = NULL;
+double RuntimeService::_last_safepoint_sync_time_sec = 0.0;
void RuntimeService::init() {
// Make sure the VM version is initialized
@@ -96,6 +97,7 @@
// update the time stamp to begin recording safepoint time
_safepoint_timer.update();
+ _last_safepoint_sync_time_sec = 0.0;
if (UsePerfData) {
_total_safepoints->inc();
if (_app_timer.is_updated()) {
@@ -108,6 +110,9 @@
if (UsePerfData) {
_sync_time_ticks->inc(_safepoint_timer.ticks_since_update());
}
+ if (PrintGCApplicationStoppedTime) {
+ _last_safepoint_sync_time_sec = last_safepoint_time_sec();
+ }
}
void RuntimeService::record_safepoint_end() {
@@ -119,8 +124,10 @@
gclog_or_tty->date_stamp(PrintGCDateStamps);
gclog_or_tty->stamp(PrintGCTimeStamps);
gclog_or_tty->print_cr("Total time for which application threads "
- "were stopped: %3.7f seconds",
- last_safepoint_time_sec());
+ "were stopped: %3.7f seconds, "
+ "Stopping threads took: %3.7f seconds",
+ last_safepoint_time_sec(),
+ _last_safepoint_sync_time_sec);
}
// update the time stamp to begin recording app time
--- a/hotspot/src/share/vm/services/runtimeService.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/runtimeService.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -37,6 +37,7 @@
static TimeStamp _safepoint_timer;
static TimeStamp _app_timer;
+ static double _last_safepoint_sync_time_sec;
public:
static void init();
--- a/hotspot/src/share/vm/services/threadService.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/services/threadService.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -597,7 +597,7 @@
GrowableArray<oop>* locked_monitors = frame->locked_monitors();
for (int j = 0; j < len; j++) {
oop monitor = locked_monitors->at(j);
- assert(monitor != NULL && monitor->is_instance(), "must be a Java object");
+ assert(monitor != NULL, "must be a Java object");
if (monitor == object) {
found = true;
break;
--- a/hotspot/src/share/vm/trace/trace.xml Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/trace/trace.xml Mon Nov 17 12:32:27 2014 -0800
@@ -383,7 +383,6 @@
<event id="SweepCodeCache" path="vm/code_sweeper/sweep" label="Sweep Code Cache"
has_thread="true" is_requestable="false" is_constant="false">
<value type="INTEGER" field="sweepIndex" label="Sweep Index" relation="SWEEP_ID"/>
- <value type="USHORT" field="sweepFractionIndex" label="Fraction Index"/>
<value type="UINT" field="sweptCount" label="Methods Swept"/>
<value type="UINT" field="flushedCount" label="Methods Flushed"/>
<value type="UINT" field="markedCount" label="Methods Reclaimed"/>
--- a/hotspot/src/share/vm/utilities/debug.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/utilities/debug.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -256,16 +256,18 @@
static const char* name[] = {
"shared read only space",
"shared read write space",
- "shared miscellaneous data space"
+ "shared miscellaneous data space",
+ "shared miscellaneous code space"
};
static const char* flag[] = {
"SharedReadOnlySize",
"SharedReadWriteSize",
- "SharedMiscDataSize"
+ "SharedMiscDataSize",
+ "SharedMiscCodeSize"
};
warning("\nThe %s is not large enough\n"
- "to preload requested classes. Use -XX:%s=\n"
+ "to preload requested classes. Use -XX:%s=<size>\n"
"to increase the initial size of %s.\n",
name[shared_space], flag[shared_space], name[shared_space]);
exit(2);
--- a/hotspot/src/share/vm/utilities/debug.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/utilities/debug.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -245,7 +245,8 @@
enum SharedSpaceType {
SharedReadOnly,
SharedReadWrite,
- SharedMiscData
+ SharedMiscData,
+ SharedMiscCode
};
void report_out_of_shared_space(SharedSpaceType space_type);
--- a/hotspot/src/share/vm/utilities/dtrace_disabled.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/utilities/dtrace_disabled.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -27,7 +27,7 @@
/* This file contains dummy provider probes needed when compiling a hotspot
* that does not support dtrace probes. This could be because we're building
- * on a system that doesn't suuport dtrace or because we're bulding a variant
+ * on a system that doesn't support dtrace or because we're bulding a variant
* of hotspot (like core) where we do not support dtrace
*/
#if !defined(DTRACE_ENABLED)
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -1048,7 +1048,7 @@
const int badResourceValue = 0xAB; // value used to zap resource area
const int freeBlockPad = 0xBA; // value used to pad freed blocks.
const int uninitBlockPad = 0xF1; // value used to zap newly malloc'd blocks.
-const intptr_t badJNIHandleVal = (intptr_t) CONST64(0xFEFEFEFEFEFEFEFE); // value used to zap jni handle area
+const intptr_t badJNIHandleVal = (intptr_t) UCONST64(0xFEFEFEFEFEFEFEFE); // value used to zap jni handle area
const juint badHeapWordVal = 0xBAADBABE; // value used to zap heap after GC
const juint badMetaWordVal = 0xBAADFADE; // value used to zap metadata heap after GC
const int badCodeHeapNewVal= 0xCC; // value used to zap Code heap at allocation
--- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Mon Nov 17 12:32:27 2014 -0800
@@ -151,11 +151,11 @@
// Constant for jlong (specifying an long long constant is C++ compiler specific)
// Build a 64bit integer constant on with Visual C++
-#define CONST64(x) (x ## i64)
-#define UCONST64(x) ((uint64_t)CONST64(x))
+#define CONST64(x) (x ## i64)
+#define UCONST64(x) (x ## ui64)
-const jlong min_jlong = CONST64(0x8000000000000000);
-const jlong max_jlong = CONST64(0x7fffffffffffffff);
+const jlong min_jlong = (jlong)UCONST64(0x8000000000000000);
+const jlong max_jlong = CONST64(0x7fffffffffffffff);
//----------------------------------------------------------------------------------------------------
// Miscellaneous
--- a/hotspot/src/share/vm/utilities/ostream.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/utilities/ostream.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -76,6 +76,8 @@
const char* format, va_list ap,
bool add_cr,
size_t& result_len) {
+ assert(buflen >= 2, "buffer too small");
+
const char* result;
if (add_cr) buflen--;
if (!strchr(format, '%')) {
@@ -88,14 +90,21 @@
result = va_arg(ap, const char*);
result_len = strlen(result);
if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate
- } else if (vsnprintf(buffer, buflen, format, ap) >= 0) {
+ } else {
+ // Handle truncation:
+ // posix: upon truncation, vsnprintf returns number of bytes which
+ // would have been written (excluding terminating zero) had the buffer
+ // been large enough
+ // windows: upon truncation, vsnprintf returns -1
+ const int written = vsnprintf(buffer, buflen, format, ap);
result = buffer;
- result_len = strlen(result);
- } else {
- DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
- result = buffer;
- result_len = buflen - 1;
- buffer[result_len] = 0;
+ if (written < (int) buflen && written >= 0) {
+ result_len = written;
+ } else {
+ DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
+ result_len = buflen - 1;
+ buffer[result_len] = 0;
+ }
}
if (add_cr) {
if (result != buffer) {
--- a/hotspot/src/share/vm/utilities/vmError.cpp Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon Nov 17 12:32:27 2014 -0800
@@ -975,11 +975,13 @@
// Run error reporting to determine whether or not to report the crash.
if (!transmit_report_done && should_report_bug(first_error->_id)) {
transmit_report_done = true;
- FILE* hs_err = os::open(log.fd(), "r");
+ const int fd2 = ::dup(log.fd());
+ FILE* const hs_err = ::fdopen(fd2, "r");
if (NULL != hs_err) {
ErrorReporter er;
er.call(hs_err, buffer, O_BUFLEN);
}
+ ::fclose(hs_err);
}
if (log.fd() != defaultStream::output_fd()) {
--- a/hotspot/test/TEST.ROOT Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/TEST.ROOT Mon Nov 17 12:32:27 2014 -0800
@@ -30,3 +30,4 @@
keys=cte_test jcmd nmt regression gc stress
groups=TEST.groups [closed/TEST.groups]
+requires.properties=sun.arch.data.model
--- a/hotspot/test/TEST.groups Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/TEST.groups Mon Nov 17 12:32:27 2014 -0800
@@ -87,7 +87,6 @@
runtime/NMT/SummarySanityCheck.java \
runtime/NMT/ThreadedMallocTestType.java \
runtime/NMT/ThreadedVirtualAllocTestType.java \
- runtime/NMT/UnsafeMallocLimit.java \
runtime/NMT/VirtualAllocCommitUncommitRecommit.java \
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.java \
@@ -198,7 +197,8 @@
# Tests that require compact2 API's
#
-needs_compact2 =
+needs_compact2 = \
+ compiler/jsr292/CreatesInterfaceDotEqualsCallInfo.java
# All tests that run on the most minimal configuration: Minimal VM on Compact 1
compact1_minimal = \
@@ -443,6 +443,7 @@
compiler/arraycopy/TestMissingControl.java \
compiler/ciReplay/TestVM_no_comp_level.sh \
compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java \
+ compiler/codecache/CheckSegmentedCodeCache.java \
compiler/codecache/CheckUpperLimit.java \
compiler/codegen/ \
compiler/cpuflags/RestoreMXCSR.java \
@@ -477,9 +478,9 @@
compiler/intrinsics/mathexact/SubExactILoopDependentTest.java \
compiler/intrinsics/stringequals/TestStringEqualsBadLength.java \
compiler/intrinsics/unsafe/UnsafeGetAddressTest.java \
+ compiler/intrinsics/classcast/NullCheckDroppingsTest.java \
compiler/jsr292/ConcurrentClassLoadingTest.java \
compiler/jsr292/CreatesInterfaceDotEqualsCallInfo.java \
- compiler/jsr292/CreatesInterfaceDotEqualsCallInfo.java \
compiler/loopopts/TestLogSum.java \
compiler/macronodes/TestEliminateAllocationPhi.java \
compiler/membars/TestMemBarAcquire.java \
@@ -602,3 +603,14 @@
:hotspot_gc \
:hotspot_runtime \
:hotspot_serviceability
+
+#All tests that depends on nashorn extension.
+#
+needs_nashorn = \
+ compiler/jsr292/CreatesInterfaceDotEqualsCallInfo.java
+
+#All tests that do not depends on nashorn extension
+#
+not_needs_nashorn = \
+ :jdk \
+ -:needs_nashorh
--- a/hotspot/test/compiler/6896617/Test6896617.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/6896617/Test6896617.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,13 +25,20 @@
* @test
* @bug 6896617
* @summary Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() with SSE instructions on x86
+ * @library /testlibrary
* @run main/othervm/timeout=1200 -Xbatch -Xmx256m Test6896617
*
*/
-import java.util.*;
-import java.nio.*;
-import java.nio.charset.*;
+import com.oracle.java.testlibrary.Utils;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+import java.util.Arrays;
+import java.util.Random;
public class Test6896617 {
final static int SIZE = 256;
@@ -54,7 +61,7 @@
sun.nio.cs.ArrayDecoder arrdec = (sun.nio.cs.ArrayDecoder)dec;
// Populate char[] with chars which can be encoded by ISO_8859_1 (<= 0xFF)
- Random rnd = new Random(0);
+ Random rnd = Utils.getRandomInstance();
int maxchar = 0xFF;
char[] a = new char[SIZE];
byte[] b = new byte[SIZE];
--- a/hotspot/test/compiler/7100757/Test7100757.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/7100757/Test7100757.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -26,11 +26,13 @@
* @test
* @bug 7100757
* @summary The BitSet.nextSetBit() produces incorrect result in 32bit VM on Sparc
- *
+ * @library /testlibrary
* @run main/timeout=300 Test7100757
*/
-import java.util.*;
+import com.oracle.java.testlibrary.Utils;
+import java.util.BitSet;
+import java.util.Random;
public class Test7100757 {
@@ -39,7 +41,7 @@
public static void main(String[] args) {
BitSet bs = new BitSet(NBITS);
- Random rnd = new Random();
+ Random rnd = Utils.getRandomInstance();
long[] ra = new long[(NBITS+63)/64];
for(int l=0; l < 5000000; l++) {
--- a/hotspot/test/compiler/7177917/Test7177917.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/7177917/Test7177917.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -26,13 +26,14 @@
* Micro-benchmark for Math.pow() and Math.exp()
*/
-import java.util.*;
+import com.oracle.java.testlibrary.Utils;
+import java.util.Random;
public class Test7177917 {
static double d;
- static Random r = new Random(0);
+ static final Random R = Utils.getRandomInstance();
static long m_pow(double[][] values) {
double res = 0;
@@ -59,10 +60,10 @@
static double[][] pow_values(int nb) {
double[][] res = new double[nb][2];
for (int i = 0; i < nb; i++) {
- double ylogx = (1 + (r.nextDouble() * 2045)) - 1023; // 2045 rather than 2046 as a safety margin
- double x = Math.abs(Double.longBitsToDouble(r.nextLong()));
+ double ylogx = (1 + (R.nextDouble() * 2045)) - 1023; // 2045 rather than 2046 as a safety margin
+ double x = Math.abs(Double.longBitsToDouble(R.nextLong()));
while (x != x) {
- x = Math.abs(Double.longBitsToDouble(r.nextLong()));
+ x = Math.abs(Double.longBitsToDouble(R.nextLong()));
}
double logx = Math.log(x) / Math.log(2);
double y = ylogx / logx;
@@ -76,7 +77,7 @@
static double[] exp_values(int nb) {
double[] res = new double[nb];
for (int i = 0; i < nb; i++) {
- double ylogx = (1 + (r.nextDouble() * 2045)) - 1023; // 2045 rather than 2046 as a safety margin
+ double ylogx = (1 + (R.nextDouble() * 2045)) - 1023; // 2045 rather than 2046 as a safety margin
double x = Math.E;
double logx = Math.log(x) / Math.log(2);
double y = ylogx / logx;
--- a/hotspot/test/compiler/7184394/TestAESBase.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/7184394/TestAESBase.java Mon Nov 17 12:32:27 2014 -0800
@@ -26,15 +26,13 @@
* @author Tom Deneau
*/
+import com.oracle.java.testlibrary.Utils;
+import java.security.AlgorithmParameters;
+import java.util.Random;
import javax.crypto.Cipher;
-import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
-import java.security.AlgorithmParameters;
-
-import java.util.Random;
-import java.util.Arrays;
abstract public class TestAESBase {
int msgSize = Integer.getInteger("msgSize", 646);
@@ -59,7 +57,7 @@
byte[] expectedEncode;
byte[] decode;
byte[] expectedDecode;
- Random random = new Random(0);
+ final Random random = Utils.getRandomInstance();
Cipher cipher;
Cipher dCipher;
AlgorithmParameters algParams;
--- a/hotspot/test/compiler/7184394/TestAESMain.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/7184394/TestAESMain.java Mon Nov 17 12:32:27 2014 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 7184394
* @summary add intrinsics to use AES instructions
+ * @library /testlibrary
*
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC -DencInputOffset=1 TestAESMain
--- a/hotspot/test/compiler/8005956/PolynomialRoot.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/8005956/PolynomialRoot.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,4 +1,3 @@
-//package com.polytechnik.utils;
/*
* (C) Vladislav Malyshkin 2010
* This file is under GPL version 3.
@@ -14,10 +13,14 @@
* @test
* @bug 8005956
* @summary C2: assert(!def_outside->member(r)) failed: Use of external LRG overlaps the same LRG defined in this block
-*
+* @library /testlibrary
* @run main/timeout=300 PolynomialRoot
*/
+import com.oracle.java.testlibrary.Utils;
+import java.util.Arrays;
+import java.util.Random;
+
public class PolynomialRoot {
@@ -57,7 +60,7 @@
public static int root4(final double [] p,final double [] re_root,final double [] im_root)
{
- if(PRINT_DEBUG) System.err.println("=====================root4:p="+java.util.Arrays.toString(p));
+ if (PRINT_DEBUG) { System.err.println("=====================root4:p=" + Arrays.toString(p)); }
final double vs=p[4];
if(PRINT_DEBUG) System.err.println("p[4]="+p[4]);
if(!(Math.abs(vs)>EPS))
@@ -367,7 +370,7 @@
- static void setRandomP(final double [] p,final int n,java.util.Random r)
+ static void setRandomP(final double [] p, final int n, Random r)
{
if(r.nextDouble()<0.1)
{
@@ -465,7 +468,7 @@
static void testRoots(final int n,
final int n_tests,
- final java.util.Random rn,
+ final Random rn,
final double eps)
{
final double [] p=new double [n+1];
@@ -763,7 +766,7 @@
final long t0=System.currentTimeMillis();
final double eps=1e-6;
//checkRoots();
- final java.util.Random r=new java.util.Random(-1381923);
+ final Random r = Utils.getRandomInstance();
printSpecialValues();
final int n_tests=100000;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/EliminateAutoBox/UnsignedLoads.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,63 @@
+/*
+ * 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. 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.
+ */
+
+/*
+ * @test
+ * @library /testlibrary
+ * @run main/othervm -Xbatch -XX:+EliminateAutoBox
+ * -XX:CompileOnly=::valueOf,::byteValue,::shortValue,::testUnsignedByte,::testUnsignedShort
+ * UnsignedLoads
+ */
+import static com.oracle.java.testlibrary.Asserts.assertEQ;
+
+public class UnsignedLoads {
+ public static int testUnsignedByte() {
+ byte[] bytes = new byte[] {-1};
+ int res = 0;
+ for (int i = 0; i < 100000; i++) {
+ for (Byte b : bytes) {
+ res = b & 0xff;
+ }
+ }
+ return res;
+ }
+
+ public static int testUnsignedShort() {
+ int res = 0;
+ short[] shorts = new short[] {-1};
+ for (int i = 0; i < 100000; i++) {
+ for (Short s : shorts) {
+ res = s & 0xffff;
+ }
+ }
+ return res;
+ }
+
+ public static void main(String[] args) {
+ assertEQ(testUnsignedByte(), 255);
+ assertEQ(testUnsignedShort(), 65535);
+ System.out.println("TEST PASSED");
+ }
+}
--- a/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java Mon Nov 17 12:32:27 2014 -0800
@@ -22,15 +22,20 @@
*/
import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
/*
* @test CheckSegmentedCodeCache
* @bug 8015774
+ * @library /testlibrary /testlibrary/whitebox
* @summary "Checks VM options related to the segmented code cache"
- * @library /testlibrary
- * @run main/othervm CheckSegmentedCodeCache
+ * @build CheckSegmentedCodeCache
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI CheckSegmentedCodeCache
*/
public class CheckSegmentedCodeCache {
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
// Code heap names
private static final String NON_METHOD = "CodeHeap 'non-nmethods'";
private static final String PROFILED = "CodeHeap 'profiled nmethods'";
@@ -133,8 +138,11 @@
failsWith(pb, "Invalid code heap sizes");
// Fails if not enough space for VM internal code
+ long minUseSpace = WHITE_BOX.getUintxVMFlag("CodeCacheMinimumUseSpace");
+ // minimum size: CodeCacheMinimumUseSpace DEBUG_ONLY(* 3)
+ long minSize = (Platform.isDebugBuild() ? 3 : 1) * minUseSpace;
pb = ProcessTools.createJavaProcessBuilder("-XX:+SegmentedCodeCache",
- "-XX:ReservedCodeCacheSize=1700K",
+ "-XX:ReservedCodeCacheSize=" + minSize,
"-XX:InitialCodeCacheSize=100K");
failsWith(pb, "Not enough space in non-nmethod code heap to run VM");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/debug/TraceIterativeGVN.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,39 @@
+/*
+ * 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. 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.
+ */
+
+/*
+ * @test
+ * @run main/othervm -Xbatch -XX:-TieredCompilation
+ * -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceIterativeGVN
+ * TraceIterativeGVN
+ */
+public class TraceIterativeGVN {
+ public static void main(String[] args) {
+ for (int i = 0; i < 100_000; i++) {
+ Byte.valueOf((byte)0);
+ }
+ System.out.println("TEST PASSED");
+ }
+}
--- a/hotspot/test/compiler/exceptions/CatchInlineExceptions.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/exceptions/CatchInlineExceptions.java Mon Nov 17 12:32:27 2014 -0800
@@ -70,7 +70,7 @@
if (counter1 != 0) {
throw new RuntimeException("Failed: counter1(" + counter1 + ") != 0");
}
- if (counter2 != counter) {
+ if (counter2 != counter0) {
throw new RuntimeException("Failed: counter2(" + counter2 + ") != counter0(" + counter0 + ")");
}
if (counter2 != counter) {
--- a/hotspot/test/compiler/intrinsics/bmi/BMITestRunner.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/BMITestRunner.java Mon Nov 17 12:32:27 2014 -0800
@@ -22,13 +22,17 @@
*
*/
-import java.util.*;
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.Utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
-import java.nio.charset.StandardCharsets;
-
-import com.oracle.java.testlibrary.*;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
/**
* Test runner that invokes all methods implemented by particular Expr
@@ -69,7 +73,7 @@
String... additionalVMOpts)
throws Throwable {
- int seed = new Random().nextInt();
+ int seed = Utils.getRandomInstance().nextInt();
int iterations = DEFAULT_ITERATIONS_COUNT;
for (String testOption : testOpts) {
@@ -81,8 +85,6 @@
}
}
- System.out.println("Running test with seed: " + seed);
-
OutputAnalyzer intOutput = runTest(expr, VMMode.INT,
additionalVMOpts,
seed, iterations);
@@ -139,9 +141,9 @@
Collections.addAll(vmOpts, new String[] {
"-XX:+DisplayVMOutputToStderr",
+ "-D" + Utils.SEED_PROPERTY_NAME + "=" + seed,
Executor.class.getName(),
expr.getName(),
- new Integer(seed).toString(),
new Integer(iterations).toString()
});
@@ -179,16 +181,15 @@
public static class Executor {
/**
- * Usage: BMITestRunner$Executor <ExprClassName> <seed> <iterations>
+ * Usage: BMITestRunner$Executor <ExprClassName> <iterations>
*/
public static void main(String args[]) throws Exception {
@SuppressWarnings("unchecked")
Class<? extends Expr> exprClass =
(Class<? extends Expr>)Class.forName(args[0]);
Expr expr = exprClass.getConstructor().newInstance();
- Random rng = new Random(Integer.valueOf(args[1]));
- int iterations = Integer.valueOf(args[2]);
- runTests(expr, iterations, rng);
+ int iterations = Integer.valueOf(args[1]);
+ runTests(expr, iterations, Utils.getRandomInstance());
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. "+
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(AndnIExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(AndnICommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(AndnLExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(AndnLCommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(BlsiIExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(BlsiICommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(BlsiLExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(BlsiLCommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(BlsmskIExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(BlsmskICommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(BlsmskLExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(BlsmskLCommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(BlsrIExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(BlsrICommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,14 +41,14 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(BlsrLExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
BMITestRunner.runTests(BlsrLCommutativeExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseBMI1Instructions");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,12 +41,11 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("lzcnt")) {
- System.out.println("CPU does not support lzcnt feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support lzcnt feature.");
}
BMITestRunner.runTests(LzcntIExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseCountLeadingZerosInstruction");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,12 +41,11 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("lzcnt")) {
- System.out.println("CPU does not support lzcnt feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support lzcnt feature.");
}
BMITestRunner.runTests(LzcntLExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseCountLeadingZerosInstruction");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,12 +41,11 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(TzcntIExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseCountTrailingZerosInstruction");
}
--- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java Mon Nov 17 12:32:27 2014 -0800
@@ -41,12 +41,11 @@
public static void main(String args[]) throws Throwable {
if (!CPUInfo.hasFeature("bmi1")) {
- System.out.println("CPU does not support bmi1 feature. " +
- "Test skipped.");
- return;
+ System.out.println("INFO: CPU does not support bmi1 feature.");
}
BMITestRunner.runTests(TzcntLExpr.class, args,
+ "-XX:+IgnoreUnrecognizedVMOptions",
"-XX:+UseCountTrailingZerosInstruction");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,346 @@
+/*
+ * 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 NullCheckDroppingsTest
+ * @bug 8054492
+ * @summary "Casting can result in redundant null checks in generated code"
+ * @library /testlibrary /testlibrary/whitebox /testlibrary/com/oracle/java/testlibrary
+ * @build NullCheckDroppingsTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -Xmixed -XX:-BackgroundCompilation -XX:-TieredCompilation -XX:CompileThreshold=1000
+ * -XX:CompileCommand=exclude,NullCheckDroppingsTest::runTest NullCheckDroppingsTest
+ */
+
+import sun.hotspot.WhiteBox;
+import sun.hotspot.code.NMethod;
+import com.oracle.java.testlibrary.Platform;
+
+import java.lang.reflect.Method;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.function.BiFunction;
+
+public class NullCheckDroppingsTest {
+
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+ static final BiFunction<Class, Object, Object> fCast = (c, o) -> c.cast(o);
+
+ static final MethodHandle SET_SSINK;
+ static final MethodHandle MH_CAST;
+
+ static {
+ try {
+ SET_SSINK = MethodHandles.lookup().findSetter(NullCheckDroppingsTest.class, "ssink", String.class);
+ MH_CAST = MethodHandles.lookup().findVirtual(Class.class,
+ "cast",
+ MethodType.methodType(Object.class, Object.class));
+ }
+ catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+ static volatile String svalue = "A";
+ static volatile String snull = null;
+ static volatile Integer iobj = new Integer(0);
+ static volatile int[] arr = new int[2];
+ static volatile Class objClass = String.class;
+ static volatile Class nullClass = null;
+
+ String ssink;
+ Integer isink;
+ int[] asink;
+
+ public static void main(String[] args) throws Exception {
+
+ // Only test C2 in Server VM
+ if (!Platform.isServer()) {
+ return;
+ }
+ // Make sure background compilation is disabled
+ if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
+ throw new AssertionError("Background compilation enabled");
+ }
+ // Make sure Tiered compilation is disabled
+ if (WHITE_BOX.getBooleanVMFlag("TieredCompilation")) {
+ throw new AssertionError("Tiered compilation enabled");
+ }
+
+ Method methodClassCast = NullCheckDroppingsTest.class.getDeclaredMethod("testClassCast", String.class);
+ Method methodMHCast = NullCheckDroppingsTest.class.getDeclaredMethod("testMHCast", String.class);
+ Method methodMHSetter = NullCheckDroppingsTest.class.getDeclaredMethod("testMHSetter", String.class);
+ Method methodFunction = NullCheckDroppingsTest.class.getDeclaredMethod("testFunction", String.class);
+
+ NullCheckDroppingsTest t = new NullCheckDroppingsTest();
+ t.runTest(methodClassCast, false);
+ t.runTest(methodMHCast, false);
+ t.runTest(methodMHSetter, false);
+ t.runTest(methodFunction, false);
+
+ // Edge cases
+ Method methodClassCastNull = NullCheckDroppingsTest.class.getDeclaredMethod("testClassCastNull", String.class);
+ Method methodNullClassCast = NullCheckDroppingsTest.class.getDeclaredMethod("testNullClassCast", String.class);
+ Method methodClassCastObj = NullCheckDroppingsTest.class.getDeclaredMethod("testClassCastObj", Object.class);
+ Method methodObjClassCast = NullCheckDroppingsTest.class.getDeclaredMethod("testObjClassCast", String.class);
+ Method methodVarClassCast = NullCheckDroppingsTest.class.getDeclaredMethod("testVarClassCast", String.class);
+ Method methodClassCastInt = NullCheckDroppingsTest.class.getDeclaredMethod("testClassCastInt", Object.class);
+ Method methodIntClassCast = NullCheckDroppingsTest.class.getDeclaredMethod("testIntClassCast", Object.class);
+ Method methodClassCastint = NullCheckDroppingsTest.class.getDeclaredMethod("testClassCastint", Object.class);
+ Method methodintClassCast = NullCheckDroppingsTest.class.getDeclaredMethod("testintClassCast", Object.class);
+ Method methodClassCastPrim = NullCheckDroppingsTest.class.getDeclaredMethod("testClassCastPrim", Object.class);
+ Method methodPrimClassCast = NullCheckDroppingsTest.class.getDeclaredMethod("testPrimClassCast", Object.class);
+
+ t.runTest(methodClassCastNull, false);
+ t.runTest(methodNullClassCast, false);
+ t.runTest(methodClassCastObj, false);
+ t.runTest(methodObjClassCast, true);
+ t.runTest(methodVarClassCast, true);
+ t.runTest(methodClassCastInt, false);
+ t.runTest(methodIntClassCast, true);
+ t.runTest(methodClassCastint, false);
+ t.runTest(methodintClassCast, false);
+ t.runTest(methodClassCastPrim, false);
+ t.runTest(methodPrimClassCast, true);
+ }
+
+ void testClassCast(String s) {
+ try {
+ ssink = String.class.cast(s);
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testClassCastNull(String s) {
+ try {
+ ssink = String.class.cast(null);
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testNullClassCast(String s) {
+ try {
+ ssink = (String)nullClass.cast(s);
+ throw new AssertionError("NullPointerException is not thrown");
+ } catch (NullPointerException t) {
+ // Ignore NullPointerException
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testClassCastObj(Object s) {
+ try {
+ ssink = String.class.cast(s);
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testObjClassCast(String s) {
+ try {
+ ssink = (String)objClass.cast(s);
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testVarClassCast(String s) {
+ Class cl = (s == null) ? null : String.class;
+ try {
+ ssink = (String)cl.cast(svalue);
+ if (s == null) {
+ throw new AssertionError("NullPointerException is not thrown");
+ }
+ } catch (NullPointerException t) {
+ // Ignore NullPointerException
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testClassCastInt(Object s) {
+ try {
+ ssink = String.class.cast(iobj);
+ throw new AssertionError("ClassCastException is not thrown");
+ } catch (ClassCastException t) {
+ // Ignore ClassCastException: Cannot cast java.lang.Integer to java.lang.String
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testIntClassCast(Object s) {
+ try {
+ isink = Integer.class.cast(s);
+ if (s != null) {
+ throw new AssertionError("ClassCastException is not thrown");
+ }
+ } catch (ClassCastException t) {
+ // Ignore ClassCastException: Cannot cast java.lang.String to java.lang.Integer
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testClassCastint(Object s) {
+ try {
+ ssink = String.class.cast(45);
+ throw new AssertionError("ClassCastException is not thrown");
+ } catch (ClassCastException t) {
+ // Ignore ClassCastException: Cannot cast java.lang.Integer to java.lang.String
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testintClassCast(Object s) {
+ try {
+ isink = int.class.cast(s);
+ if (s != null) {
+ throw new AssertionError("ClassCastException is not thrown");
+ }
+ } catch (ClassCastException t) {
+ // Ignore ClassCastException: Cannot cast java.lang.String to java.lang.Integer
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testClassCastPrim(Object s) {
+ try {
+ ssink = String.class.cast(arr);
+ throw new AssertionError("ClassCastException is not thrown");
+ } catch (ClassCastException t) {
+ // Ignore ClassCastException: Cannot cast [I to java.lang.String
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testPrimClassCast(Object s) {
+ try {
+ asink = int[].class.cast(s);
+ if (s != null) {
+ throw new AssertionError("ClassCastException is not thrown");
+ }
+ } catch (ClassCastException t) {
+ // Ignore ClassCastException: Cannot cast java.lang.String to [I
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testMHCast(String s) {
+ try {
+ ssink = (String) (Object) MH_CAST.invokeExact(String.class, (Object) s);
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testMHSetter(String s) {
+ try {
+ SET_SSINK.invokeExact(this, s);
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void testFunction(String s) {
+ try {
+ ssink = (String) fCast.apply(String.class, s);
+ } catch (Throwable t) {
+ throw new Error(t);
+ }
+ }
+
+ void runTest(Method method, boolean deopt) {
+ if (method == null) {
+ throw new AssertionError("method was not found");
+ }
+ // Ensure method is compiled
+ WHITE_BOX.testSetDontInlineMethod(method, true);
+ for (int i = 0; i < 3000; i++) {
+ try {
+ method.invoke(this, svalue);
+ } catch (Exception e) {
+ throw new Error("Unexpected exception: ", e);
+ }
+ }
+ NMethod nm = getNMethod(method);
+
+ // Passing null should cause a de-optimization
+ // if method is compiled with a null-check.
+ try {
+ method.invoke(this, snull);
+ } catch (Exception e) {
+ throw new Error("Unexpected exception: ", e);
+ }
+ checkDeoptimization(method, nm, deopt);
+ }
+
+ static NMethod getNMethod(Method test) {
+ // Because background compilation is disabled, method should now be compiled
+ if (!WHITE_BOX.isMethodCompiled(test)) {
+ throw new AssertionError(test + " not compiled");
+ }
+
+ NMethod nm = NMethod.get(test, false); // not OSR nmethod
+ if (nm == null) {
+ throw new AssertionError(test + " missing nmethod?");
+ }
+ if (nm.comp_level != 4) {
+ throw new AssertionError(test + " compiled by not C2: " + nm);
+ }
+ return nm;
+ }
+
+ static void checkDeoptimization(Method method, NMethod nmOrig, boolean deopt) {
+ // Check deoptimization event (intrinsic Class.cast() works).
+ if (WHITE_BOX.isMethodCompiled(method) == deopt) {
+ throw new AssertionError(method + " was" + (deopt ? " not" : "") + " deoptimized");
+ }
+ if (deopt) {
+ return;
+ }
+ // Ensure no recompilation when no deoptimization is expected.
+ NMethod nm = NMethod.get(method, false); // not OSR nmethod
+ if (nm == null) {
+ throw new AssertionError(method + " missing nmethod?");
+ }
+ if (nm.comp_level != 4) {
+ throw new AssertionError(method + " compiled by not C2: " + nm);
+ }
+ if (nm.compile_id != nmOrig.compile_id) {
+ throw new AssertionError(method + " was recompiled: old nmethod=" + nmOrig + ", new nmethod=" + nm);
+ }
+ }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8024924
* @summary Test constant addExact
+ * @library /testlibrary
* @compile AddExactIConstantTest.java Verify.java
* @run main AddExactIConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8024924
* @summary Test non constant addExact
+ * @library /testlibrary
* @compile AddExactILoadTest.java Verify.java
* @run main AddExactILoadTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8024924
* @summary Test non constant addExact
+ * @library /testlibrary
* @compile AddExactILoopDependentTest.java Verify.java
* @run main AddExactILoopDependentTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8024924
* @summary Test non constant addExact
+ * @library /testlibrary
* @compile AddExactINonConstantTest.java Verify.java
* @run main AddExactINonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,11 +25,15 @@
* @test
* @bug 8025657
* @summary Test repeating addExact
+ * @library /testlibrary
* @compile AddExactIRepeatTest.java Verify.java
* @run main AddExactIRepeatTest
*
*/
+import com.oracle.java.testlibrary.Utils;
+import java.util.Random;
+
public class AddExactIRepeatTest {
public static void main(String[] args) {
runTest(new Verify.AddExactI());
@@ -44,7 +48,7 @@
}
public static void runTest(Verify.BinaryMethod method) {
- java.util.Random rnd = new java.util.Random();
+ Random rnd = Utils.getRandomInstance();
for (int i = 0; i < 50000; ++i) {
int x = Integer.MAX_VALUE - 10;
int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
--- a/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test constant addExact
+ * @library /testlibrary
* @compile AddExactLConstantTest.java Verify.java
* @run main AddExactLConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test non constant addExact
+ * @library /testlibrary
* @compile AddExactLNonConstantTest.java Verify.java
* @run main AddExactLNonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test decrementExact
+ * @library /testlibrary
* @compile DecExactITest.java Verify.java
* @run main DecExactITest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test decrementExact
+ * @library /testlibrary
* @compile DecExactLTest.java Verify.java
* @run main DecExactLTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test incrementExact
+ * @library /testlibrary
* @compile IncExactITest.java Verify.java
* @run main IncExactITest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test incrementExact
+ * @library /testlibrary
* @compile IncExactLTest.java Verify.java
* @run main IncExactLTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test constant multiplyExact
+ * @library /testlibrary
* @compile MulExactIConstantTest.java Verify.java
* @run main MulExactIConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test multiplyExact
+ * @library /testlibrary
* @compile MulExactILoadTest.java Verify.java
* @run main MulExactILoadTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test loop dependent multiplyExact
+ * @library /testlibrary
* @compile MulExactILoopDependentTest.java Verify.java
* @run main MulExactILoopDependentTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test non constant multiplyExact
+ * @library /testlibrary
* @compile MulExactINonConstantTest.java Verify.java
* @run main MulExactINonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,11 +25,15 @@
* @test
* @bug 8026844
* @summary Test repeating multiplyExact
+ * @library /testlibrary
* @compile MulExactIRepeatTest.java Verify.java
* @run main MulExactIRepeatTest
*
*/
+import com.oracle.java.testlibrary.Utils;
+import java.util.Random;
+
public class MulExactIRepeatTest {
public static void main(String[] args) {
runTest(new Verify.MulExactI());
@@ -44,7 +48,7 @@
}
public static void runTest(Verify.BinaryMethod method) {
- java.util.Random rnd = new java.util.Random();
+ Random rnd = Utils.getRandomInstance();
for (int i = 0; i < 50000; ++i) {
int x = Integer.MAX_VALUE - 10;
int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
--- a/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test constant mulExact
+ * @library /testlibrary
* @compile MulExactLConstantTest.java Verify.java
* @run main MulExactLConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test non constant mulExact
+ * @library /testlibrary
* @compile MulExactLNonConstantTest.java Verify.java
* @run main MulExactLNonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test constant negExact
+ * @library /testlibrary
* @compile NegExactIConstantTest.java Verify.java
* @run main NegExactIConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test negExact
+ * @library /testlibrary
* @compile NegExactILoadTest.java Verify.java
* @run main NegExactILoadTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test negExact loop dependent
+ * @library /testlibrary
* @compile NegExactILoopDependentTest.java Verify.java
* @run main NegExactILoopDependentTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test non constant negExact
+ * @library /testlibrary
* @compile NegExactINonConstantTest.java Verify.java
* @run main NegExactINonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test constant negExact
+ * @library /testlibrary
* @compile NegExactLConstantTest.java Verify.java
* @run main NegExactLConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test constant negExact
+ * @library /testlibrary
* @compile NegExactLNonConstantTest.java Verify.java
* @run main NegExactLNonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test subtractExact as condition
+ * @library /testlibrary
* @compile SubExactICondTest.java Verify.java
* @run main SubExactICondTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test constant subtractExact
+ * @library /testlibrary
* @compile SubExactIConstantTest.java Verify.java
* @run main SubExactIConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test non constant subtractExact
+ * @library /testlibrary
* @compile SubExactILoadTest.java Verify.java
* @run main SubExactILoadTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test non constant subtractExact
+ * @library /testlibrary
* @compile SubExactILoopDependentTest.java Verify.java
* @run main SubExactILoopDependentTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,6 +25,7 @@
* @test
* @bug 8026844
* @summary Test non constant subtractExact
+ * @library /testlibrary
* @compile SubExactINonConstantTest.java Verify.java
* @run main SubExactINonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,12 +25,14 @@
* @test
* @bug 8026844
* @summary Test repeating subtractExact
+ * @library /testlibrary
* @compile SubExactIRepeatTest.java Verify.java
* @run main SubExactIRepeatTest
*
*/
-import java.lang.ArithmeticException;
+import com.oracle.java.testlibrary.Utils;
+import java.util.Random;
public class SubExactIRepeatTest {
public static void main(String[] args) {
@@ -46,7 +48,7 @@
}
public static void runTest(Verify.BinaryMethod method) {
- java.util.Random rnd = new java.util.Random();
+ Random rnd = Utils.getRandomInstance();
for (int i = 0; i < 50000; ++i) {
int x = Integer.MIN_VALUE + 10;
int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,6 +26,7 @@
* @bug 8026844
* @bug 8027353
* @summary Test constant subtractExact
+ * @library /testlibrary
* @compile SubExactLConstantTest.java Verify.java
* @run main SubExactLConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,6 +26,7 @@
* @bug 8026844
* @bug 8027353
* @summary Test non constant subtractExact
+ * @library /testlibrary
* @compile SubExactLNonConstantTest.java Verify.java
* @run main SubExactLNonConstantTest
*
--- a/hotspot/test/compiler/intrinsics/mathexact/Verify.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/intrinsics/mathexact/Verify.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -21,6 +21,13 @@
* questions.
*/
+import com.oracle.java.testlibrary.Utils;
+import java.util.Random;
+
+/**
+ * The class depends on Utils class from testlibrary package.
+ * It uses factory method that obtains random generator.
+ */
public class Verify {
public static String throwWord(boolean threw) {
return (threw ? "threw" : "didn't throw");
@@ -134,7 +141,7 @@
public static class LoadTest {
- public static java.util.Random rnd = new java.util.Random();
+ public static Random rnd = Utils.getRandomInstance();
public static int[] values = new int[256];
public static void init() {
@@ -159,7 +166,7 @@
}
public static class NonConstantTest {
- public static java.util.Random rnd = new java.util.Random();
+ public static Random rnd = Utils.getRandomInstance();
public static int[] values = new int[] { Integer.MAX_VALUE, Integer.MIN_VALUE };
public static void verify(BinaryMethod method) {
@@ -180,7 +187,7 @@
public static class NonConstantLongTest {
public static long[] values = { Long.MIN_VALUE, Long.MAX_VALUE, 0, Long.MAX_VALUE - 1831 };
- public static java.util.Random rnd = new java.util.Random();
+ public static Random rnd = Utils.getRandomInstance();
public static void verify(BinaryLongMethod method) {
for (int i = 0; i < 50000; ++i) {
@@ -199,7 +206,7 @@
}
public static class LoopDependentTest {
- public static java.util.Random rnd = new java.util.Random();
+ public static Random rnd = Utils.getRandomInstance();
public static void verify(BinaryMethod method) {
int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
--- a/hotspot/test/compiler/jsr292/ConcurrentClassLoadingTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/jsr292/ConcurrentClassLoadingTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,18 +25,21 @@
* @test
* @bug 8022595
* @summary JSR292: deadlock during class loading of MethodHandles, MethodHandleImpl & MethodHandleNatives
- *
+ * @library /testlibrary
* @run main/othervm ConcurrentClassLoadingTest
*/
-import java.util.*;
+import com.oracle.java.testlibrary.Utils;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class ConcurrentClassLoadingTest {
int numThreads = 0;
- long seed = 0;
CyclicBarrier l;
- Random rand;
+ private static final Random rand = Utils.getRandomInstance();
public static void main(String[] args) throws Throwable {
ConcurrentClassLoadingTest test = new ConcurrentClassLoadingTest();
@@ -49,9 +52,6 @@
while (i < args.length) {
String flag = args[i];
switch(flag) {
- case "-seed":
- seed = Long.parseLong(args[++i]);
- break;
case "-numThreads":
numThreads = Integer.parseInt(args[++i]);
break;
@@ -67,15 +67,9 @@
numThreads = Runtime.getRuntime().availableProcessors();
}
- if (seed == 0) {
- seed = (new Random()).nextLong();
- }
- rand = new Random(seed);
-
l = new CyclicBarrier(numThreads + 1);
System.out.printf("Threads: %d\n", numThreads);
- System.out.printf("Seed: %d\n", seed);
}
final List<Loader> loaders = new ArrayList<>();
@@ -90,7 +84,9 @@
System.out.printf("Thread #%d:\n", t);
for (int i = 0; i < count; i++) {
- if (c.size() == 0) break;
+ if (c.isEmpty()) {
+ break;
+ }
int k = rand.nextInt(c.size());
String elem = c.remove(k);
--- a/hotspot/test/compiler/startup/SmallCodeCacheStartup.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/startup/SmallCodeCacheStartup.java Mon Nov 17 12:32:27 2014 -0800
@@ -27,10 +27,20 @@
* @summary Test ensures that there is no crash if there is not enough ReservedCodeacacheSize
* to initialize all compiler threads. The option -Xcomp gives the VM more time to
* to trigger the old bug.
- * @run main/othervm -XX:ReservedCodeCacheSize=3m -XX:CICompilerCount=64 -Xcomp SmallCodeCacheStartup
+ * @library /testlibrary
*/
+import com.oracle.java.testlibrary.*;
+
public class SmallCodeCacheStartup {
public static void main(String[] args) throws Exception {
+ try {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:ReservedCodeCacheSize=3m",
+ "-XX:CICompilerCount=64",
+ "-Xcomp",
+ "SmallCodeCacheStartup");
+ pb.start();
+ } catch (VirtualMachineError e) {}
+
System.out.println("TEST PASSED");
}
}
--- a/hotspot/test/compiler/types/correctness/OffTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/types/correctness/OffTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -36,10 +36,10 @@
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.Utils;
+import java.util.Random;
import scenarios.ProfilingType;
-import java.util.Random;
-
public class OffTest {
private static final String[] OPTIONS = {
"-Xbootclasspath/a:.",
@@ -63,14 +63,7 @@
private static final int PROFILING_TYPE_INDEX = OPTIONS.length - 1;
private static final int TYPE_PROFILE_INDEX = OPTIONS.length - 4;
private static final int USE_TYPE_SPECULATION_INDEX = OPTIONS.length - 3;
- private static final Random RNG;
-
- static {
- String str = System.getProperty("seed");
- long seed = str != null ? Long.parseLong(str) : new Random().nextLong();
- RNG = new Random(seed);
- System.out.printf("-Dseed=%d%n", seed);
- }
+ private static final Random RNG = Utils.getRandomInstance();
public static void main(String[] args) throws Exception {
int count = DEFAULT_COUNT;
--- a/hotspot/test/compiler/unsafe/UnsafeRaw.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/unsafe/UnsafeRaw.java Mon Nov 17 12:32:27 2014 -0800
@@ -80,7 +80,7 @@
final int element_size = 4;
final int magic = 0x12345678;
- Random rnd = new Random();
+ Random rnd = Utils.getRandomInstance();
long array = unsafe.allocateMemory(array_size * element_size); // 128 ints
long addr = array + array_size * element_size / 2; // something in the middle to work with
--- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -73,8 +73,6 @@
protected static final int THRESHOLD;
/** invocation count to trigger OSR compilation */
protected static final long BACKEDGE_THRESHOLD;
- /** invocation count to warm up method before triggering OSR compilation */
- protected static final long OSR_WARMUP = 2000;
/** Value of {@code java.vm.info} (interpreted|mixed|comp mode) */
protected static final String MODE = System.getProperty("java.vm.info");
@@ -197,7 +195,6 @@
* is compiled, or if {@linkplain #method} has zero
* compilation level.
*/
-
protected final void checkNotCompiled(int compLevel) {
if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
throw new RuntimeException(method + " must not be in queue");
@@ -218,24 +215,30 @@
* compilation level.
*/
protected final void checkNotCompiled() {
- if (WHITE_BOX.isMethodCompiled(method, false)) {
- throw new RuntimeException(method + " must be not compiled");
- }
- if (WHITE_BOX.getMethodCompilationLevel(method, false) != 0) {
- throw new RuntimeException(method + " comp_level must be == 0");
- }
- checkNotOsrCompiled();
+ checkNotCompiled(true);
+ checkNotCompiled(false);
}
- protected final void checkNotOsrCompiled() {
+ /**
+ * Checks, that {@linkplain #method} is not (OSR-)compiled.
+ *
+ * @param isOsr Check for OSR compilation if true
+ * @throws RuntimeException if {@linkplain #method} is in compiler queue or
+ * is compiled, or if {@linkplain #method} has zero
+ * compilation level.
+ */
+ protected final void checkNotCompiled(boolean isOsr) {
+ waitBackgroundCompilation();
if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
throw new RuntimeException(method + " must not be in queue");
}
- if (WHITE_BOX.isMethodCompiled(method, true)) {
- throw new RuntimeException(method + " must be not osr_compiled");
+ if (WHITE_BOX.isMethodCompiled(method, isOsr)) {
+ throw new RuntimeException(method + " must not be " +
+ (isOsr ? "osr_" : "") + "compiled");
}
- if (WHITE_BOX.getMethodCompilationLevel(method, true) != 0) {
- throw new RuntimeException(method + " osr_comp_level must be == 0");
+ if (WHITE_BOX.getMethodCompilationLevel(method, isOsr) != 0) {
+ throw new RuntimeException(method + (isOsr ? " osr_" : " ") +
+ "comp_level must be == 0");
}
}
@@ -498,8 +501,7 @@
= new Callable<Integer>() {
@Override
public Integer call() throws Exception {
- int result = warmup(OSR_CONSTRUCTOR);
- return result + new Helper(null, CompilerWhiteBoxTest.BACKEDGE_THRESHOLD).hashCode();
+ return new Helper(null, CompilerWhiteBoxTest.BACKEDGE_THRESHOLD).hashCode();
}
};
@@ -509,8 +511,7 @@
@Override
public Integer call() throws Exception {
- int result = warmup(OSR_METHOD);
- return result + helper.osrMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD);
+ return helper.osrMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD);
}
};
@@ -518,66 +519,10 @@
= new Callable<Integer>() {
@Override
public Integer call() throws Exception {
- int result = warmup(OSR_STATIC);
- return result + osrStaticMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD);
+ return osrStaticMethod(CompilerWhiteBoxTest.BACKEDGE_THRESHOLD);
}
};
- /**
- * Deoptimizes all non-osr versions of the given executable after
- * compilation finished.
- *
- * @param e Executable
- * @throws Exception
- */
- private static void waitAndDeoptimize(Executable e) throws Exception {
- CompilerWhiteBoxTest.waitBackgroundCompilation(e);
- if (WhiteBox.getWhiteBox().isMethodQueuedForCompilation(e)) {
- throw new RuntimeException(e + " must not be in queue");
- }
- // Deoptimize non-osr versions of executable
- WhiteBox.getWhiteBox().deoptimizeMethod(e, false);
- }
-
- /**
- * Executes the method multiple times to make sure we have
- * enough profiling information before triggering an OSR
- * compilation. Otherwise the C2 compiler may add uncommon traps.
- *
- * @param m Method to be executed
- * @return Number of times the method was executed
- * @throws Exception
- */
- private static int warmup(Method m) throws Exception {
- Helper helper = new Helper();
- int result = 0;
- for (long i = 0; i < CompilerWhiteBoxTest.OSR_WARMUP; ++i) {
- result += (int)m.invoke(helper, 1);
- }
- // Deoptimize non-osr versions
- waitAndDeoptimize(m);
- return result;
- }
-
- /**
- * Executes the constructor multiple times to make sure we
- * have enough profiling information before triggering an OSR
- * compilation. Otherwise the C2 compiler may add uncommon traps.
- *
- * @param c Constructor to be executed
- * @return Number of times the constructor was executed
- * @throws Exception
- */
- private static int warmup(Constructor c) throws Exception {
- int result = 0;
- for (long i = 0; i < CompilerWhiteBoxTest.OSR_WARMUP; ++i) {
- result += c.newInstance(null, 1).hashCode();
- }
- // Deoptimize non-osr versions
- waitAndDeoptimize(c);
- return result;
- }
-
private static final Constructor CONSTRUCTOR;
private static final Constructor OSR_CONSTRUCTOR;
private static final Method METHOD;
@@ -622,16 +567,83 @@
return 42;
}
- private static int osrStaticMethod(long limit) {
+ /**
+ * Deoptimizes all non-osr versions of the given executable after
+ * compilation finished.
+ *
+ * @param e Executable
+ * @throws Exception
+ */
+ private static void waitAndDeoptimize(Executable e) {
+ CompilerWhiteBoxTest.waitBackgroundCompilation(e);
+ if (WhiteBox.getWhiteBox().isMethodQueuedForCompilation(e)) {
+ throw new RuntimeException(e + " must not be in queue");
+ }
+ // Deoptimize non-osr versions of executable
+ WhiteBox.getWhiteBox().deoptimizeMethod(e, false);
+ }
+
+ /**
+ * Executes the method multiple times to make sure we have
+ * enough profiling information before triggering an OSR
+ * compilation. Otherwise the C2 compiler may add uncommon traps.
+ *
+ * @param m Method to be executed
+ * @return Number of times the method was executed
+ * @throws Exception
+ */
+ private static int warmup(Method m) throws Exception {
+ waitAndDeoptimize(m);
+ Helper helper = new Helper();
int result = 0;
+ for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) {
+ result += (int)m.invoke(helper, 1);
+ }
+ // Wait to make sure OSR compilation is not blocked by
+ // non-OSR compilation in the compile queue
+ CompilerWhiteBoxTest.waitBackgroundCompilation(m);
+ return result;
+ }
+
+ /**
+ * Executes the constructor multiple times to make sure we
+ * have enough profiling information before triggering an OSR
+ * compilation. Otherwise the C2 compiler may add uncommon traps.
+ *
+ * @param c Constructor to be executed
+ * @return Number of times the constructor was executed
+ * @throws Exception
+ */
+ private static int warmup(Constructor c) throws Exception {
+ waitAndDeoptimize(c);
+ int result = 0;
+ for (long i = 0; i < CompilerWhiteBoxTest.THRESHOLD; ++i) {
+ result += c.newInstance(null, 1).hashCode();
+ }
+ // Wait to make sure OSR compilation is not blocked by
+ // non-OSR compilation in the compile queue
+ CompilerWhiteBoxTest.waitBackgroundCompilation(c);
+ return result;
+ }
+
+ private static int osrStaticMethod(long limit) throws Exception {
+ int result = 0;
+ if (limit != 1) {
+ result = warmup(OSR_STATIC);
+ }
+ // Trigger osr compilation
for (long i = 0; i < limit; ++i) {
result += staticMethod();
}
return result;
}
- private int osrMethod(long limit) {
+ private int osrMethod(long limit) throws Exception {
int result = 0;
+ if (limit != 1) {
+ result = warmup(OSR_METHOD);
+ }
+ // Trigger osr compilation
for (long i = 0; i < limit; ++i) {
result += method();
}
@@ -646,8 +658,12 @@
}
// for OSR constructor test case
- private Helper(Object o, long limit) {
+ private Helper(Object o, long limit) throws Exception {
int result = 0;
+ if (limit != 1) {
+ result = warmup(OSR_CONSTRUCTOR);
+ }
+ // Trigger osr compilation
for (long i = 0; i < limit; ++i) {
result += method();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+import sun.hotspot.WhiteBox;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+
+/*
+ * @test DeoptimizeMultipleOSRTest
+ * @bug 8061817
+ * @library /testlibrary /testlibrary/whitebox
+ * @build DeoptimizeMultipleOSRTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,DeoptimizeMultipleOSRTest::triggerOSR DeoptimizeMultipleOSRTest
+ * @summary testing of WB::deoptimizeMethod()
+ */
+public class DeoptimizeMultipleOSRTest {
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ private static final long BACKEDGE_THRESHOLD = 150000;
+ private Method method;
+ private int counter = 0;
+
+ public static void main(String[] args) throws Exception {
+ DeoptimizeMultipleOSRTest test = new DeoptimizeMultipleOSRTest();
+ test.test();
+ }
+
+ /**
+ * Triggers two different OSR compilations for the same method and
+ * checks if WhiteBox.deoptimizeMethod() deoptimizes both.
+ *
+ * @throws Exception
+ */
+ public void test() throws Exception {
+ method = DeoptimizeMultipleOSRTest.class.getDeclaredMethod("triggerOSR", boolean.class, long.class);
+ // Trigger two OSR compiled versions
+ triggerOSR(true, BACKEDGE_THRESHOLD);
+ triggerOSR(false, BACKEDGE_THRESHOLD);
+ // Wait for compilation
+ CompilerWhiteBoxTest.waitBackgroundCompilation(method);
+ // Deoptimize
+ WHITE_BOX.deoptimizeMethod(method, true);
+ if (WHITE_BOX.isMethodCompiled(method, true)) {
+ throw new AssertionError("Not all OSR compiled versions were deoptimized");
+ }
+ }
+
+ /**
+ * Triggers OSR compilations by executing loops.
+ *
+ * @param first Determines which loop to execute
+ * @param limit The number of loop iterations
+ */
+ public void triggerOSR(boolean first, long limit) {
+ if (limit != 1) {
+ // Warmup method to avoid uncommon traps
+ for (int i = 0; i < limit; ++i) {
+ triggerOSR(first, 1);
+ }
+ CompilerWhiteBoxTest.waitBackgroundCompilation(method);
+ }
+ if (first) {
+ // Trigger OSR compilation 1
+ for (int i = 0; i < limit; ++i) {
+ counter++;
+ }
+ } else {
+ // Trigger OSR compilation 2
+ for (int i = 0; i < limit; ++i) {
+ counter++;
+ }
+ }
+ }
+}
--- a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -132,14 +132,15 @@
throw new RuntimeException(method
+ " is not compilable after clearMethodState()");
}
-
+ // Make method not (OSR-)compilable (depending on testCase.isOsr())
makeNotCompilable();
if (isCompilable()) {
throw new RuntimeException(method + " must be not compilable");
}
-
+ // Try to (OSR-)compile method
compile();
- checkNotOsrCompiled();
+ // Method should not be (OSR-)compiled
+ checkNotCompiled(testCase.isOsr());
if (isCompilable()) {
throw new RuntimeException(method + " must be not compilable");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestUseNUMAInterleaving.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,60 @@
+/*
+ * 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 TestUseNUMAInterleaving
+ * @summary Tests that UseNUMAInterleaving enabled for all collectors by
+ * ergonomics, on all platforms when UseNUMA feature is enabled.
+ * @bug 8059614
+ * @key gc
+ * @library /testlibrary
+ * @run driver TestUseNUMAInterleaving
+ */
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class TestUseNUMAInterleaving {
+
+ public static void main(String[] args) throws Exception {
+ String[] vmargs = new String[]{
+ "-XX:+UseNUMA",
+ "-XX:+PrintFlagsFinal",
+ "-version"
+ };
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, vmargs);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ boolean isNUMAEnabled
+ = Boolean.parseBoolean(output.firstMatch(NUMA_FLAG_PATTERN, 1));
+
+ if (isNUMAEnabled) {
+ output.shouldMatch("\\bUseNUMAInterleaving\\b.*?=.*?true");
+ System.out.println(output.getStdout());
+ } else {
+ System.out.println(output.firstMatch(NUMA_FLAG_PATTERN));
+ System.out.println(output.firstMatch(NUMA_FLAG_PATTERN, 1));
+ }
+ }
+
+ private static final String NUMA_FLAG_PATTERN = "\\bUseNUMA\\b.*?=.*?([a-z]+)";
+}
--- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java Mon Nov 17 12:32:27 2014 -0800
@@ -135,7 +135,6 @@
"-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);
--- a/hotspot/test/runtime/7194254/Test7194254.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/runtime/7194254/Test7194254.java Mon Nov 17 12:32:27 2014 -0800
@@ -27,6 +27,7 @@
* @summary Creates several threads with different java priorities and checks
* whether jstack reports correct priorities for them.
*
+ * @ignore 8060219
* @run main Test7194254
*/
--- a/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java Mon Nov 17 12:32:27 2014 -0800
@@ -24,41 +24,56 @@
/*
* @test
* @summary Test corner case that overflows malloc site hashtable bucket
+ * @requires sun.arch.data.model == "32"
* @key nmt jcmd stress
* @library /testlibrary /testlibrary/whitebox
- * @ignore - This test is disabled since it will stress NMT and timeout during normal testing
+ * @ignore 8062870
* @build MallocSiteHashOverflow
* @run main ClassFileInstaller sun.hotspot.WhiteBox
- * @run main/othervm/timeout=480 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteHashOverflow
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteHashOverflow
*/
import com.oracle.java.testlibrary.*;
import sun.hotspot.WhiteBox;
public class MallocSiteHashOverflow {
- private static long K = 1024;
+
public static void main(String args[]) throws Exception {
- String vm_name = System.getProperty("java.vm.name");
+ // Size of entries based on malloc tracking header defined in mallocTracker.hpp
// For 32-bit systems, create 257 malloc sites with the same hash bucket to overflow a hash bucket
- // For 64-bit systems, create 64K + 1 malloc sites with the same hash bucket to overflow a hash bucket
long entries = 257;
- if (Platform.is64bit()) {
- entries = 64 * K + 1;
- }
OutputAnalyzer output;
WhiteBox wb = WhiteBox.getWhiteBox();
+ int MAX_HASH_SIZE = wb.NMTGetHashSize();
// Grab my own PID
String pid = Integer.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
- wb.NMTOverflowHashBucket(entries);
-
- // Run 'jcmd <pid> VM.native_memory summary'
+ // Verify that current tracking level is "detail"
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "statistics"});
output = new OutputAnalyzer(pb.start());
- output.shouldContain("Tracking level has been downgraded due to lack of resources");
+ output.shouldContain("Native Memory Tracking Statistics");
+
+ // Attempt to cause NMT to downgrade tracking level by allocating small amounts
+ // of memory with random pseudo call stack
+ int pc = 1;
+ for (int i = 0; i < entries; i++) {
+ long addr = wb.NMTMallocWithPseudoStack(1, pc);
+ if (addr == 0) {
+ throw new RuntimeException("NMTMallocWithPseudoStack: out of memory");
+ }
+ // We free memory here since it doesn't affect pseudo malloc alloc site hash table entries
+ wb.NMTFree(addr);
+ pc += MAX_HASH_SIZE;
+ if (i == entries) {
+ // Verify that tracking has been downgraded
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "statistics"});
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Tracking level has been downgraded due to lack of resources");
+ }
+ }
}
}
--- a/hotspot/test/runtime/NMT/UnsafeMallocLimit.java Fri Nov 14 17:53:46 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * 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 8055289
- * @library /testlibrary
- * @build UnsafeMallocLimit
- * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=summary UnsafeMallocLimit
- */
-
-import com.oracle.java.testlibrary.*;
-import sun.misc.Unsafe;
-
-public class UnsafeMallocLimit {
-
- public static void main(String args[]) throws Exception {
- if (Platform.is32bit()) {
- Unsafe unsafe = Utils.getUnsafe();
- try {
- unsafe.allocateMemory(1 << 30);
- throw new RuntimeException("Did not get expected OOME");
- } catch (OutOfMemoryError e) {
- // Expected exception
- }
- } else {
- System.out.println("Test only valid on 32-bit platforms");
- }
- }
-}
--- a/hotspot/test/runtime/NMT/UnsafeMallocLimit2.java Fri Nov 14 17:53:46 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * 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 8058818
- * @library /testlibrary
- * @build UnsafeMallocLimit2
- * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=off UnsafeMallocLimit2
- */
-
-import com.oracle.java.testlibrary.*;
-import sun.misc.Unsafe;
-
-public class UnsafeMallocLimit2 {
-
- public static void main(String args[]) throws Exception {
- if (Platform.is32bit()) {
- Unsafe unsafe = Utils.getUnsafe();
- try {
- // Allocate greater than MALLOC_MAX and likely won't fail to allocate,
- // so it hits the NMT code that asserted.
- // Test that this doesn't cause an assertion with NMT off.
- // The option above overrides if all the tests are run with NMT on.
- unsafe.allocateMemory(0x40000000);
- System.out.println("Allocation succeeded");
- } catch (OutOfMemoryError e) {
- System.out.println("Allocation failed");
- }
- } else {
- System.out.println("Test only valid on 32-bit platforms");
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineAnnotations.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,410 @@
+/*
+ * 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
+ * @library /testlibrary
+ * @summary Test that type annotations are retained after a retransform
+ * @run main RedefineAnnotations buildagent
+ * @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
+ */
+
+import static com.oracle.java.testlibrary.Asserts.assertTrue;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.NoSuchFieldException;
+import java.lang.NoSuchMethodException;
+import java.lang.RuntimeException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.lang.reflect.AnnotatedArrayType;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.AnnotatedWildcardType;
+import java.lang.reflect.Executable;
+import java.lang.reflect.TypeVariable;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.FieldVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.ASM5;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE_USE)
+@interface TestAnn {
+ String site();
+}
+
+public class RedefineAnnotations {
+ static Instrumentation inst;
+ public static void premain(String agentArgs, Instrumentation inst) {
+ RedefineAnnotations.inst = inst;
+ }
+
+ static class Transformer implements ClassFileTransformer {
+
+ public byte[] asm(ClassLoader loader, String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM5, cw) { };
+ ClassReader cr = new ClassReader(classfileBuffer);
+ cr.accept(cv, 0);
+ return cw.toByteArray();
+ }
+
+ public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
+
+ LinkedList<F> fields = new LinkedList<>();
+
+ public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
+ super(api, cv);
+ }
+
+ @Override public FieldVisitor visitField(int access, String name,
+ String desc, String signature, Object value) {
+ if (name.startsWith("dummy")) {
+ // Remove dummy field
+ fields.addLast(new F(access, name, desc, signature, value));
+ return null;
+ }
+ return cv.visitField(access, name, desc, signature, value);
+ }
+
+ @Override public void visitEnd() {
+ F f;
+ while ((f = fields.pollFirst()) != null) {
+ // Re-add dummy fields
+ cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
+ }
+ }
+
+ private class F {
+ private int access;
+ private String name;
+ private String desc;
+ private String signature;
+ private Object value;
+ F(int access, String name, String desc, String signature, Object value) {
+ this.access = access;
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.value = value;
+ }
+ }
+ }
+
+ @Override public byte[] transform(ClassLoader loader, String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+
+ if (className.contains("TypeAnnotatedTestClass")) {
+ try {
+ // Here we remove and re-add the dummy fields. This shuffles the constant pool
+ return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+ } catch (Throwable e) {
+ // The retransform native code that called this method does not propagate
+ // exceptions. Instead of getting an uninformative generic error, catch
+ // problems here and print it, then exit.
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ return null;
+ }
+ }
+
+ private static void buildAgent() {
+ try {
+ ClassFileInstaller.main("RedefineAnnotations");
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write agent classfile", e);
+ }
+
+ try {
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: RedefineAnnotations");
+ pw.println("Agent-Class: RedefineAnnotations");
+ pw.println("Can-Retransform-Classes: true");
+ pw.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write manifest file for the agent", e);
+ }
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
+ throw new RuntimeException("Could not write the agent jar file");
+ }
+ }
+
+ public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
+ if (argv.length == 1 && argv[0].equals("buildagent")) {
+ buildAgent();
+ return;
+ }
+
+ if (inst == null) {
+ throw new RuntimeException("Instrumentation object was null");
+ }
+
+ RedefineAnnotations test = new RedefineAnnotations();
+ test.testTransformAndVerify();
+ }
+
+ // Class type annotations
+ private Annotation classTypeParameterTA;
+ private Annotation extendsTA;
+ private Annotation implementsTA;
+
+ // Field type annotations
+ private Annotation fieldTA;
+ private Annotation innerTA;
+ private Annotation[] arrayTA = new Annotation[4];
+ private Annotation[] mapTA = new Annotation[5];
+
+ // Method type annotations
+ private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
+
+ private void testTransformAndVerify()
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
+ Class<?> myClass = c;
+
+ /*
+ * Verify that the expected annotations are where they should be before transform.
+ */
+ verifyClassTypeAnnotations(c);
+ verifyFieldTypeAnnotations(c);
+ verifyMethodTypeAnnotations(c);
+
+ try {
+ inst.addTransformer(new Transformer(), true);
+ inst.retransformClasses(myClass);
+ } catch (UnmodifiableClassException e) {
+ throw new RuntimeException(e);
+ }
+
+ /*
+ * Verify that the expected annotations are where they should be after transform.
+ * Also verify that before and after are equal.
+ */
+ verifyClassTypeAnnotations(c);
+ verifyFieldTypeAnnotations(c);
+ verifyMethodTypeAnnotations(c);
+ }
+
+ private void verifyClassTypeAnnotations(Class c) {
+ Annotation anno;
+
+ anno = c.getTypeParameters()[0].getAnnotations()[0];
+ verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
+ classTypeParameterTA = anno;
+
+ anno = c.getAnnotatedSuperclass().getAnnotations()[0];
+ verifyTestAnn(extendsTA, anno, "extends");
+ extendsTA = anno;
+
+ anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
+ verifyTestAnn(implementsTA, anno, "implements");
+ implementsTA = anno;
+ }
+
+ private void verifyFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ verifyBasicFieldTypeAnnotations(c);
+ verifyInnerFieldTypeAnnotations(c);
+ verifyArrayFieldTypeAnnotations(c);
+ verifyMapFieldTypeAnnotations(c);
+ }
+
+ private void verifyBasicFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
+ verifyTestAnn(fieldTA, anno, "field");
+ fieldTA = anno;
+ }
+
+ private void verifyInnerFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
+ Annotation anno = at.getAnnotations()[0];
+ verifyTestAnn(innerTA, anno, "inner");
+ innerTA = anno;
+ }
+
+ private void verifyArrayFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno;
+ AnnotatedType at;
+
+ at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
+ anno = at.getAnnotations()[0];
+ verifyTestAnn(arrayTA[0], anno, "array1");
+ arrayTA[0] = anno;
+
+ for (int i = 1; i <= 3; i++) {
+ at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
+ anno = at.getAnnotations()[0];
+ verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
+ arrayTA[i] = anno;
+ }
+ }
+
+ private void verifyMapFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno;
+ AnnotatedType atBase;
+ AnnotatedType atParameter;
+ atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
+
+ anno = atBase.getAnnotations()[0];
+ verifyTestAnn(mapTA[0], anno, "map1");
+ mapTA[0] = anno;
+
+ atParameter =
+ ((AnnotatedParameterizedType) atBase).
+ getAnnotatedActualTypeArguments()[0];
+ anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
+ verifyTestAnn(mapTA[1], anno, "map2");
+ mapTA[1] = anno;
+
+ anno =
+ ((AnnotatedWildcardType) atParameter).
+ getAnnotatedUpperBounds()[0].getAnnotations()[0];
+ verifyTestAnn(mapTA[2], anno, "map3");
+ mapTA[2] = anno;
+
+ atParameter =
+ ((AnnotatedParameterizedType) atBase).
+ getAnnotatedActualTypeArguments()[1];
+ anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
+ verifyTestAnn(mapTA[3], anno, "map4");
+ mapTA[3] = anno;
+
+ anno =
+ ((AnnotatedParameterizedType) atParameter).
+ getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
+ verifyTestAnn(mapTA[4], anno, "map5");
+ mapTA[4] = anno;
+ }
+
+ private void verifyMethodTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+ Annotation anno;
+ Executable typeAnnotatedMethod =
+ c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
+
+ anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
+ verifyTestAnn(returnTA, anno, "return");
+ returnTA = anno;
+
+ anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
+ verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
+ methodTypeParameterTA = anno;
+
+ anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
+ verifyTestAnn(formalParameterTA, anno, "formalParameter");
+ formalParameterTA = anno;
+
+ anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
+ verifyTestAnn(throwsTA, anno, "throws");
+ throwsTA = anno;
+ }
+
+ private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
+ verifyTestAnnSite(anno, expectedSite);
+
+ // When called before transform verifyAgainst will be null, when called
+ // after transform it will be the annotation from before the transform
+ if (verifyAgainst != null) {
+ assertTrue(anno.equals(verifyAgainst),
+ "Annotations do not match before and after." +
+ " Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
+ }
+ }
+
+ private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
+ String expectedAnn = "@TestAnn(site=" + expectedSite + ")";
+ assertTrue(testAnn.toString().equals(expectedAnn),
+ "Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
+ }
+
+ public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
+ extends @TestAnn(site="extends") Thread
+ implements @TestAnn(site="implements") Runnable {
+
+ public @TestAnn(site="field") boolean typeAnnotatedBoolean;
+
+ public
+ RedefineAnnotations.
+ @TestAnn(site="inner") TypeAnnotatedTestClass
+ typeAnnotatedInner;
+
+ public
+ @TestAnn(site="array4") boolean
+ @TestAnn(site="array1") []
+ @TestAnn(site="array2") []
+ @TestAnn(site="array3") []
+ typeAnnotatedArray;
+
+ public @TestAnn(site="map1") Map
+ <@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
+ @TestAnn(site="map4") List<@TestAnn(site="map5") Object>> typeAnnotatedMap;
+
+ public int dummy1;
+ public int dummy2;
+ public int dummy3;
+
+ @TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
+ typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
+ throws @TestAnn(site="throws") ClassNotFoundException {
+
+ @TestAnn(site="local_variable_type") int foo = 0;
+ throw new ClassNotFoundException();
+ }
+
+ public void run() {}
+ }
+}
--- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Mon Nov 17 12:32:27 2014 -0800
@@ -51,9 +51,12 @@
// Known issue, JDK-8038422 (assert() on Windows)
// new SharedSizeTestData("-XX:SharedMiscDataSize", "500k", "miscellaneous data"),
- // This will cause a VM crash; commenting out for now; see bug JDK-8038268
- // @ignore JDK-8038268
- // new SharedSizeTestData("-XX:SharedMiscCodeSize", "20k", "miscellaneous code"),
+ // Too small of a misc code size should not cause a vm crash.
+ // It should result in the following error message:
+ // The shared miscellaneous code space is not large enough
+ // to preload requested classes. Use -XX:SharedMiscCodeSize=
+ // to increase the initial size of shared miscellaneous code space.
+ new SharedSizeTestData("-XX:SharedMiscCodeSize", "20k", "miscellaneous code"),
// these values are larger than default ones, but should
// be acceptable and not cause failure
--- a/hotspot/test/runtime/lambda-features/InvokespecialInterface.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/runtime/lambda-features/InvokespecialInterface.java Mon Nov 17 12:32:27 2014 -0800
@@ -33,11 +33,12 @@
import java.util.function.*;
import java.util.*;
+public class InvokespecialInterface {
interface I {
default void imethod() { System.out.println("I::imethod"); }
}
-class C implements I {
+static class C implements I {
public void foo() { I.super.imethod(); } // invokespecial InterfaceMethod
public void bar() { I i = this; i.imethod(); } // invokeinterface same
public void doSomeInvokedynamic() {
@@ -48,7 +49,6 @@
}
}
-public class InvokespecialInterface {
public static void main(java.lang.String[] unused) {
// need to create C and call I::foo()
C c = new C();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/lambda-features/TestInterfaceInit.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,87 @@
+/*
+ * 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 8034275
+ * @summary [JDK 8u40] Test interface initialization: only for interfaces declaring default methods
+ * @run main TestInterfaceInit
+ */
+import java.util.List;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+public class TestInterfaceInit {
+
+ static List<Class<?>> cInitOrder = new ArrayList<>();
+
+ // Declares a default method and initializes
+ interface I {
+ boolean v = TestInterfaceInit.out(I.class);
+ default void x() {}
+ }
+
+ // Declares a default method and initializes
+ interface J extends I {
+ boolean v = TestInterfaceInit.out(J.class);
+ default void x() {}
+ }
+ // No default method, does not initialize
+ interface JN extends J {
+ boolean v = TestInterfaceInit.out(JN.class);
+ }
+
+ // Declares a default method and initializes
+ interface K extends I {
+ boolean v = TestInterfaceInit.out(K.class);
+ default void x() {}
+ }
+
+ // No default method, does not initialize
+ interface KN extends K {
+ boolean v = TestInterfaceInit.out(KN.class);
+ }
+
+ interface L extends JN, KN {
+ boolean v = TestInterfaceInit.out(L.class);
+ default void x() {}
+ }
+
+ public static void main(String[] args) {
+ // Trigger initialization
+ boolean v = L.v;
+
+ List<Class<?>> expectedCInitOrder = Arrays.asList(I.class,J.class,K.class,L.class);
+ if (!cInitOrder.equals(expectedCInitOrder)) {
+ throw new RuntimeException(String.format("Class initialization array %s not equal to expected array %s", cInitOrder, expectedCInitOrder));
+ }
+ }
+
+ static boolean out(Class c) {
+ System.out.println("#: initializing " + c.getName());
+ cInitOrder.add(c);
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/lambda-features/TestInterfaceOrder.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,88 @@
+/*
+ * 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 8034275
+ * @summary [JDK 8u40] Test interface initialization order
+ * @run main TestInterfaceOrder
+ */
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+public class TestInterfaceOrder {
+ static List<Class<?>> cInitOrder = new ArrayList<>();
+
+ public static void main(java.lang.String[] args) {
+ //Trigger initialization
+ C c = new C();
+
+ List<Class<?>> expectedCInitOrder = Arrays.asList(I.class, J.class, A.class, K.class, B.class, L.class, C.class);
+ if (!cInitOrder.equals(expectedCInitOrder)) {
+ throw new RuntimeException(String.format("Class initialization order %s not equal to expected order %s", cInitOrder, expectedCInitOrder));
+ }
+ }
+
+ interface I {
+ boolean v = TestInterfaceOrder.out(I.class);
+ default void i() {}
+ }
+
+ interface J extends I {
+ boolean v = TestInterfaceOrder.out(J.class);
+ default void j() {}
+ }
+
+ static class A implements J {
+ static boolean v = TestInterfaceOrder.out(A.class);
+ }
+
+ interface K extends I {
+ boolean v = TestInterfaceOrder.out(K.class);
+ default void k() {}
+ }
+
+ static class B extends A implements K {
+ static boolean v = TestInterfaceOrder.out(B.class);
+ }
+
+ interface L {
+ boolean v = TestInterfaceOrder.out(L.class);
+ default void l() {}
+ }
+
+ static class C extends B implements L {
+ static boolean v = TestInterfaceOrder.out(C.class);
+ }
+
+
+ static boolean out(Class c) {
+ System.out.println("#: initializing " + c.getName());
+ cInitOrder.add(c);
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/reflect/ArrayGetIntException.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,76 @@
+/*
+ * 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 6191224
+ * @summary (reflect) Misleading detail string in IllegalArgumentException thrown by Array.get<Type>
+ * @run main ArrayGetIntException
+ */
+import java.io.*;
+import java.lang.reflect.Array;
+
+public class ArrayGetIntException {
+ public static void main(String[] args) throws Exception {
+ Object[] objArray = {new Integer(Integer.MAX_VALUE)};
+
+ // this access is legal
+ try {
+ System.out.println(Array.get(objArray, 0));
+ System.out.println("Test #1 PASSES");
+ } catch(Exception e) {
+ failTest("Test #1 FAILS - legal access denied" + e.getMessage());
+ }
+
+ // this access is not legal, but needs to generate the proper exception message
+ try {
+ System.out.println(Array.getInt(objArray, 0));
+ failTest("Test #2 FAILS - no exception");
+ } catch(Exception e) {
+ System.out.println(e);
+ if (e.getMessage().equals("Argument is not an array of primitive type")) {
+ System.out.println("Test #2 PASSES");
+ } else {
+ failTest("Test #2 FAILS - incorrect message: " + e.getMessage());
+ }
+ }
+
+ // this access is not legal, but needs to generate the proper exception message
+ try {
+ System.out.println(Array.getInt(new Object(), 0));
+ failTest("Test #3 FAILS - no exception");
+ } catch(Exception e) {
+ System.out.println(e);
+ if (e.getMessage().equals("Argument is not an array")) {
+ System.out.println("Test #3 PASSES");
+ } else {
+ failTest("Test #3 FAILS - incorrect message: " + e.getMessage());
+ }
+ }
+ }
+
+ private static void failTest(String errStr) {
+ System.out.println(errStr);
+ throw new Error(errStr);
+ }
+}
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -27,6 +27,7 @@
* @library ..
* @build DcmdUtil CompilerQueueTest
* @run main CompilerQueueTest
+ * @run main/othervm -XX:-TieredCompilation CompilerQueueTest
* @run main/othervm -Xint CompilerQueueTest
* @summary Test of diagnostic command Compiler.queue
*/
@@ -87,7 +88,9 @@
}
private static void validateMethodLine(String str) throws Exception {
- String name = str.substring(19);
+ // Skip until package/class name begins. Trim to remove whitespace that
+ // may differ.
+ String name = str.substring(14).trim();
int sep = name.indexOf("::");
if (sep == -1) {
throw new Exception("Failed dcmd queue, didn't find separator :: in: " + name);
--- a/hotspot/test/serviceability/threads/TestFalseDeadLock.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/serviceability/threads/TestFalseDeadLock.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -21,14 +21,17 @@
* questions.
*/
+import com.oracle.java.testlibrary.Utils;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.Random;
/*
* @test
+ * @ignore 8061157
* @bug 8016304
* @summary Make sure no deadlock is reported for this program which has no deadlocks.
+ * @library /testlibrary
* @run main/othervm TestFalseDeadLock
*/
@@ -65,7 +68,7 @@
public static class Test implements Runnable {
public void run() {
- Random r = new Random();
+ Random r = Utils.getRandomInstance();
while (running) {
try {
synchronized (this) {
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Mon Nov 17 12:32:27 2014 -0800
@@ -24,21 +24,21 @@
package com.oracle.java.testlibrary;
import static com.oracle.java.testlibrary.Asserts.assertTrue;
-
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
+import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.ArrayList;
-import java.util.List;
import java.util.Arrays;
import java.util.Collections;
-import java.util.regex.Pattern;
+import java.util.List;
+import java.util.Random;
import java.util.regex.Matcher;
-import java.lang.reflect.Field;
+import java.util.regex.Pattern;
import sun.misc.Unsafe;
/**
@@ -64,6 +64,21 @@
private static Unsafe unsafe = null;
/**
+ * Defines property name for seed value.
+ */
+ public static final String SEED_PROPERTY_NAME = "com.oracle.java.testlibrary.random.seed";
+
+ /* (non-javadoc)
+ * Random generator with (or without) predefined seed. Depends on
+ * "com.oracle.java.testlibrary.random.seed" property value.
+ */
+ private static volatile Random RANDOM_GENERATOR;
+
+ /**
+ * Contains the seed value used for {@link java.util.Random} creation.
+ */
+ public static final long SEED = Long.getLong(SEED_PROPERTY_NAME, new Random().nextLong());
+ /**
* Returns the value of 'test.timeout.factor' system property
* converted to {@code double}.
*/
@@ -332,4 +347,24 @@
}
return new String(hexView);
}
+
+ /**
+ * Returns {@link java.util.Random} generator initialized with particular seed.
+ * The seed could be provided via system property {@link Utils#SEED_PROPERTY_NAME}
+ * In case no seed is provided, the method uses a random number.
+ * The used seed printed to stdout.
+ * @return {@link java.util.Random} generator with particular seed.
+ */
+ public static Random getRandomInstance() {
+ if (RANDOM_GENERATOR == null) {
+ synchronized (Utils.class) {
+ if (RANDOM_GENERATOR == null) {
+ RANDOM_GENERATOR = new Random(SEED);
+ System.out.printf("For random generator using seed: %d%n", SEED);
+ System.out.printf("To re-run test with same seed value please add \"-D%s=%d\" to command line.%n", SEED_PROPERTY_NAME, SEED);
+ }
+ }
+ }
+ return RANDOM_GENERATOR;
+ }
}
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Mon Nov 17 12:32:27 2014 -0800
@@ -98,10 +98,10 @@
public native void NMTCommitMemory(long addr, long size);
public native void NMTUncommitMemory(long addr, long size);
public native void NMTReleaseMemory(long addr, long size);
- public native void NMTOverflowHashBucket(long num);
public native long NMTMallocWithPseudoStack(long size, int index);
public native boolean NMTIsDetailSupported();
public native boolean NMTChangeTrackingLevel();
+ public native int NMTGetHashSize();
// Compiler
public native void deoptimizeAll();
@@ -179,6 +179,8 @@
public native void printRegionInfo(int context);
// VM flags
+ public native boolean isConstantVMFlag(String name);
+ public native boolean isLockedVMFlag(String name);
public native void setBooleanVMFlag(String name, boolean value);
public native void setIntxVMFlag(String name, long value);
public native void setUintxVMFlag(String name, long value);
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java Mon Nov 17 12:32:27 2014 -0800
@@ -34,18 +34,21 @@
return obj == null ? null : new NMethod(obj);
}
private NMethod(Object[] obj) {
- assert obj.length == 2;
+ assert obj.length == 3;
comp_level = (Integer) obj[0];
insts = (byte[]) obj[1];
+ compile_id = (Integer) obj[2];
}
public byte[] insts;
public int comp_level;
+ public int compile_id;
@Override
public String toString() {
return "NMethod{" +
"insts=" + insts +
", comp_level=" + comp_level +
+ ", compile_id=" + compile_id +
'}';
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary_tests/RandomGeneratorTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,154 @@
+/*
+ * 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
+ * @summary Verify correctnes of the random generator from Utility.java
+ * @library /testlibrary
+ * @run driver RandomGeneratorTest SAME_SEED
+ * @run driver RandomGeneratorTest NO_SEED
+ * @run driver RandomGeneratorTest DIFFERENT_SEED
+ */
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.Utils;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * The test verifies correctness of work {@link com.oracle.java.testlibrary.Utils#getRandomInstance()}.
+ * Test works in three modes: same seed provided, no seed provided and
+ * different seed provided. In the first case the test expects that all random numbers
+ * will be repeated in all next iterations. For other two modes test expects that
+ * randomly generated numbers differ from original.
+ */
+public class RandomGeneratorTest {
+ private static final String SEED_VM_OPTION = "-D" + Utils.SEED_PROPERTY_NAME + "=";
+
+ public static void main( String[] args) throws Throwable {
+ if (args.length == 0) {
+ throw new Error("TESTBUG: No test mode provided.");
+ }
+ SeedOption seedOpt = SeedOption.valueOf(args[0]);
+ List<String> jvmArgs = new ArrayList<String>();
+ String optStr = seedOpt.getSeedOption();
+ if (optStr != null) {
+ jvmArgs.add(optStr);
+ }
+ jvmArgs.add(RandomRunner.class.getName());
+ String[] cmdLineArgs = jvmArgs.toArray(new String[jvmArgs.size()]);
+ String etalon = ProcessTools.executeTestJvm(cmdLineArgs).getOutput().trim();
+ seedOpt.verify(etalon, cmdLineArgs);
+ }
+
+ /**
+ * The utility enum helps to generate an appropriate string that should be passed
+ * to the command line depends on the testing mode. It is also responsible for the result
+ * validation.
+ */
+ private enum SeedOption {
+ SAME_SEED {
+ @Override
+ public String getSeedOption() {
+ return SEED_VM_OPTION + Utils.SEED;
+ }
+
+ @Override
+ protected boolean isOutputExpected(String orig, String output) {
+ return output.equals(orig);
+ }
+ },
+ DIFFERENT_SEED {
+ @Override
+ public String getSeedOption() {
+ return SEED_VM_OPTION + Utils.getRandomInstance().nextLong();
+ }
+
+ @Override
+ public void verify(String orig, String[] cmdLine) {
+ cmdLine[0] = getSeedOption();
+ super.verify(orig, cmdLine);
+ }
+ },
+ NO_SEED {
+ @Override
+ public String getSeedOption() {
+ return null;
+ }
+ };
+
+ /**
+ * Generates a string to be added as a command line argument.
+ * It contains "-D" prefix, system property name, '=' sign
+ * and seed value.
+ * @return command line argument
+ */
+ public abstract String getSeedOption();
+
+ protected boolean isOutputExpected(String orig, String output) {
+ return !output.equals(orig);
+ }
+
+ /**
+ * Verifies that the original output meets expectations
+ * depending on the test mode. It compares the output of second execution
+ * to original one.
+ * @param orig original output
+ * @param cmdLine command line arguments
+ * @throws Throwable - Throws an exception in case test failure.
+ */
+ public void verify(String orig, String[] cmdLine) {
+ String lastLineOrig = getLastLine(orig);
+ String lastLine;
+ try {
+ lastLine = getLastLine(ProcessTools.executeTestJvm(cmdLine).getOutput().trim());
+ } catch (Throwable t) {
+ throw new Error("TESTBUG: Unexpedted exception during jvm execution.", t);
+ }
+ if (!isOutputExpected(lastLineOrig, lastLine)) {
+ throw new AssertionError("Unexpected random number sequence for mode: " + this.name());
+ }
+ }
+
+ private static String getLastLine(String output) {
+ return output.substring(output.lastIndexOf(Utils.NEW_LINE)).trim();
+ }
+ }
+
+ /**
+ * The helper class generates several random numbers
+ * and prints them out.
+ */
+ public static class RandomRunner {
+ private static final int COUNT = 10;
+ public static void main(String[] args) {
+ StringBuilder sb = new StringBuilder();
+ Random rng = Utils.getRandomInstance();
+ for (int i = 0; i < COUNT; i++) {
+ sb.append(rng.nextLong()).append(' ');
+ }
+ System.out.println(sb.toString());
+ }
+ }
+}
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -43,6 +43,7 @@
private static final Boolean[] TESTS = {true, false, true, true, false};
private static final String TEST_NAME = "BooleanTest";
private static final String FLAG_NAME = "PrintCompilation";
+ private static final String FLAG_DEBUG_NAME = "SafepointALot";
private static final String METHOD = TEST_NAME + "::method";
private static final String METHOD1 = METHOD + "1";
private static final String METHOD2 = METHOD + "2";
@@ -54,6 +55,7 @@
VmFlagTest.WHITE_BOX::getBooleanVMFlag);
testFunctional(false);
testFunctional(true);
+ VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getBooleanVMFlag);
} else {
boolean value = Boolean.valueOf(args[0]);
method1();
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -34,7 +34,7 @@
*/
public class DoubleTest {
- private static final String FLAG_NAME = null;
+ private static final String FLAG_NAME = "CompileThresholdScaling";
private static final Double[] TESTS = {0d, -0d, -1d, 1d,
Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN,
Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY};
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -35,6 +35,7 @@
public class IntxTest {
private static final String FLAG_NAME = "OnStackReplacePercentage";
+ private static final String FLAG_DEBUG_NAME = "InlineFrequencyCount";
private static final Long[] TESTS = {0L, 100L, -1L,
(long) Integer.MAX_VALUE, (long) Integer.MIN_VALUE};
@@ -42,6 +43,7 @@
VmFlagTest.runTest(FLAG_NAME, TESTS,
VmFlagTest.WHITE_BOX::setIntxVMFlag,
VmFlagTest.WHITE_BOX::getIntxVMFlag);
+ VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getIntxVMFlag);
}
}
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -35,12 +35,14 @@
public class StringTest {
private static final String FLAG_NAME = "CompileOnly";
+ private static final String FLAG_DEBUG_NAME = "SuppressErrorAt";
private static final String[] TESTS = {"StringTest::*", ""};
public static void main(String[] args) throws Exception {
VmFlagTest.runTest(FLAG_NAME, TESTS,
VmFlagTest.WHITE_BOX::setStringVMFlag,
VmFlagTest.WHITE_BOX::getStringVMFlag);
+ VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getStringVMFlag);
}
}
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -36,6 +36,7 @@
public class UintxTest {
private static final String FLAG_NAME = "VerifyGCStartAt";
+ private static final String FLAG_DEBUG_NAME = "CodeCacheMinimumUseSpace";
private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE,
(1L << 32L) - 1L, 1L << 32L};
private static final Long[] EXPECTED_64 = TESTS;
@@ -47,6 +48,7 @@
Platform.is64bit() ? EXPECTED_64 : EXPECTED_32,
VmFlagTest.WHITE_BOX::setUintxVMFlag,
VmFlagTest.WHITE_BOX::getUintxVMFlag);
+ VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getUintxVMFlag);
}
}
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -37,16 +37,18 @@
private final BiConsumer<T, T> test;
private final BiConsumer<String, T> set;
private final Function<String, T> get;
+ private final boolean isPositive;
protected VmFlagTest(String flagName, BiConsumer<String, T> set,
Function<String, T> get, boolean isPositive) {
this.flagName = flagName;
this.set = set;
this.get = get;
+ this.isPositive = isPositive;
if (isPositive) {
- test = this::testPositive;
+ test = this::testWritePositive;
} else {
- test = this::testNegative;
+ test = this::testWriteNegative;
}
}
@@ -63,6 +65,10 @@
runTest(existentFlag, tests, tests, set, get);
}
+ protected static <T> void runTest(String existentFlag, Function<String, T> get) {
+ runTest(existentFlag, null, null, null, get);
+ }
+
protected static <T> void runTest(String existentFlag, T[] tests,
T[] results, BiConsumer<String, T> set, Function<String, T> get) {
if (existentFlag != null) {
@@ -72,13 +78,23 @@
}
public final void test(T[] tests, T[] results) {
- Asserts.assertEQ(tests.length, results.length, "[TESTBUG] tests.length != results.length");
- for (int i = 0, n = tests.length ; i < n; ++i) {
- test.accept(tests[i], results[i]);
+ if (isPositive) {
+ testRead();
+ }
+ if (tests != null) {
+ Asserts.assertEQ(tests.length, results.length, "[TESTBUG] tests.length != results.length");
+ for (int i = 0, n = tests.length ; i < n; ++i) {
+ test.accept(tests[i], results[i]);
+ }
}
}
protected String getVMOptionAsString() {
+ if (WHITE_BOX.isConstantVMFlag(flagName) || WHITE_BOX.isLockedVMFlag(flagName)) {
+ // JMM cannot access debug flags in product builds or locked flags,
+ // use whitebox methods to get such flags value.
+ return asString(getValue());
+ }
HotSpotDiagnosticMXBean diagnostic
= ManagementFactoryHelper.getDiagnosticMXBean();
VMOption tmp;
@@ -90,18 +106,24 @@
return tmp == null ? null : tmp.getValue();
}
- private void testPositive(T value, T expected) {
- String oldValue = getVMOptionAsString();
- Asserts.assertEQ(oldValue, asString(getValue()));
- Asserts.assertEQ(oldValue, asString(WHITE_BOX.getVMFlag(flagName)));
- setNewValue(value);
- String newValue = getVMOptionAsString();
- Asserts.assertEQ(newValue, asString(expected));
- Asserts.assertEQ(newValue, asString(getValue()));
- Asserts.assertEQ(newValue, asString(WHITE_BOX.getVMFlag(flagName)));
+ private String testRead() {
+ String value = getVMOptionAsString();
+ Asserts.assertNotNull(value);
+ Asserts.assertEQ(value, asString(getValue()));
+ Asserts.assertEQ(value, asString(WHITE_BOX.getVMFlag(flagName)));
+ return value;
}
- private void testNegative(T value, T expected) {
+ private void testWritePositive(T value, T expected) {
+ setNewValue(value);
+ String newValue = testRead();
+ Asserts.assertEQ(newValue, asString(expected));
+ }
+
+ private void testWriteNegative(T value, T expected) {
+ // Should always return false for non-existing flags
+ Asserts.assertFalse(WHITE_BOX.isConstantVMFlag(flagName));
+ Asserts.assertFalse(WHITE_BOX.isLockedVMFlag(flagName));
String oldValue = getVMOptionAsString();
Asserts.assertEQ(oldValue, asString(getValue()));
Asserts.assertEQ(oldValue, asString(WHITE_BOX.getVMFlag(flagName)));
@@ -114,4 +136,3 @@
return value == null ? null : "" + value;
}
}
-
--- a/jaxp/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/jaxp/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -281,3 +281,4 @@
61b4c9acaa58e482db6601ec5dc4fc3d2d8dbb55 jdk9-b36
48e4ec70cc1c8651e4a0324d91f193c4edd83af9 jdk9-b37
6c6b34477e93e6fb350035f73ed7c02266b78380 jdk9-b38
+a12d347f84176200593999f4da91ae2bb86865b2 jdk9-b39
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java Mon Nov 17 12:32:27 2014 -0800
@@ -213,6 +213,10 @@
public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) {
stack.push(obj);
obj.accept(visitor);
+
+ LocalVariable[] vars = obj.getLocalVariableTypeTable();
+ for(int i=0; i < vars.length; i++)
+ vars[i].accept(this);
stack.pop();
}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java Mon Nov 17 12:32:27 2014 -0800
@@ -87,6 +87,7 @@
private boolean strip_attributes;
private ArrayList variable_vec = new ArrayList();
+ private ArrayList type_vec = new ArrayList();
private ArrayList line_number_vec = new ArrayList();
private ArrayList exception_vec = new ArrayList();
private ArrayList throws_vec = new ArrayList();
@@ -260,7 +261,7 @@
}
} else if (a instanceof LocalVariableTypeTable) {
LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable();
- removeLocalVariables();
+ removeLocalVariableTypes();
for (int k = 0; k < lv.length; k++) {
LocalVariable l = lv[k];
InstructionHandle start = il.findHandle(l.getStartPC());
@@ -272,7 +273,7 @@
if (null == end) {
end = il.getEnd();
}
- addLocalVariable(l.getName(), Type.getType(l.getSignature()), l
+ addLocalVariableType(l.getName(), Type.getType(l.getSignature()), l
.getIndex(), start, end);
}
} else
@@ -406,6 +407,31 @@
return lg;
}
+ /*
+ * If the range of the variable has not been set yet, it will be set to be
+ * val id from the start to the end of the instruction list.
+ *
+ * @return array of declared local variable types sorted by index
+ */
+ private LocalVariableGen[] getLocalVariableTypes() {
+ int size = type_vec.size();
+ LocalVariableGen[] lg = new LocalVariableGen[size];
+ type_vec.toArray(lg);
+
+ for(int i=0; i < size; i++) {
+ if(lg[i].getStart() == null)
+ lg[i].setStart(il.getStart());
+
+ if(lg[i].getEnd() == null)
+ lg[i].setEnd(il.getEnd());
+ }
+
+ if(size > 1)
+ sort(lg, 0, size - 1);
+
+ return lg;
+ }
+
/**
* @return `LocalVariableTable' attribute of all the local variables of this method.
*/
@@ -422,6 +448,68 @@
}
/**
+ * @return `LocalVariableTypeTable' attribute of all the local variable
+ * types of this method.
+ */
+ public LocalVariableTypeTable getLocalVariableTypeTable(ConstantPoolGen cp) {
+ LocalVariableGen[] lg = getLocalVariableTypes();
+ int size = lg.length;
+ LocalVariable[] lv = new LocalVariable[size];
+
+ for(int i=0; i < size; i++)
+ lv[i] = lg[i].getLocalVariable(cp);
+
+ return new LocalVariableTypeTable(cp.addUtf8("LocalVariableTypeTable"),
+ 2 + lv.length * 10, lv, cp.getConstantPool());
+ }
+
+ /**
+ * Adds a local variable type to this method.
+ *
+ * @param name variable name
+ * @param type variable type
+ * @param slot the index of the local variable, if type is long or double, the next available
+ * index is slot+2
+ * @param start from where the variable is valid
+ * @param end until where the variable is valid
+ * @return new local variable object
+ * @see LocalVariable
+ */
+ private LocalVariableGen addLocalVariableType(String name, Type type, int slot,
+ InstructionHandle start,
+ InstructionHandle end) {
+ byte t = type.getType();
+
+ if(t != Constants.T_ADDRESS) {
+ int add = type.getSize();
+
+ if(slot + add > max_locals)
+ max_locals = slot + add;
+
+ LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end);
+ int i;
+
+ if((i = type_vec.indexOf(l)) >= 0) // Overwrite if necessary
+ type_vec.set(i, l);
+ else
+ type_vec.add(l);
+
+ return l;
+ } else {
+ throw new IllegalArgumentException("Can not use " + type +
+ " as type for local variable");
+
+ }
+ }
+
+ /**
+ * Remove all local variable types.
+ */
+ private void removeLocalVariableTypes() {
+ type_vec.clear();
+ }
+
+ /**
* Give an instruction a line number corresponding to the source code line.
*
* @param ih instruction to tag
@@ -637,12 +725,17 @@
LineNumberTable lnt = null;
LocalVariableTable lvt = null;
+ LocalVariableTypeTable lvtt = null;
- /* Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.)
+ /* Create LocalVariableTable, LocalvariableTypeTable, and LineNumberTable
+ * attributes (for debuggers, e.g.)
*/
if((variable_vec.size() > 0) && !strip_attributes)
addCodeAttribute(lvt = getLocalVariableTable(cp));
+ if((type_vec.size() > 0) && !strip_attributes)
+ addCodeAttribute(lvtt = getLocalVariableTypeTable(cp));
+
if((line_number_vec.size() > 0) && !strip_attributes)
addCodeAttribute(lnt = getLineNumberTable(cp));
@@ -691,6 +784,7 @@
// Undo effects of adding attributes
if(lvt != null) removeCodeAttribute(lvt);
+ if(lvtt != null) removeCodeAttribute(lvtt);
if(lnt != null) removeCodeAttribute(lnt);
if(code != null) removeAttribute(code);
if(et != null) removeAttribute(et);
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java Mon Nov 17 12:32:27 2014 -0800
@@ -146,8 +146,9 @@
fCurrentEntity.lineNumber++;
fCurrentEntity.columnNumber = 1;
if (fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = (char)c;
- load(1, false, true);
+ load(1, false, false);
}
if (c == '\r' && external) {
int cc = fCurrentEntity.ch[fCurrentEntity.position++];
@@ -305,9 +306,10 @@
if (XML11Char.isXML11NameStart(ch)) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = ch;
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
fCurrentEntity.columnNumber++;
String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
return symbol;
@@ -316,9 +318,10 @@
}
else if (XML11Char.isXML11NameHighSurrogate(ch)) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = ch;
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
--fCurrentEntity.position;
--fCurrentEntity.startPosition;
return null;
@@ -331,10 +334,11 @@
return null;
}
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(2);
fCurrentEntity.ch[0] = ch;
fCurrentEntity.ch[1] = ch2;
offset = 0;
- if (load(2, false, true)) {
+ if (load(2, false, false)) {
fCurrentEntity.columnNumber += 2;
String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
return symbol;
@@ -463,9 +467,10 @@
if (XML11Char.isXML11NCNameStart(ch)) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = ch;
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
fCurrentEntity.columnNumber++;
String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
return symbol;
@@ -474,9 +479,10 @@
}
else if (XML11Char.isXML11NameHighSurrogate(ch)) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = ch;
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
--fCurrentEntity.position;
--fCurrentEntity.startPosition;
return null;
@@ -489,10 +495,11 @@
return null;
}
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(2);
fCurrentEntity.ch[0] = ch;
fCurrentEntity.ch[1] = ch2;
offset = 0;
- if (load(2, false, true)) {
+ if (load(2, false, false)) {
fCurrentEntity.columnNumber += 2;
String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
return symbol;
@@ -627,9 +634,10 @@
if (XML11Char.isXML11NCNameStart(ch)) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = ch;
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
fCurrentEntity.columnNumber++;
String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
qname.setValues(null, name, name, null);
@@ -639,9 +647,10 @@
}
else if (XML11Char.isXML11NameHighSurrogate(ch)) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = ch;
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
--fCurrentEntity.startPosition;
--fCurrentEntity.position;
return false;
@@ -654,10 +663,11 @@
return false;
}
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(2);
fCurrentEntity.ch[0] = ch;
fCurrentEntity.ch[1] = ch2;
offset = 0;
- if (load(2, false, true)) {
+ if (load(2, false, false)) {
fCurrentEntity.columnNumber += 2;
String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 2);
qname.setValues(null, name, name, null);
@@ -834,8 +844,9 @@
load(0, true, true);
}
else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ invokeListeners(0);
fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
- load(1, false, true);
+ load(1, false, false);
fCurrentEntity.position = 0;
fCurrentEntity.startPosition = 0;
}
@@ -975,8 +986,9 @@
load(0, true, true);
}
else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ invokeListeners(0);
fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
- load(1, false, true);
+ load(1, false, false);
fCurrentEntity.startPosition = 0;
fCurrentEntity.position = 0;
}
@@ -1345,8 +1357,9 @@
else if (c == '\n' && (cc == '\r' ) && fCurrentEntity.isExternal()) {
// handle newlines
if (fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = (char)cc;
- load(1, false, true);
+ load(1, false, false);
}
int ccc = fCurrentEntity.ch[++fCurrentEntity.position];
if (ccc == '\n' || ccc == 0x85) {
@@ -1407,8 +1420,9 @@
fCurrentEntity.lineNumber++;
fCurrentEntity.columnNumber = 1;
if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ invokeListeners(0);
fCurrentEntity.ch[0] = (char)c;
- entityChanged = load(1, true, true);
+ entityChanged = load(1, true, false);
if (!entityChanged) {
// the load change the position to be 1,
// need to restore it when entity not changed
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java Mon Nov 17 12:32:27 2014 -0800
@@ -538,8 +538,9 @@
fCurrentEntity.lineNumber++;
fCurrentEntity.columnNumber = 1;
if (fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = (char)c;
- load(1, false, true);
+ load(1, false, false);
}
if (c == '\r' && isExternal) {
if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
@@ -670,9 +671,10 @@
int offset = fCurrentEntity.position;
if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
fCurrentEntity.columnNumber++;
String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
@@ -776,10 +778,11 @@
if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
if (++fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
offset = 0;
- if (load(1, false, true)) {
+ if (load(1, false, false)) {
fCurrentEntity.columnNumber++;
//adding into symbol table.
//XXX We are trying to add single character in SymbolTable??????
@@ -906,8 +909,9 @@
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true, true);
} else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ invokeListeners(0);
fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
- load(1, false, true);
+ load(1, false, false);
fCurrentEntity.position = 0;
}
@@ -1054,8 +1058,9 @@
if (fCurrentEntity.position == fCurrentEntity.count) {
load(0, true, true);
} else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ invokeListeners(0);
fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
- load(1, false, true);
+ load(1, false, false);
fCurrentEntity.position = 0;
}
@@ -1427,8 +1432,9 @@
} else if (c == '\n' && cc == '\r' && isExternal) {
// handle newlines
if (fCurrentEntity.position == fCurrentEntity.count) {
+ invokeListeners(1);
fCurrentEntity.ch[0] = (char)cc;
- load(1, false, true);
+ load(1, false, false);
}
fCurrentEntity.position++;
if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
@@ -1502,8 +1508,9 @@
fCurrentEntity.lineNumber++;
fCurrentEntity.columnNumber = 1;
if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ invokeListeners(0);
fCurrentEntity.ch[0] = (char)c;
- entityChanged = load(1, true, true);
+ entityChanged = load(1, true, false);
if (!entityChanged){
// the load change the position to be 1,
// need to restore it when entity not changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/AuctionController.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,386 @@
+/*
+ * 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 test.auctionportal;
+
+import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_LANGUAGE;
+import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_SOURCE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.nio.file.Paths;
+import java.util.GregorianCalendar;
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import static jaxp.library.JAXPTestUtilities.bomStream;
+import static jaxp.library.JAXPTestUtilities.failUnexpected;
+import org.testng.annotations.Test;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.TypeInfo;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSSerializer;
+import org.xml.sax.SAXException;
+import static test.auctionportal.HiBidConstants.PORTAL_ACCOUNT_NS;
+import static test.auctionportal.HiBidConstants.XML_DIR;
+
+/**
+ * This is the user controller class for the Auction portal HiBid.com.
+ */
+public class AuctionController {
+ /**
+ * Check for DOMErrorHandler handling DOMError. Before fix of bug 4890927
+ * DOMConfiguration.setParameter("well-formed",true) throws an exception.
+ */
+ @Test
+ public void testCreateNewItem2Sell() {
+ String xmlFile = XML_DIR + "novelsInvalid.xml";
+
+ try {
+ Document document = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder().parse(xmlFile);
+
+ document.getDomConfig().setParameter("well-formed", true);
+
+ DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+ DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
+ MyDOMOutput domOutput = new MyDOMOutput();
+ domOutput.setByteStream(System.out);
+ LSSerializer writer = impl.createLSSerializer();
+ writer.write(document, domOutput);
+ } catch (ParserConfigurationException | SAXException | IOException
+ | ClassNotFoundException | InstantiationException
+ | IllegalAccessException | ClassCastException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Check for DOMErrorHandler handling DOMError. Before fix of bug 4896132
+ * test throws DOM Level 1 node error.
+ */
+ @Test
+ public void testCreateNewItem2SellRetry() {
+ String xmlFile = XML_DIR + "accountInfo.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ Document document = dbf.newDocumentBuilder().parse(xmlFile);
+
+ DOMConfiguration domConfig = document.getDomConfig();
+ MyDOMErrorHandler errHandler = new MyDOMErrorHandler();
+ domConfig.setParameter("error-handler", errHandler);
+
+ DOMImplementationLS impl =
+ (DOMImplementationLS) DOMImplementationRegistry.newInstance()
+ .getDOMImplementation("LS");
+ LSSerializer writer = impl.createLSSerializer();
+ MyDOMOutput domoutput = new MyDOMOutput();
+
+ domoutput.setByteStream(System.out);
+ writer.write(document, domoutput);
+
+ document.normalizeDocument();
+ writer.write(document, domoutput);
+ assertFalse(errHandler.isError());
+ } catch (ParserConfigurationException | SAXException | IOException
+ | ClassNotFoundException | InstantiationException
+ | IllegalAccessException | ClassCastException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Check if setting the attribute to be of type ID works. This will affect
+ * the Attr.isID method according to the spec.
+ */
+ @Test
+ public void testCreateID() {
+ String xmlFile = XML_DIR + "accountInfo.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+
+ Document document = dbf.newDocumentBuilder().parse(xmlFile);
+ Element account = (Element)document
+ .getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Account").item(0);
+
+ account.setIdAttributeNS(PORTAL_ACCOUNT_NS, "accountID", true);
+ Attr aID = account.getAttributeNodeNS(PORTAL_ACCOUNT_NS, "accountID");
+ assertTrue(aID.isId());
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Check the user data on the node.
+ */
+ @Test
+ public void testCheckingUserData() {
+ String xmlFile = XML_DIR + "accountInfo.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ Document document = docBuilder.parse(xmlFile);
+
+ Element account = (Element)document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Account").item(0);
+ assertEquals(account.getNodeName(), "acc:Account");
+ Element firstName = (Element) document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "FirstName").item(0);
+ assertEquals(firstName.getNodeName(), "FirstName");
+
+ Document doc1 = docBuilder.newDocument();
+ Element someName = doc1.createElement("newelem");
+
+ someName.setUserData("mykey", "dd",
+ (operation, key, data, src, dst) -> {
+ System.err.println("In UserDataHandler" + key);
+ System.out.println("In UserDataHandler");
+ });
+ Element impAccount = (Element)document.importNode(someName, true);
+ assertEquals(impAccount.getNodeName(), "newelem");
+ document.normalizeDocument();
+ String data = (someName.getUserData("mykey")).toString();
+ assertEquals(data, "dd");
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+
+ /**
+ * Check the UTF-16 XMLEncoding xml file.
+ * @see <a href="content/movies.xml">movies.xml</a>
+ */
+ @Test
+ public void testCheckingEncoding() {
+ // Note since movies.xml is UTF-16 encoding. We're not using stanard XML
+ // file suffix.
+ String xmlFile = XML_DIR + "movies.xml.data";
+
+ //try (FileInputStream is = new FileInputStream(xmlFile)) {
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ InputStream source = bomStream("UTF-16", xmlFile);
+ Document document = dbf.newDocumentBuilder().parse(source);
+ assertEquals(document.getXmlEncoding(), "UTF-16");
+ assertEquals(document.getXmlStandalone(), true);
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Check validation API features. A schema which is including in Bug 4909119
+ * used to be testing for the functionalities.
+ * @see <a href="content/userDetails.xsd">userDetails.xsd</a>
+ */
+ @Test
+ public void testGetOwnerInfo() {
+ String schemaFile = XML_DIR + "userDetails.xsd";
+ String xmlFile = XML_DIR + "userDetails.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+ Schema schema = schemaFactory.newSchema(Paths.get(schemaFile).toFile());
+
+ Validator validator = schema.newValidator();
+ MyErrorHandler eh = new MyErrorHandler();
+ validator.setErrorHandler(eh);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ docBuilder.setErrorHandler(eh);
+
+ Document document = docBuilder.parse(new FileInputStream(xmlFile));
+ DOMResult dResult = new DOMResult();
+ DOMSource domSource = new DOMSource(document);
+ validator.validate(domSource, dResult);
+ assertFalse(eh.isAnyError());
+ } catch (SAXException | ParserConfigurationException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Check grammar caching with imported schemas.
+ * @see <a href="content/coins.xsd">coins.xsd</a>
+ * @see <a href="content/coinsImportMe.xsd">coinsImportMe.xsd</a>
+ */
+ @Test
+ public void testGetOwnerItemList() {
+ String xsdFile = XML_DIR + "coins.xsd";
+ String xmlFile = XML_DIR + "coins.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+ dbf.setValidating(false);
+
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+ Schema schema = schemaFactory.newSchema(new File(((xsdFile))));
+
+ MyErrorHandler eh = new MyErrorHandler();
+ Validator validator = schema.newValidator();
+ validator.setErrorHandler(eh);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ Document document = docBuilder.parse(new FileInputStream(xmlFile));
+ validator.validate(new DOMSource(document), new DOMResult());
+ assertFalse(eh.isAnyError());
+ } catch (SAXException | ParserConfigurationException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+
+ /**
+ * Check for the same imported schemas but will use SAXParserFactory and try
+ * parsing using the SAXParser. SCHEMA_SOURCE attribute is using for this
+ * test.
+ * @see <a href="content/coins.xsd">coins.xsd</a>
+ * @see <a href="content/coinsImportMe.xsd">coinsImportMe.xsd</a>
+ */
+
+ @Test
+ public void testGetOwnerItemList1() {
+ String xsdFile = XML_DIR + "coins.xsd";
+ String xmlFile = XML_DIR + "coins.xml";
+
+ try {
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ spf.setNamespaceAware(true);
+ spf.setValidating(true);
+
+ SAXParser sp = spf.newSAXParser();
+ sp.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+ sp.setProperty(JAXP_SCHEMA_SOURCE, xsdFile);
+
+ MyErrorHandler eh = new MyErrorHandler();
+ sp.parse(new File(xmlFile), eh);
+ assertFalse(eh.isAnyError());
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Check usage of javax.xml.datatype.Duration class.
+ */
+ @Test
+ public void testGetItemDuration() {
+ String xmlFile = XML_DIR + "itemsDuration.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ Document document = dbf.newDocumentBuilder().parse(xmlFile);
+
+ Element durationElement = (Element) document.getElementsByTagName("sellDuration").item(0);
+
+ NodeList childList = durationElement.getChildNodes();
+
+ for (int i = 0; i < childList.getLength(); i++) {
+ System.out.println("child " + i + childList.item(i));
+ }
+
+ Duration duration = DatatypeFactory.newInstance().newDuration("P365D");
+ Duration sellDuration = DatatypeFactory.newInstance().newDuration(childList.item(0).getNodeValue());
+ assertFalse(sellDuration.isShorterThan(duration));
+ assertFalse(sellDuration.isLongerThan(duration));
+ assertEquals(sellDuration.getField(DatatypeConstants.DAYS), BigInteger.valueOf(365));
+ assertEquals(sellDuration.normalizeWith(new GregorianCalendar(1999, 2, 22)), duration);
+
+ Duration myDuration = sellDuration.add(duration);
+ assertEquals(myDuration.normalizeWith(new GregorianCalendar(2003, 2, 22)),
+ DatatypeFactory.newInstance().newDuration("P730D"));
+ } catch (ParserConfigurationException | DatatypeConfigurationException
+ | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Check usage of TypeInfo interface introduced in DOM L3.
+ */
+ @Test
+ public void testGetTypeInfo() {
+ String xmlFile = XML_DIR + "accountInfo.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+ dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ docBuilder.setErrorHandler(new MyErrorHandler());
+
+ Document document = docBuilder.parse(xmlFile);
+ Element userId = (Element)document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "UserID").item(0);
+ TypeInfo typeInfo = userId.getSchemaTypeInfo();
+ assertTrue(typeInfo.getTypeName().equals("nonNegativeInteger"));
+ assertTrue(typeInfo.getTypeNamespace().equals(W3C_XML_SCHEMA_NS_URI));
+
+ Element role = (Element)document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Role").item(0);
+ TypeInfo roletypeInfo = role.getSchemaTypeInfo();
+ assertTrue(roletypeInfo.getTypeName().equals("BuyOrSell"));
+ assertTrue(roletypeInfo.getTypeNamespace().equals(PORTAL_ACCOUNT_NS));
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/AuctionItemRepository.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,482 @@
+/*
+ * 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 test.auctionportal;
+
+import static com.sun.org.apache.xerces.internal.impl.Constants.SP_ENTITY_EXPANSION_LIMIT;
+import static com.sun.org.apache.xerces.internal.impl.Constants.SP_MAX_OCCUR_LIMIT;
+import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_LANGUAGE;
+import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_SOURCE;
+import static org.testng.Assert.assertTrue;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import static javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING;
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold;
+import static jaxp.library.JAXPTestUtilities.failCleanup;
+import static jaxp.library.JAXPTestUtilities.failUnexpected;
+import static org.testng.Assert.assertFalse;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import static test.auctionportal.HiBidConstants.CLASS_DIR;
+import static test.auctionportal.HiBidConstants.GOLDEN_DIR;
+import static test.auctionportal.HiBidConstants.XML_DIR;
+
+/**
+ * This is a test class for the Auction portal HiBid.com.
+ */
+public class AuctionItemRepository {
+ /**
+ * XML file for parsing.
+ */
+ private final static String ENTITY_XML = XML_DIR + "entity.xml";
+
+ /**
+ * Feature name.
+ */
+ private final static String FEATURE_NAME = "http://xml.org/sax/features/namespace-prefixes";
+
+ /**
+ * Setting the EntityExpansion Limit to 128000 and checks if the XML
+ * document that has more than two levels of entity expansion is parsed or
+ * not. Previous system property was changed to jdk.xml.entityExpansionLimit
+ * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html.
+ */
+ @Test
+ public void testEntityExpansionSAXPos() {
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ // Secure processing will limit XML processing to conform to
+ // implementation limits.
+ factory.setFeature(FEATURE_SECURE_PROCESSING, true);
+ // Set entityExpansionLimit as 2 should expect fatalError
+ System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(128000));
+ SAXParser parser = factory.newSAXParser();
+
+ MyErrorHandler fatalHandler = new MyErrorHandler();
+ parser.parse(new File(ENTITY_XML), fatalHandler);
+ assertFalse(fatalHandler.isAnyError());
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+ /**
+ * Setting the EntityExpansion Limit to 2 and checks if the XML
+ * document that has more than two levels of entity expansion is parsed or
+ * not. Previous system property was changed to jdk.xml.entityExpansionLimit
+ * see http://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html.
+ */
+ @Test(expectedExceptions = SAXParseException.class)
+ public void testEntityExpansionSAXNeg() throws SAXParseException {
+ //
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ // Secure processing will limit XML processing to conform to
+ // implementation limits.
+ factory.setFeature(FEATURE_SECURE_PROCESSING, true);
+ // Set entityExpansionLimit as 2 should expect SAXParseException
+ System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2));
+ SAXParser parser = factory.newSAXParser();
+
+ MyErrorHandler fatalHandler = new MyErrorHandler();
+ parser.parse(new File(ENTITY_XML), fatalHandler);
+ } catch (SAXParseException e) {
+ throw e;
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Testing set MaxOccursLimit to 10000 in the secure processing enabled for
+ * SAXParserFactory.
+ */
+ @Test
+ public void testMaxOccurLimitPos() {
+ String schema_file = XML_DIR + "toys.xsd";
+ String xml_file = XML_DIR + "toys.xml";
+
+ try (InputStream is = new FileInputStream(xml_file)) {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(true);
+ factory.setFeature(FEATURE_SECURE_PROCESSING, true);
+ System.setProperty(SP_MAX_OCCUR_LIMIT, String.valueOf(10000));
+ SAXParser parser = factory.newSAXParser();
+ parser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+ parser.setProperty(JAXP_SCHEMA_SOURCE, new File(schema_file));
+ MyErrorHandler eh = new MyErrorHandler();
+ parser.parse(is, eh);
+ assertFalse(eh.isAnyError());
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Use a DocumentBuilder to create a DOM object and see if Secure Processing
+ * feature affects the entity expansion.
+ */
+ @Test
+ public void testEntityExpansionDOMPos() {
+ try {
+ DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
+ dfactory.setFeature(FEATURE_SECURE_PROCESSING, true);
+ System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(10000));
+ DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
+ MyErrorHandler eh = new MyErrorHandler();
+ dBuilder.setErrorHandler(eh);
+ dBuilder.parse(ENTITY_XML);
+ assertFalse(eh.isAnyError());
+ } catch (ParserConfigurationException | IOException | SAXException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Use a DocumentBuilder to create a DOM object and see how does the Secure
+ * Processing feature and entityExpansionLimit value affects output.
+ * Negative test that when entityExpansionLimit is too small.
+ */
+ @Test(expectedExceptions = SAXParseException.class)
+ public void testEntityExpansionDOMNeg() throws SAXParseException {
+ try {
+ DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
+ dfactory.setFeature(FEATURE_SECURE_PROCESSING, true);
+ System.setProperty(SP_ENTITY_EXPANSION_LIMIT, String.valueOf(2));
+ DocumentBuilder dBuilder = dfactory.newDocumentBuilder();
+ MyErrorHandler eh = new MyErrorHandler();
+ dBuilder.setErrorHandler(eh);
+ dBuilder.parse(ENTITY_XML);
+ } catch (SAXParseException e) {
+ throw e;
+ } catch (ParserConfigurationException | IOException | SAXException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Test xi:include with a SAXParserFactory.
+ */
+ @Test
+ public void testXIncludeSAXPos() {
+ String resultFile = CLASS_DIR + "doc_xinclude.out";
+ String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml";
+ String xmlFile = XML_DIR + "doc_xinclude.xml";
+
+ try {
+ try(FileOutputStream fos = new FileOutputStream(resultFile)) {
+ XInclHandler xh = new XInclHandler(fos, null);
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ spf.setNamespaceAware(true);
+ spf.setXIncludeAware(true);
+ spf.setFeature(FEATURE_NAME, true);
+ spf.newSAXParser().parse(new File(xmlFile), xh);
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+
+ /**
+ * Test the simple case of including a document using xi:include using a
+ * DocumentBuilder.
+ */
+ @Test
+ public void testXIncludeDOMPos() {
+ String resultFile = CLASS_DIR + "doc_xincludeDOM.out";
+ String goldFile = GOLDEN_DIR + "doc_xincludeGold.xml";
+ String xmlFile = XML_DIR + "doc_xinclude.xml";
+ try {
+ try (FileOutputStream fos = new FileOutputStream(resultFile)) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setXIncludeAware(true);
+ dbf.setNamespaceAware(true);
+
+ Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
+ doc.setXmlStandalone(true);
+
+ TransformerFactory.newInstance().newTransformer().
+ transform(new DOMSource(doc), new StreamResult(fos));
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+
+ /**
+ * Test the simple case of including a document using xi:include within a
+ * xi:fallback using a DocumentBuilder.
+ */
+ @Test
+ public void testXIncludeFallbackDOMPos() {
+ String resultFile = CLASS_DIR + "doc_fallbackDOM.out";
+ String goldFile = GOLDEN_DIR + "doc_fallbackGold.xml";
+ String xmlFile = XML_DIR + "doc_fallback.xml";
+ try{
+ try (FileOutputStream fos = new FileOutputStream(resultFile)) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setXIncludeAware(true);
+ dbf.setNamespaceAware(true);
+
+ Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
+ doc.setXmlStandalone(true);
+ TransformerFactory.newInstance().newTransformer()
+ .transform(new DOMSource(doc), new StreamResult(fos));
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+
+ /**
+ * Test for xi:fallback where the fall back text is parsed as text. This
+ * test uses a nested xi:include for the fallback test.
+ */
+ @Test
+ public void testXIncludeFallbackTextPos() {
+ String resultFile = CLASS_DIR + "doc_fallback_text.out";
+ String goldFile = GOLDEN_DIR + "doc_fallback_textGold.xml";
+ String xmlFile = XML_DIR + "doc_fallback_text.xml";
+
+ try{
+ try (FileOutputStream fos = new FileOutputStream(resultFile)) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setXIncludeAware(true);
+ dbf.setNamespaceAware(true);
+
+ Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
+ doc.setXmlStandalone(true);
+ TransformerFactory.newInstance().newTransformer()
+ .transform(new DOMSource(doc), new StreamResult(fos));
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+
+ /**
+ * Test the XPointer element() framework with XInclude.
+ */
+ @Test
+ public void testXpointerElementPos() {
+ String resultFile = CLASS_DIR + "doc_xpointer_element.out";
+ String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml";
+ String xmlFile = XML_DIR + "doc_xpointer_element.xml";
+
+ try{
+ try (FileOutputStream fos = new FileOutputStream(resultFile)) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setXIncludeAware(true);
+ dbf.setNamespaceAware(true);
+
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ TransformerFactory.newInstance().newTransformer()
+ .transform(new DOMSource(db.parse(new File(xmlFile))),
+ new StreamResult(fos));
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+
+ /**
+ * Test the XPointer framework with a SAX object.
+ */
+ @Test
+ public void testXPointerPos() {
+ String resultFile = CLASS_DIR + "doc_xpointer.out";
+ String goldFile = GOLDEN_DIR + "doc_xpointerGold.xml";
+ String xmlFile = XML_DIR + "doc_xpointer.xml";
+
+ try{
+ try (FileOutputStream fos = new FileOutputStream(resultFile)) {
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ spf.setNamespaceAware(true);
+ spf.setXIncludeAware(true);
+ spf.setFeature(FEATURE_NAME, true);
+ // parse the file
+ spf.newSAXParser().parse(new File(xmlFile), new XInclHandler(fos, null));
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+
+ /**
+ * Test if xi:include may reference the doc containing the include if the
+ * parse type is text.
+ */
+ @Test
+ public void testXIncludeLoopPos() {
+ String resultFile = CLASS_DIR + "doc_xinc_loops.out";
+ String goldFile = GOLDEN_DIR + "doc_xinc_loopGold.xml";
+ String xmlFile = XML_DIR + "doc_xinc_loops.xml";
+
+ try{
+ try (FileOutputStream fos = new FileOutputStream(resultFile)) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setXIncludeAware(true);
+ dbf.setNamespaceAware(true);
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(new File(xmlFile));
+ doc.normalizeDocument();
+ doc.setXmlStandalone(true);
+
+ TransformerFactory.newInstance().newTransformer()
+ .transform(new DOMSource(doc), new StreamResult(fos));
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+
+ /**
+ * Test if two non nested xi:include elements can include the same document
+ * with an xi:include statement.
+ */
+ @Test
+ public void testXIncludeNestedPos() {
+ String resultFile = CLASS_DIR + "schedule.out";
+ String goldFile = GOLDEN_DIR + "scheduleGold.xml";
+ String xmlFile = XML_DIR + "schedule.xml";
+
+ try{
+ try (FileOutputStream fos = new FileOutputStream(resultFile)) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setXIncludeAware(true);
+ dbf.setNamespaceAware(true);
+
+ Document doc = dbf.newDocumentBuilder().parse(new File(xmlFile));
+ doc.setXmlStandalone(true);
+ TransformerFactory.newInstance().newTransformer()
+ .transform(new DOMSource(doc), new StreamResult(fos));
+ }
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/MyDOMErrorHandler.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,60 @@
+/*
+ * 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 test.auctionportal;
+
+import org.w3c.dom.DOMErrorHandler;
+import org.w3c.dom.DOMError;
+
+/**
+ * Error handler for recording DOM processing error.
+ */
+public class MyDOMErrorHandler implements DOMErrorHandler {
+ /**
+ * flag shows if there is any error.
+ */
+ private volatile boolean errorOccured = false;
+
+ /**
+ * Set errorOcurred to true when an error occurs.
+ * @param error The error object that describes the error. This object
+ * may be reused by the DOM implementation across multiple calls to
+ * the handleError method.
+ * @return true that processing may continue depending on.
+ */
+ @Override
+ public boolean handleError (DOMError error) {
+ System.err.println( "ERROR" + error.getMessage());
+ System.err.println( "ERROR" + error.getRelatedData());
+ errorOccured = true;
+ return true;
+ }
+
+ /**
+ * Showing if any error was handled.
+ * @return true if there is one or more error.
+ * false no error occurs.
+ */
+ public boolean isError() {
+ return errorOccured;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/MyDOMOutput.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,137 @@
+/*
+ * 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 test.auctionportal;
+
+import org.w3c.dom.ls.LSOutput;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * A Thread-safe LS output destination for DOM processing. LSOutput objects
+ * belong to the application. The DOM implementation will never modify them
+ * (though it may make copies and modify the copies, if necessary).
+ */
+public class MyDOMOutput implements LSOutput {
+ /**
+ * An attribute of a language and binding dependent type that represents a
+ * writable stream of bytes.
+ */
+ private OutputStream bytestream;
+
+ /**
+ * character encoding to use for the output.
+ */
+ private String encoding;
+
+ /**
+ * The system identifier.
+ */
+ private String sysId;
+
+ /**
+ * Writable stream to which 16-bit units can be output.
+ */
+ private Writer writer;
+
+ /**
+ * An attribute of a language and binding dependent type that represents a
+ * writable stream of bytes.
+ *
+ * @return a writable stream.
+ */
+ @Override
+ public OutputStream getByteStream() {
+ return bytestream;
+ }
+
+ /**
+ * An attribute of a language and binding dependent type that represents a
+ * writable stream to which 16-bit units can be output.
+ *
+ * @return writable stream instance.
+ */
+ @Override
+ public Writer getCharacterStream() {
+ return writer;
+ }
+
+ /**
+ * The character encoding to use for the output.
+ *
+ * @return the character encoding.
+ */
+ @Override
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * The system identifier for this output destination.
+ *
+ * @return system identifier.
+ */
+ @Override
+ public String getSystemId() {
+ return sysId;
+ }
+
+ /**
+ * Set writable stream of bytes.
+ *
+ * @param bs OutputStream instance
+ */
+ @Override
+ public void setByteStream(OutputStream bs) {
+ bytestream = bs;
+ }
+
+ /**
+ * Set 16 bits unit writable stream.
+ *
+ * @param bs a Writer instance
+ */
+ @Override
+ public void setCharacterStream(Writer cs) {
+ writer = cs;
+ }
+
+ /**
+ * Set character encoding to use for the output.
+ *
+ * @param encoding encoding set to the output
+ */
+ @Override
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ /**
+ * Set the system identifier for the output.
+ *
+ * @param sysId system identifier string.
+ */
+ @Override
+ public void setSystemId(String sysId) {
+ this.sysId = sysId;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/MyErrorHandler.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,100 @@
+/*
+ * 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 test.auctionportal;
+
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * ErrorHandler for error handling. Set state if any method in error, warning
+ * or fatalError was called.
+ */
+public final class MyErrorHandler extends DefaultHandler {
+ /**
+ * Enumeration for ErrorHandler's state.
+ */
+ private enum STATE { ERROR, FATAL, WARNING, NORMAL};
+
+ /**
+ * Set state as normal by default.
+ */
+ private volatile STATE state = STATE.NORMAL;
+
+ /**
+ * Keep exception for further investigation.
+ */
+ private volatile SAXParseException exception;
+
+ /**
+ * Save exception and set state to ERROR.
+ * @param e exception wrap error.
+ */
+ @Override
+ public void error (SAXParseException e) {
+ state = STATE.ERROR;
+ exception = e;
+ }
+
+ /**
+ * Save exception and set state to FATAL.
+ * @param e exception wrap error.
+ */
+ @Override
+ public void fatalError (SAXParseException e) {
+ state = STATE.FATAL;
+ exception = e;
+ }
+
+ /**
+ * Save exception and set state to WARNING.
+ * @param e exception wrap error.
+ */
+ @Override
+ public void warning (SAXParseException e) {
+ state = STATE.WARNING;
+ exception = e;
+ }
+
+ /**
+ * return ErrorHandle's state .
+ * @return true No error, fatalError and warning.
+ * false there is any error, fatalError or warning in processing.
+ */
+ public boolean isAnyError() {
+ if (state != STATE.NORMAL)
+ System.out.println(exception);
+ return state != STATE.NORMAL;
+ }
+
+ /**
+ * return whether fatalError is the only error.
+ * @return true fatalError is the only error.
+ * false there is no error, or other error besides fatalError.
+ */
+ public boolean isFatalError() {
+ if (state == STATE.FATAL)
+ System.out.println(exception);
+ return state == STATE.FATAL;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/UserController.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,338 @@
+/*
+ * 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 test.auctionportal;
+
+import static com.sun.org.apache.xerces.internal.jaxp.JAXPConstants.JAXP_SCHEMA_LANGUAGE;
+import static org.testng.Assert.assertFalse;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold;
+import static jaxp.library.JAXPTestUtilities.failCleanup;
+import static jaxp.library.JAXPTestUtilities.failUnexpected;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSParser;
+import org.w3c.dom.ls.LSSerializer;
+import org.xml.sax.SAXException;
+import static test.auctionportal.HiBidConstants.CLASS_DIR;
+import static test.auctionportal.HiBidConstants.GOLDEN_DIR;
+import static test.auctionportal.HiBidConstants.PORTAL_ACCOUNT_NS;
+import static test.auctionportal.HiBidConstants.XML_DIR;
+
+/**
+ * This is the user controller class for the Auction portal HiBid.com.
+ */
+public class UserController {
+ /**
+ * Checking when creating an XML document using DOM Level 2 validating
+ * it without having a schema source or a schema location It must throw a
+ * sax parse exception.
+ */
+ @Test
+ public void testCreateNewUser() {
+ String resultFile = CLASS_DIR + "accountInfoOut.xml";
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ MyErrorHandler eh = new MyErrorHandler();
+ docBuilder.setErrorHandler(eh);
+
+ Document document = docBuilder.newDocument();
+
+ Element account = document.createElementNS(PORTAL_ACCOUNT_NS, "acc:Account");
+ Attr accountID = document.createAttributeNS(PORTAL_ACCOUNT_NS, "acc:accountID");
+ account.setAttributeNode(accountID);
+
+ account.appendChild(document.createElement("FirstName"));
+ account.appendChild(document.createElementNS(PORTAL_ACCOUNT_NS, "acc:LastName"));
+ account.appendChild(document.createElement("UserID"));
+
+ DOMImplementationLS impl
+ = (DOMImplementationLS) DOMImplementationRegistry
+ .newInstance().getDOMImplementation("LS");
+ LSSerializer writer = impl.createLSSerializer();
+ LSParser builder = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
+ FileOutputStream output = new FileOutputStream(resultFile);
+ MyDOMOutput domOutput = new MyDOMOutput();
+
+ domOutput.setByteStream(output);
+ writer.write(account, domOutput);
+ docBuilder.parse(resultFile);
+
+ assertTrue(eh.isAnyError());
+ } catch (ParserConfigurationException | ClassNotFoundException |
+ InstantiationException | IllegalAccessException
+ | ClassCastException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Checking conflicting namespaces and use renameNode and normalizeDocument.
+ * @see <a href="content/accountInfo.xml">accountInfo.xml</a>
+ */
+ @Test
+ public void testAddUser() {
+ String resultFile = CLASS_DIR + "accountRole.out";
+ String xmlFile = XML_DIR + "accountInfo.xml";
+
+ try {
+ // Copy schema for outputfile
+ Files.copy(Paths.get(XML_DIR, "accountInfo.xsd"),
+ Paths.get(CLASS_DIR, "accountInfo.xsd"),
+ StandardCopyOption.REPLACE_EXISTING);
+ MyErrorHandler eh = new MyErrorHandler();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+
+ dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ docBuilder.setErrorHandler(eh);
+
+ Document document = docBuilder.parse(xmlFile);
+ Element sell = (Element) document.getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Sell").item(0);
+ Element role = (Element) sell.getParentNode();
+
+ Element buy = (Element) document.renameNode(sell, PORTAL_ACCOUNT_NS, "acc:Buy");
+ role.appendChild(buy);
+
+ DOMImplementationLS impl
+ = (DOMImplementationLS) DOMImplementationRegistry
+ .newInstance().getDOMImplementation("LS");
+ LSSerializer writer = impl.createLSSerializer();
+
+
+ try(FileOutputStream output = new FileOutputStream(resultFile)) {
+ MyDOMOutput mydomoutput = new MyDOMOutput();
+ mydomoutput.setByteStream(output);
+ writer.write(document, mydomoutput);
+ }
+
+ docBuilder.parse(resultFile);
+ assertFalse(eh.isAnyError());
+ } catch (ParserConfigurationException | SAXException | IOException
+ | ClassNotFoundException | InstantiationException
+ | IllegalAccessException | ClassCastException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Checking Text content in XML file.
+ * @see <a href="content/accountInfo.xml">accountInfo.xml</a>
+ */
+ @Test
+ public void testMoreUserInfo() {
+ String xmlFile = XML_DIR + "accountInfo.xml";
+
+ try {
+ System.out.println("Checking additional user info");
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+
+ dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ MyErrorHandler eh = new MyErrorHandler();
+ docBuilder.setErrorHandler(eh);
+
+ Document document = docBuilder.parse(xmlFile);
+ Element account = (Element)document
+ .getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "Account").item(0);
+ String textContent = account.getTextContent();
+ assertTrue(textContent.trim().regionMatches(0, "Rachel", 0, 6));
+ assertEquals(textContent, "RachelGreen744");
+
+ Attr accountID = account.getAttributeNodeNS(PORTAL_ACCOUNT_NS, "accountID");
+ assertTrue(accountID.getTextContent().trim().equals("1"));
+
+ assertFalse(eh.isAnyError());
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * This will check if adoptNode works will adoptNode from
+ * @see <a href="content/userInfo.xml">userInfo.xml</a>
+ * @see <a href="content/accountInfo.xml">accountInfo.xml</a>. This is
+ * adopting a node from the XML file which is validated by a DTD and
+ * into an XML file which is validated by the schema This covers Row 5
+ * for the table
+ * http://javaweb.sfbay/~jsuttor/JSR206/jsr-206-html/ch03s05.html. Filed
+ * bug 4893745 because there was a difference in behavior
+ */
+ @Test
+ public void testCreateUserAccount() {
+ System.out.println("Creating user account");
+ String userXmlFile = XML_DIR + "userInfo.xml";
+ String accountXmlFile = XML_DIR + "accountInfo.xml";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ MyErrorHandler eh = new MyErrorHandler();
+ docBuilder.setErrorHandler(eh);
+
+ Document document = docBuilder.parse(userXmlFile);
+ Element user = (Element) document.getElementsByTagName("FirstName").item(0);
+ // Set schema after parsing userInfo.xml. Otherwise it will conflict
+ // with DTD validation.
+ dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+ DocumentBuilder docBuilder1 = dbf.newDocumentBuilder();
+ docBuilder1.setErrorHandler(eh);
+ Document accDocument = docBuilder1.parse(accountXmlFile);
+
+ Element firstName = (Element) accDocument
+ .getElementsByTagNameNS(PORTAL_ACCOUNT_NS, "FirstName").item(0);
+ Element adoptedAccount = (Element) accDocument.adoptNode(user);
+
+ Element parent = (Element) firstName.getParentNode();
+ parent.replaceChild(adoptedAccount, firstName);
+
+ DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+ DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
+ LSSerializer writer = impl.createLSSerializer();
+
+ MyDOMOutput mydomoutput = new MyDOMOutput();
+ mydomoutput.setByteStream(System.out);
+
+ writer.write(document, mydomoutput);
+ writer.write(accDocument, mydomoutput);
+
+ assertFalse(eh.isAnyError());
+ } catch (ParserConfigurationException | SAXException | IOException
+ | ClassNotFoundException | InstantiationException
+ | IllegalAccessException | ClassCastException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Checking for Row 8 from the schema table when setting the schemaSource
+ * without the schemaLanguage must report an error.
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testUserError() throws IllegalArgumentException {
+ System.out.println("Creating an error in user account");
+
+ String xmlFile = XML_DIR + "userInfo.xml";
+ String schema = "http://java.sun.com/xml/jaxp/properties/schemaSource";
+ String schemaValue = "http://dummy.com/dummy.xsd";
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+ dbf.setAttribute(schema, schemaValue);
+
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ MyErrorHandler eh = new MyErrorHandler();
+ docBuilder.setErrorHandler(eh);
+ Document document = docBuilder.parse(xmlFile);
+ assertFalse(eh.isAnyError());
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ failUnexpected(e);
+ }
+ }
+
+ /**
+ * Checking for namespace normalization.
+ * @see <a href="content/screenName.xml">screenName.xml</a> has prefix of
+ * userName is bound to "http://hibid.com/user" namespace normalization
+ * will create a namespace of prefix us and attach userEmail.
+ */
+ @Test
+ public void testCheckScreenNameExists() {
+ String resultFile = CLASS_DIR + "screenName.out";
+ String xmlFile = XML_DIR + "screenName.xml";
+ String goldFile = GOLDEN_DIR + "screenNameGold.xml";
+
+ String nsTagName = "http://hibid.com/screenName";
+ String userNs = "http://hibid.com/user";
+
+ try (FileOutputStream output = new FileOutputStream(resultFile)) {
+ DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+ DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
+ LSSerializer writer = impl.createLSSerializer();
+ LSParser builder = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
+ Document document = builder.parseURI(xmlFile);
+ NodeList nl = document.getElementsByTagNameNS(nsTagName, "screen-name");
+ assertEquals(nl.getLength(), 1);
+ Element screenName = (Element)nl.item(0);
+ Element userEmail = document.createElementNS(userNs, "userEmail");
+ assertTrue(userEmail.isDefaultNamespace(userNs));
+
+ Text email = document.createTextNode("myid@hibid.com");
+ userEmail.appendChild(email);
+ screenName.appendChild(userEmail);
+ document.normalizeDocument();
+
+ MyDOMOutput domoutput = new MyDOMOutput();
+ domoutput.setByteStream(output);
+ writer.write(document, domoutput);
+
+ assertTrue(compareDocumentWithGold(goldFile, resultFile));
+ } catch (ClassNotFoundException | InstantiationException
+ | IllegalAccessException | ClassCastException | IOException
+ | ParserConfigurationException | SAXException e) {
+ failUnexpected(e);
+ } finally {
+ try {
+ Path resultPath = Paths.get(resultFile);
+ if (Files.exists(resultPath)) {
+ Files.delete(resultPath);
+ }
+ } catch (IOException ex) {
+ failCleanup(ex, resultFile);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/XInclHandler.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,382 @@
+/*
+ * 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 test.auctionportal;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.stream.Collectors;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A SAX2 event handlers.
+ * This SAX2 ContentHandler receives callback event then print whole document
+ * that is parsed.
+ */
+public class XInclHandler extends DefaultHandler implements LexicalHandler {
+ /**
+ * Print writer.
+ */
+ private final PrintWriter fOut;
+
+ /**
+ * Canonical output.
+ */
+ private volatile boolean fCanonical;
+
+ /**
+ * Element depth.
+ */
+ private volatile int fElementDepth;
+
+ /**
+ * Sets whether output is canonical.
+ */
+ public void setCanonical(boolean canonical) {
+ fCanonical = canonical;
+ }
+
+ /**
+ * Sets the output stream for printing.
+ * @param stream OutputStream for message output.
+ * @param encoding File encoding for message output.
+ */
+ public XInclHandler(OutputStream stream, String encoding)
+ throws UnsupportedEncodingException {
+ // At least set one encoding.
+ if (encoding == null) {
+ encoding = "UTF8";
+ }
+
+ fOut = new PrintWriter(new OutputStreamWriter(stream, encoding), false);
+ }
+
+ /**
+ * Receive notification of the beginning of the document. Write the start
+ * document tag if it's not canonical mode.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ */
+ @Override
+ public void startDocument() throws SAXException {
+ fElementDepth = 0;
+
+ if (!fCanonical) {
+ writeFlush("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ }
+ }
+
+ /**
+ * Receive notification of a processing instruction.
+ * @param target The processing instruction target.
+ * @param data The processing instruction data, or null if
+ * none is supplied.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ */
+ @Override
+ public void processingInstruction (String target, String data)
+ throws SAXException {
+ if (fElementDepth > 0) {
+ StringBuilder instruction = new StringBuilder("<?").append(target);
+ if (data != null && data.length() > 0) {
+ instruction.append(' ').append(data);
+ }
+ instruction.append("?>");
+ writeFlush(instruction.toString());
+ }
+ }
+
+ /**
+ * Receive notification of the start of an element then write the normalized
+ * output to the file.
+ * @param uri The Namespace URI, or the empty string if the
+ * element has no Namespace URI or if Namespace
+ * processing is not being performed.
+ * @param localName The local name (without prefix), or the
+ * empty string if Namespace processing is not being
+ * performed.
+ * @param qName The qualified name (with prefix), or the
+ * empty string if qualified names are not available.
+ * @param attributes The attributes attached to the element. If
+ * there are no attributes, it shall be an empty
+ * Attributes object.
+ */
+ @Override
+ public void startElement(String uri, String local, String raw,
+ Attributes attrs) throws SAXException {
+ fElementDepth++;
+ StringBuilder start = new StringBuilder().append('<').append(raw);
+ if (attrs != null) {
+ for (int i = 0; i < attrs.getLength(); i++) {
+ start.append(' ').append(attrs.getQName(i)).append("=\"").
+ append(normalizeAndPrint(attrs.getValue(i))).append('"');
+ }
+ }
+ start.append('>');
+ writeFlush(start.toString());
+ }
+
+ /**
+ * Receive notification of character data inside an element and write
+ * normalized characters to file.
+ * @param ch The characters.
+ * @param start The start position in the character array.
+ * @param length The number of characters to use from the
+ * character array.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ */
+ @Override
+ public void characters(char ch[], int start, int length)
+ throws SAXException {
+ writeFlush(normalizeAndPrint(ch, start, length));
+ }
+
+ /**
+ * Receiving notification of ignorable whitespace in element content and
+ * writing normalized ignorable characters to file.
+ * @param ch The characters.
+ * @param start The start position in the character array.
+ * @param length The number of characters to use from the
+ * character array.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ */
+ @Override
+ public void ignorableWhitespace(char ch[], int start, int length)
+ throws SAXException {
+ characters(ch, start, length);
+ }
+
+ /**
+ * Receive notification of the end of an element and print end element.
+ *
+ * @param uri The Namespace URI, or the empty string if the
+ * element has no Namespace URI or if Namespace
+ * processing is not being performed.
+ * @param localName The local name (without prefix), or the
+ * empty string if Namespace processing is not being
+ * performed.
+ * @param qName The qualified name (with prefix), or the
+ * empty string if qualified names are not available.
+ */
+ @Override
+ public void endElement(String uri, String local, String raw)
+ throws SAXException {
+ fElementDepth--;
+ writeFlush("</" + raw + ">");
+ }
+
+ /**
+ * Receive notification of a parser warning and print it out.
+ * @param e The warning information encoded as an exception.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ */
+ @Override
+ public void warning(SAXParseException ex) throws SAXException {
+ printError("Warning", ex);
+ }
+
+ /**
+ * Receive notification of a parser error and print it out.
+ * @param e The error information encoded as an exception.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+
+ */
+ @Override
+ public void error(SAXParseException ex) throws SAXException {
+ printError("Error", ex);
+ }
+
+ /**
+ * Receive notification of a parser fatal error. Throw out fatal error
+ * following print fatal error message.
+ * @param e The fatal error information encoded as an exception.
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+
+ */
+ @Override
+ public void fatalError(SAXParseException ex) throws SAXException {
+ printError("Fatal Error", ex);
+ throw ex;
+ }
+
+ /**
+ * Do nothing on start DTD.
+ * @param name The document type name.
+ * @param publicId The declared public identifier for the
+ * external DTD subset, or null if none was declared.
+ * @param systemId The declared system identifier for the
+ * external DTD subset, or null if none was declared.
+ * (Note that this is not resolved against the document
+ * base URI.)
+ * @exception SAXException The application may raise an
+ * exception.
+ */
+ @Override
+ public void startDTD(String name, String publicId, String systemId)
+ throws SAXException {
+ }
+
+ /**
+ * Do nothing on end DTD.
+ * @exception SAXException The application may raise an exception.
+ */
+ @Override
+ public void endDTD() throws SAXException {
+ }
+
+ /**
+ * Do nothing on start entity.
+ * @param name The name of the entity. If it is a parameter
+ * entity, the name will begin with '%', and if it is the
+ * external DTD subset, it will be "[dtd]".
+ * @exception SAXException The application may raise an exception.
+ */
+ @Override
+ public void startEntity(String name) throws SAXException {
+ }
+
+ /**
+ * Do nothing on end entity.
+ * @param name The name of the entity. If it is a parameter
+ * entity, the name will begin with '%', and if it is the
+ * external DTD subset, it will be "[dtd]".
+ * @exception SAXException The application may raise an exception.
+ */
+ @Override
+ public void endEntity(String name) throws SAXException {
+ }
+
+ /**
+ * Do nothing on start CDATA section.
+ * @exception SAXException The application may raise an exception.
+ */
+ @Override
+ public void startCDATA() throws SAXException {
+ }
+
+ /**
+ * Do nothing on end CDATA section.
+ * @exception SAXException The application may raise an exception.
+ */
+ @Override
+ public void endCDATA() throws SAXException {
+ }
+
+ /**
+ * Report an normalized XML comment when receive a comment in the document.
+ *
+ * @param ch An array holding the characters in the comment.
+ * @param start The starting position in the array.
+ * @param length The number of characters to use from the array.
+ * @exception SAXException The application may raise an exception.
+ */
+ @Override
+ public void comment(char ch[], int start, int length) throws SAXException {
+ if (!fCanonical && fElementDepth > 0) {
+ writeFlush("<!--" + normalizeAndPrint(ch, start, length) + "-->");
+ }
+ }
+
+ /**
+ * Normalizes and prints the given string.
+ * @param s String to be normalized
+ */
+ private String normalizeAndPrint(String s) {
+ return s.chars().mapToObj(c -> normalizeAndPrint((char)c)).
+ collect(Collectors.joining());
+ }
+
+ /**
+ * Normalizes and prints the given array of characters.
+ * @param ch The characters to be normalized.
+ * @param start The start position in the character array.
+ * @param length The number of characters to use from the
+ * character array.
+ */
+ private String normalizeAndPrint(char[] ch, int offset, int length) {
+ return normalizeAndPrint(new String(ch, offset, length));
+ }
+
+ /**
+ * Normalizes given character.
+ * @param c char to be normalized.
+ */
+ private String normalizeAndPrint(char c) {
+ switch (c) {
+ case '<':
+ return "<";
+ case '>':
+ return ">";
+ case '&':
+ return "&";
+ case '"':
+ return """;
+ case '\r':
+ case '\n':
+ return fCanonical ? "&#" + Integer.toString(c) + ";" : String.valueOf(c);
+ default:
+ return String.valueOf(c);
+ }
+ }
+
+ /**
+ * Prints the error message.
+ * @param type error type
+ * @param ex exception that need to be printed
+ */
+ private void printError(String type, SAXParseException ex) {
+ System.err.print("[" + type + "] ");
+ String systemId = ex.getSystemId();
+ if (systemId != null) {
+ int index = systemId.lastIndexOf('/');
+ if (index != -1)
+ systemId = systemId.substring(index + 1);
+ System.err.print(systemId);
+ }
+ System.err.print(':' + ex.getLineNumber());
+ System.err.print(':' + ex.getColumnNumber());
+ System.err.println(": " + ex.getMessage());
+ System.err.flush();
+ }
+
+ /**
+ * Write out and flush.
+ * @param out string to be written.
+ */
+ private void writeFlush(String out) {
+ fOut.print(out);
+ fOut.flush();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/accountInfo.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<acc:Account xmlns="http://www.auctionportal.org/Accounts"
+ xmlns:acc="http://www.auctionportal.org/Accounts"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.auctionportal.org/Accounts accountInfo.xsd" acc:accountID="1">
+
+ <FirstName>Rachel</FirstName>
+ <LastName>Green</LastName>
+ <UserID>744</UserID>
+ <Role><Sell/></Role>
+</acc:Account>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/accountInfo.xsd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.auctionportal.org/Accounts"
+ xmlns:acc="http://www.auctionportal.org/Accounts"
+ xmlns="http://www.auctionportal.org/Accounts" elementFormDefault="qualified">
+
+<xs:element name="Account">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="FirstName" type ="xs:string"/>
+ <xs:element name="MiddleInitial" type ="xs:string" minOccurs="0"/>
+ <xs:element ref="LastName"/>
+
+ <!-- This is to associate the account with the screenName
+ later will work on uniqueness with identity constraints
+ importing/including this schema in another one
+ -->
+ <xs:element name="UserID" type ="xs:nonNegativeInteger" />
+ <xs:element name="Role" type ="BuyOrSell" minOccurs="0" maxOccurs="1" />
+
+ <!-- This may not make sense but this is to test the date -->
+ <xs:element name="DateOfBirth" type ="DateType" minOccurs="0" maxOccurs="1" />
+ <xs:element name="EmailQname" type ="xs:QName" minOccurs="0" maxOccurs="1" />
+ <xs:element name="AptNo" type ="xs:unsignedShort" minOccurs="0" maxOccurs="1" />
+ <xs:element name="StreetNo" type ="xs:short" minOccurs="0" maxOccurs="1" />
+ </xs:sequence>
+ <xs:attribute ref="accountID"/>
+ </xs:complexType>
+</xs:element>
+
+<xs:element name="LastName" type ="xs:string"/>
+
+<!-- The accountID is same as UserID This is just to check how
+ global attributes are treated-->
+<xs:attribute name="accountID" type="xs:integer"/>
+
+<xs:complexType name="BuyOrSell">
+ <xs:choice>
+ <xs:element name="Buy" type="PlaceHolder"/>
+ <xs:element name="Sell" type="PlaceHolder"/>
+ </xs:choice>
+</xs:complexType>
+
+<!-- an empty complex type declared globally-->
+<xs:complexType name="PlaceHolder">
+</xs:complexType>
+
+
+<!-- This may all not make too much sense
+ but just to check the date features of schema-->
+<xs:complexType name="DateType">
+ <xs:sequence>
+ <!--<xs:all>-->
+ <xs:element name="YearMonth" type="xs:gYearMonth"/>
+ <xs:element name="MonthDay" type="xs:gMonthDay"/>
+ <xs:element name="Date" type="xs:date"/>
+ <!--</xs:all>-->
+ </xs:sequence>
+</xs:complexType>
+
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/activity.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,6 @@
+<?xml version="1.0" ?>
+<activity id="1" >
+ <name>Code</name>
+ <description>Some description</description>
+</activity>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/bookInfo.dtd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,13 @@
+<!ELEMENT document ANY>
+<!ELEMENT title (#PCDATA)>
+<!ELEMENT publisher (#PCDATA)>
+<!ELEMENT book (#PCDATA)>
+<!ELEMENT bookurn (#PCDATA)>
+<!ELEMENT xmlns:pages (#PCDATA)>
+<!ATTLIST book price CDATA "$100">
+<!ATTLIST book author CDATA "Herold">
+<!ATTLIST book number ID #REQUIRED>
+<!ATTLIST bookurn xmlns CDATA "10">
+<!ATTLIST bookurn xmlns:isbn CDATA "10">
+<!ENTITY ws "Walter Sam Communications">
+<!ENTITY af "Alfred publication">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/bookInfo.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no" ?>
+<!DOCTYPE document SYSTEM "bookInfo.dtd">
+<document>
+ Publishers of the Music of New York Women Composers
+
+ <title>The Publishers </title>
+
+ <publisher>
+ Alfred Publishing
+ &ws;
+ 15535 Morrison
+ South Oaks CA 91403
+ </publisher>
+
+ <book price="$100" author = "Herold" number = "no_11">
+ eXtensible Markup Language
+ </book>
+
+ <bookurn xmlns='urn:loc.gov:books'
+ xmlns:isbn='urn:ISBN:0-395-36341-6'/>
+ <xmlns:pages />
+
+ Publishers are not noted in report by time.
+
+</document>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/coins.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<im:coin
+ xmlns:im="http://www.hibid.com/items"
+ xmlns="http://www.hibid.com/items"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:it="http://someimport.com">
+ <im:description>
+ <im:info> 1950 gold coin
+ </im:info>
+ </im:description>
+ <dates_data xmlns="http://www.hibid.com/items">
+ <it:mint>1950-04-04T00:00:00</it:mint>
+ <it:circulation> 1960
+ </it:circulation>
+ </dates_data>
+</im:coin>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/coins.xsd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.hibid.com/items"
+ xmlns="http://www.hibid.com/items"
+ xmlns:im="http://someimport.com"
+ elementFormDefault="qualified"
+ xmlns:it="http://www.hibid.com/items" >
+
+ <xs:import schemaLocation="coinsImportMe.xsd" namespace="http://someimport.com"/>
+
+
+
+ <xs:element name="coin">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="description" type="it:description" />
+ <xs:element name="dates_data" type="im:dates_data" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="description">
+ <xs:sequence>
+ <xs:element name="info" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+
+
+ <xs:simpleType name="yearType">
+ <xs:restriction base="xs:int">
+ <xs:enumeration value="1930" />
+ <xs:enumeration value="1949" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:element name="YearInfo">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="reMintYear" type="yearType" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/coinsImportMe.xsd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://someimport.com"
+ xmlns="http://someimport.com"
+ elementFormDefault="qualified"
+ xmlns:im="http://someimport.com" >
+
+
+ <xs:complexType name="dates_data">
+ <xs:sequence>
+ <xs:element name="mint" type="xs:dateTime" />
+ <xs:element name="circulation" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="designer">
+ <xs:sequence>
+ <xs:element name="name" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/data.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,18 @@
+<?xml version='1.0'?>
+<data id="employee">
+ <employee id="employee">
+ <name>timepass</name>
+ <sex>M</sex>
+ <age>10</age>
+ <complexion>Fair</complexion>
+ <figure>36-28-36</figure>
+ </employee>
+ <employee>
+ <name>COOOOL</name>
+ <sex>F</sex>
+ <age>20</age>
+ <complexion>Dark</complexion>
+ <figure>26-32-26</figure>
+ </employee>
+</data>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/doc_fallback.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,11 @@
+<?xml version='1.0'?>
+<document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "task.xml" resource:</p>
+ <example>
+ <xi:include href="task.xml" parse="xml">
+ <xi:fallback >
+ <xi:include href="fallback.xml" parse="xml" />
+ </xi:fallback>
+ </xi:include>
+ </example>
+</document>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/doc_fallback_text.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,11 @@
+<?xml version='1.0'?>
+<document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "tasks.xml" resource:</p>
+ <example>
+ <xi:include href="task.xml" parse="xml">
+ <xi:fallback >
+ <xi:include href="fallback_text.xml" parse="text" />
+ </xi:fallback>
+ </xi:include>
+ </example>
+</document>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/doc_xinc_loops.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the outer XML file</p>
+ <example>
+
+ <xi:include href="task.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="doc_xinc_loops.xml" parse="text" />
+ </xi:fallback>
+ </xi:include>
+ </example>
+</root>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/doc_xinclude.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,6 @@
+<?xml version='1.0'?>
+<document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "data.xml" resource:</p>
+ <example><xi:include href="tasks.xml" parse="xml"/></example>
+</document>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/doc_xpointer.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,6 @@
+<?xml version='1.0'?>
+<document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "tasks.xml" resource:</p>
+ <example><xi:include href="tasks.xml" xpointer="element(/1/2/1)" parse="xml"/></example>
+</document>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/doc_xpointer_element.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,5 @@
+<?xml version='1.0'?>
+<document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "tasks.xml" resource:</p>
+ <example><xi:include href="tasks.xml" xpointer="element(/1/2/1)" parse="xml"/></example>
+</document>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/document_xinclude.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,6 @@
+<?xml version='1.0'?>
+<document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "data.xml" resource:</p>
+ <example><xi:include href="data.xml" parse="xml"/></example>
+</document>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/entity.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Document : entity.xml
+ Created on : August 6, 2003, 5:39 PM
+ Author : Prasad Subramanian
+ Description:
+ To create a base XML document to test the entiity expansion limit
+-->
+<!DOCTYPE status[
+<!ENTITY firstEntity "fe">
+<!ENTITY secondEntity "&firstEntity;&firstEntity;" >
+<!ENTITY thirdEntity "&secondEntity;&secondEntity;" >
+<!ENTITY fourthEntity "&thirdEntity;&thirdEntity;" >
+<!ENTITY fifthEntity "&fourthEntity;&fourthEntity;" >
+<!-- <!ENTITY sixthEntity "&fifthEntity;&fifthEntity;">
+<!ENTITY seventhEntity "&sixthEntity;&sixthEntity;" >
+<!ENTITY eighthEntity "&seventhEntity;&seventhEntity;" >
+<!ENTITY ninthEntity "&eighthEntity;&eighthEntity;" >
+<!ENTITY tenthEntity "&ninthEntity;&ninthEntity;" >
+<!ENTITY eleventhEntity "&tenthEntity;&tenthEntity;"> -->
+]>
+<report>
+ <tests>
+ <test>
+ <id>Test Id</id>
+ <name>Test Name</name>
+ <description>My Desc</description>
+ <status>&fifthEntity;</status>
+ </test>
+ </tests>
+</report>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/fallback.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fallback> This is the fallback text </fallback>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/fallback_text.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,1 @@
+This is the fallback text as a text
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/inclusion.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<activities xmlns:xi="http://www.w3.org/2001/XInclude" >
+ <xi:include href="activity.xml" parse="xml" />
+</activities>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/itemsDuration.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+
+<item xmlns="http://www.hibid.com/items" itemID="i1" name="Warn Bros Pitcher" category="other" country="US">
+ <description> 20th century vase. Really unique . Really antique</description>
+ <ownerID>2</ownerID>
+ <sellStartDateTime> 2002-03-11T15:23:45</sellStartDateTime>
+ <sellStartDate> 2002-03-11</sellStartDate>
+ <sellStartTime> 15:23:45</sellStartTime>
+ <sellDuration>P365D</sellDuration>
+ <bidderID>a2</bidderID>
+ <bidPrice></bidPrice>
+ <elapsedTime></elapsedTime>
+
+</item>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/movies.xml.data Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
+<Collection>
+ <movies>
+ <movie>
+ <name>ઠકત</name>
+ <director>Vipul Shah</director>
+ <country>Indian</country>
+ <language>Gujarati</language>
+ <releaseDate>1997-03-02-08:00</releaseDate>
+ </movie>
+ </movies>
+</Collection>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/novels.xsd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+xmlns="www.novels.com"
+xsi:schemaLocation=""www.novels.com" novels.xsd" >
+
+
+
+<xs:element name="novel" type="novelType" />
+
+<xs:complexType name="novelType">
+ <xs:sequence maxOccurs ="3" minOccurs="1">
+ <xs:element name="mystery" type="xs:string"/>
+ <xs:element name="links" type="linksType"/>
+ </xs:sequence>
+</xs:complexType>
+
+<xs:simpleType name="linksType">
+ <xs:restriction base="xs:anyURI">
+ <xs:enumeration value="http://www.links.com"/>
+ <xs:enumeration value="http://www.mystery.com"/>
+ <xs:enumeration value="http://www.hitchcock.com"/>
+ </xs:restriction>
+</xs:simpleType>
+
+</xs:schema>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/novelsInvalid.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<novel>
+ <mystery>Mystery of Whispering Mummy</mystery>
+ <links>http://www.links.com </links>
+
+ <mystery>Mystery of Vanishing Treasure</mystery>
+ <links>http://www.alfrdhitchcock.com </links>
+</novel>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/schedule.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schedule xmlns:xi="http://www.w3.org/2001/XInclude" >
+ <task xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="inclusion.xml" parse="xml" />
+ </task>
+ <task xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="inclusion.xml" parse="xml" />
+ </task>
+</schedule>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/screenName.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+
+
+<us:screen-names xmlns:us="http://hibid.com/screenName">
+ xmlns="http://hibid.com/screenName">
+ <us:screen-name>
+ <us:userName xmlns:us="http://hibid.com/user"> tom </us:userName>
+ <userNo>10 </userNo>
+ </us:screen-name>
+</us:screen-names>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/tasks.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<tasks>
+ <task id="task1" >
+ <owner>John doe</owner>
+ <startdate>10/02/2003</startdate>
+ <enddate>11/02/2003</enddate>
+ <description>This is task 1</description>
+ </task>
+ <task id="task2" >
+ <owner>Jane Doe</owner>
+ <startdate>10/02/2003</startdate>
+ <enddate>11/02/2003</enddate>
+ <description>This is task 2</description>
+ </task>
+</tasks>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/toys.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Document : toys.xml
+ Created on : August 11, 2003, 6:42 PM
+ Author : Prasad Subramanian
+ Description:
+-->
+
+<toys>
+ <toy>
+ <name>Lego-Model01</name>
+ <price>65.99</price>
+ </toy>
+ <toy>
+ <name>Lego-Model2</name>
+ <price>69.99</price>
+ </toy>
+ <toy>
+ <name>Lego-Model3</name>
+ <price>14.99</price>
+ </toy>
+ <toy>
+ <name>Barbie-Pink</name>
+ <price>12.99</price>
+ </toy>
+ <toy>
+ <name>Barbie-Blue</name>
+ <price>13.99</price>
+ </toy>
+ <toy>
+ <name>Barbie-White</name>
+ <price>13.99</price>
+ </toy>
+ <toy>
+ <name>Barbie-Plain</name>
+ <price>13.99</price>
+ </toy>
+</toys>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/toys.xsd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="toys">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="toy" maxOccurs="200">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="name" type="xs:string" minOccurs="0"/>
+ <xs:element name="price" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/userAddress.xsd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.hibid.com/useraccount"
+ xmlns="http://www.hibid.com/useraccount"
+ xmlns:user="http://www.hibid.com/useraccount" elementFormDefault="qualified">
+
+
+
+ <xs:complexType name="AddressType">
+ <xs:sequence>
+ <xs:element name="StreetInfo" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+
+
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/userDetails.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<user xmlns="http://www.hibid.com/useraccount"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.hibid.com/useraccount userDetails.xsd http://www.hibid.com/useraccount userAddress.xsd">
+ <Name>Bob </Name>
+ <addresses>
+ <homeAddress>
+ <StreetInfo>555 Beverly Hills Rd
+ </StreetInfo>
+ </homeAddress>
+ </addresses>
+
+</user>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/userDetails.xsd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding = "utf-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://www.hibid.com/useraccount"
+ xmlns="http://www.hibid.com/useraccount"
+ xmlns:user="http://www.hibid.com/useraccount" elementFormDefault="qualified" >
+
+ <xs:include schemaLocation="userAddress.xsd"/>
+
+ <xs:simpleType name="charType">
+ <xs:restriction base="xs:NCName">
+ <xs:minLength value="1" />
+ <xs:maxLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="_2CharsType">
+ <xs:restriction base="xs:string">
+ <xs:length value="2" fixed="true"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="_3digits">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]{3}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="_7digits">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]{7}" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="EmptyElement" />
+
+
+ <!-- *************************************
+ *** phone number type ****
+ *************************************
+ -->
+ <xs:complexType name="international_AreaCode_Type">
+ <xs:sequence>
+ <xs:element name="countryCode" type="_3digits"/>
+ <xs:element name="areaCode" type="_3digits"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="us_AreaCode_Type">
+ <xs:sequence>
+ <xs:element name="areaCode" type="_3digits"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="us_phonenumber_type">
+ <xs:complexContent>
+ <xs:extension base="us_AreaCode_Type">
+ <xs:sequence>
+ <xs:element name="localNumber" type="_7digits"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="international_phonenumber_type">
+ <xs:complexContent>
+ <xs:extension base="international_AreaCode_Type">
+ <xs:sequence>
+ <xs:element name="localNumber" type="_7digits"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <!-- *************************************
+ *** address type ****
+ *************************************
+ -->
+ <xs:simpleType name="stateAbrvType">
+ <xs:restriction base="_2CharsType">
+ <xs:pattern value="[A-Z]" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="us_zipCodeType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]{5}(-[0-9]{4})?" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="state.zip_type">
+ <xs:union memberTypes="stateAbrvType us_zipCodeType"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="CityInfo_type">
+ <xs:restriction base="xs:normalizedString">
+ <xs:whiteSpace value="collapse" />
+ </xs:restriction>
+ </xs:simpleType>
+
+
+ <!-- *************************************
+ *** user ****
+ *************************************
+ -->
+ <xs:element name="user">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="Name" type="xs:string" minOccurs="0" />
+
+
+ <xs:element name="addresses">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="homeAddress" type="AddressType"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+
+
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/userInfo.dtd Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,6 @@
+<!ELEMENT userInfo (user+)>
+<!ELEMENT user (FirstName,LastName,UserID)>
+<!ELEMENT FirstName (#PCDATA)>
+<!ELEMENT LastName (#PCDATA)>
+<!ELEMENT UserID (#PCDATA)>
+<!ATTLIST user accountID CDATA "100">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/content/userInfo.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,12 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE userInfo SYSTEM "userInfo.dtd">
+<userInfo>
+ <user accountID="a111">
+ <FirstName>King
+ </FirstName>
+ <LastName>Kong
+ </LastName>
+ <UserID>007
+ </UserID>
+ </user>
+</userInfo>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/golden/doc_fallbackGold.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?><document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "task.xml" resource:</p>
+ <example>
+
+ <fallback xml:base="fallback.xml"> This is the fallback text </fallback>
+
+ </example>
+</document>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/golden/doc_fallback_textGold.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "tasks.xml" resource:</p>
+ <example>
+
+ This is the fallback text as a text
+
+
+ </example>
+</document>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/golden/doc_xinc_loopGold.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the outer XML file</p>
+ <example>
+
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<root xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the outer XML file</p>
+ <example>
+
+ <xi:include href="task.xml" parse="xml">
+ <xi:fallback>
+ <xi:include href="doc_xinc_loops.xml" parse="text" />
+ </xi:fallback>
+ </xi:include>
+ </example>
+</root>
+
+
+
+ </example>
+</root>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/golden/doc_xincludeGold.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding="UTF-8"?><document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "data.xml" resource:</p>
+ <example><tasks xml:base="tasks.xml">
+ <task id="task1" >
+ <owner>John doe</owner>
+ <startdate>10/02/2003</startdate>
+ <enddate>11/02/2003</enddate>
+ <description>This is task 1</description>
+ </task>
+ <task id="task2" >
+ <owner>Jane Doe</owner>
+ <startdate>10/02/2003</startdate>
+ <enddate>11/02/2003</enddate>
+ <description>This is task 2</description>
+ </task>
+</tasks></example>
+</document>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/golden/doc_xpointerGold.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?><document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <p>The following is the source of the "tasks.xml" resource:</p>
+ <example><owner xml:base="tasks.xml">Jane Doe</owner></example>
+</document>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/golden/scheduleGold.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?><schedule xmlns:xi="http://www.w3.org/2001/XInclude">
+ <task>
+ <activities xml:base="inclusion.xml">
+ <activity id="1" xml:base="activity.xml">
+ <name>Code</name>
+ <description>Some description</description>
+</activity>
+</activities>
+ </task>
+ <task>
+ <activities xml:base="inclusion.xml">
+ <activity id="1" xml:base="activity.xml">
+ <name>Code</name>
+ <description>Some description</description>
+</activity>
+</activities>
+ </task>
+</schedule>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/auctionportal/golden/screenNameGold.xml Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<us:screen-names xmlns:us="http://hibid.com/screenName">
+ xmlns="http://hibid.com/screenName">
+ <us:screen-name>
+ <us:userName xmlns:us="http://hibid.com/user"> tom </us:userName>
+ <userNo>10 </userNo>
+ <userEmail xmlns="http://hibid.com/user">myid@hibid.com</userEmail></us:screen-name>
+</us:screen-names>
--- a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JAXPTestUtilities.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JAXPTestUtilities.java Mon Nov 17 12:32:27 2014 -0800
@@ -22,11 +22,23 @@
*/
package jaxp.library;
-
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
import static org.testng.Assert.fail;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
/**
* This is an interface provide basic support for JAXP functional test.
@@ -59,6 +71,22 @@
public static final String TEMP_DIR = System.getProperty("java.io.tmpdir", ".");
/**
+ * BOM table for storing BOM header.
+ */
+ private final static Map<String, byte[]> bom = new HashMap();
+
+ /**
+ * Initialize all BOM headers.
+ */
+ static {
+ bom.put("UTF-8", new byte[]{(byte)0xEF, (byte) 0xBB, (byte) 0xBF});
+ bom.put("UTF-16BE", new byte[]{(byte)0xFE, (byte)0xFF});
+ bom.put("UTF-16LE", new byte[]{(byte)0xFF, (byte)0xFE});
+ bom.put("UTF-32BE", new byte[]{(byte)0x00, (byte)0x00, (byte)0xFE, (byte)0xFF});
+ bom.put("UTF-32LE", new byte[]{(byte)0xFF, (byte)0xFE, (byte)0x00, (byte)0x00});
+ }
+
+ /**
* Compare contents of golden file with test output file line by line.
* return true if they're identical.
* @param goldfile Golden output file name
@@ -75,6 +103,63 @@
}
/**
+ * Compare contents of golden file with test output file by their document
+ * representation.
+ * Here we ignore the white space and comments. return true if they're
+ * lexical identical.
+ * @param goldfile Golden output file name.
+ * @param resultFile Test output file name.
+ * @return true if two file's document representation are identical.
+ * false if two file's document representation are not identical.
+ * @throws javax.xml.parsers.ParserConfigurationException if the
+ * implementation is not available or cannot be instantiated.
+ * @throws SAXException If any parse errors occur.
+ * @throws IOException if an I/O error occurs reading from the file or a
+ * malformed or unmappable byte sequence is read .
+ */
+ public static boolean compareDocumentWithGold(String goldfile, String resultFile)
+ throws ParserConfigurationException, SAXException, IOException {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setCoalescing(true);
+ factory.setIgnoringElementContentWhitespace(true);
+ factory.setIgnoringComments(true);
+ DocumentBuilder db = factory.newDocumentBuilder();
+
+ Document goldD = db.parse(Paths.get(goldfile).toFile());
+ goldD.normalizeDocument();
+ Document resultD = db.parse(Paths.get(resultFile).toFile());
+ resultD.normalizeDocument();
+ return goldD.isEqualNode(resultD);
+ }
+ /**
+ * Convert stream to ByteArrayInputStream by given character set.
+ * @param charset target character set.
+ * @param file a file that contains no BOM head content.
+ * @return a ByteArrayInputStream contains BOM heads and bytes in original
+ * stream
+ * @throws IOException I/O operation failed or unsupported character set.
+ */
+ public static InputStream bomStream(String charset, String file)
+ throws IOException {
+ String localCharset = charset;
+ if (charset.equals("UTF-16") || charset.equals("UTF-32")) {
+ localCharset
+ += ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN ? "BE" : "LE";
+ }
+ if (!bom.containsKey(localCharset))
+ throw new UnsupportedCharsetException("Charset:" + localCharset);
+
+ byte[] content = Files.readAllLines(Paths.get(file)).stream().
+ collect(Collectors.joining()).getBytes(localCharset);
+ byte[] head = bom.get(localCharset);
+ ByteBuffer bb = ByteBuffer.allocate(content.length + head.length);
+ bb.put(head);
+ bb.put(content);
+ return new ByteArrayInputStream(bb.array());
+ }
+
+ /**
* Prints error message if an exception is thrown
* @param ex The exception is thrown by test.
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/test/auctionportal/HiBidConstants.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,68 @@
+/*
+ * 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 test.auctionportal;
+
+import static jaxp.library.JAXPTestUtilities.FILE_SEP;
+import static jaxp.library.JAXPTestUtilities.USER_DIR;
+
+/**
+ * This is the Base test class provide basic support for Auction portal test.
+ */
+public class HiBidConstants {
+ /**
+ * Current test directory.
+ */
+ public static final String CLASS_DIR
+ = System.getProperty("test.classes", ".") + FILE_SEP;
+
+ /**
+ * Package name that separates by slash.
+ */
+ public static final String PACKAGE_NAME = FILE_SEP +
+ HiBidConstants.class.getPackage().getName().replaceAll("[.]", FILE_SEP);
+
+
+ /**
+ * Java source directory.
+ */
+ public static final String SRC_DIR = System.getProperty("test.src", USER_DIR)
+ .replaceAll("\\" + System.getProperty("file.separator"), "/")
+ + PACKAGE_NAME + FILE_SEP;
+
+ /**
+ * Source XML file directory.
+ */
+ public static final String XML_DIR = SRC_DIR + "content" + FILE_SEP;
+
+ /**
+ * Golden output file directory.
+ * We pre-define all expected output in golden output file. Test verifies
+ * whether the standard output is same as content of golden file.
+ */
+ public static final String GOLDEN_DIR = SRC_DIR + "golden" + FILE_SEP;
+
+ /**
+ * Name space for account operation.
+ */
+ public static final String PORTAL_ACCOUNT_NS = "http://www.auctionportal.org/Accounts";
+}
--- a/jaxws/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/jaxws/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -284,3 +284,4 @@
84803c3be7f79d29c7dc40749d7743675f64107a jdk9-b36
90de6ecbff46386a3f9d6f7ca876e7aa6381f50a jdk9-b37
dd4ba422dba858b1c3c4b38f49a3e514be4e2790 jdk9-b38
+381bad1174c7c27352bee604535332da4ee2c556 jdk9-b39
--- a/jdk/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -281,3 +281,4 @@
cdcf2e599e42935c2d1d19a24bb19e808aeb43b5 jdk9-b36
27c3345d6dce39a22c262f30bb1f0e0b00c3709e jdk9-b37
d2d745313c81d1fc01f426983b9f784ab1f750e8 jdk9-b38
+ca6edf957fe1c6ea818530b503578e872cea7239 jdk9-b39
--- a/jdk/make/data/tzdata/VERSION Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/VERSION Mon Nov 17 12:32:27 2014 -0800
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2014i
+tzdata2014j
--- a/jdk/make/data/tzdata/africa Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/africa Mon Nov 17 12:32:27 2014 -0800
@@ -29,20 +29,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2013-02-21):
+# From Paul Eggert (2014-10-31):
#
-# A good source for time zone historical data outside the U.S. is
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Another source occasionally used is Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
@@ -88,7 +87,6 @@
# 3:00 CAST Central Africa Summer Time (no longer used)
# 3:00 SAST South Africa Summer Time (no longer used)
# 3:00 EAT East Africa Time
-# 4:00 EAST East Africa Summer Time (no longer used)
# Algeria
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -169,9 +167,7 @@
1:00 - WAT
# Comoros
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Comoro 2:53:04 - LMT 1911 Jul # Moroni, Gran Comoro
- 3:00 - EAT
+# See Africa/Nairobi.
# Democratic Republic of the Congo
# See Africa/Lagos for the western part and Africa/Maputo for the eastern.
@@ -195,9 +191,7 @@
Link Africa/Abidjan Atlantic/St_Helena # St Helena
# Djibouti
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Djibouti 2:52:36 - LMT 1911 Jul
- 3:00 - EAT
+# See Africa/Nairobi.
###############################################################################
@@ -410,27 +404,8 @@
# See Africa/Lagos.
# Eritrea
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Asmara 2:35:32 - LMT 1870
- 2:35:32 - AMT 1890 # Asmara Mean Time
- 2:35:20 - ADMT 1936 May 5 # Adis Dera MT
- 3:00 - EAT
-
# Ethiopia
-# From Paul Eggert (2014-07-31):
-# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a
-# 12-hour clock starting at our 06:00, so their "8 o'clock" is our
-# 02:00 or 14:00. Keep this in mind when you ask the time in Amharic.
-#
-# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time
-# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in
-# 1890, and that they switched to 3:00 on 1936-05-05. Perhaps 38E50
-# was for Adis Dera. Quite likely the Shanks data entries are wrong
-# anyway.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Addis_Ababa 2:34:48 - LMT 1870
- 2:35:20 - ADMT 1936 May 5 # Adis Dera MT
- 3:00 - EAT
+# See Africa/Nairobi.
# Gabon
# See Africa/Lagos.
@@ -474,6 +449,15 @@
2:30 - BEAT 1940
2:45 - BEAUT 1960
3:00 - EAT
+Link Africa/Nairobi Africa/Addis_Ababa # Ethiopia
+Link Africa/Nairobi Africa/Asmara # Eritrea
+Link Africa/Nairobi Africa/Dar_es_Salaam # Tanzania
+Link Africa/Nairobi Africa/Djibouti
+Link Africa/Nairobi Africa/Kampala # Uganda
+Link Africa/Nairobi Africa/Mogadishu # Somalia
+Link Africa/Nairobi Indian/Antananarivo # Madagascar
+Link Africa/Nairobi Indian/Comoro
+Link Africa/Nairobi Indian/Mayotte
# Lesotho
# See Africa/Johannesburg.
@@ -551,11 +535,7 @@
2:00 - EET
# Madagascar
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Antananarivo 3:10:04 - LMT 1911 Jul
- 3:00 - EAT 1954 Feb 27 23:00s
- 3:00 1:00 EAST 1954 May 29 23:00s
- 3:00 - EAT
+# See Africa/Nairobi.
# Malawi
# See Africa/Maputo.
@@ -658,9 +638,7 @@
# no information; probably like Indian/Mauritius
# Mayotte
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou
- 3:00 - EAT
+# See Africa/Nairobi.
# Morocco
# See the 'europe' file for Spanish Morocco (Africa/Ceuta).
@@ -1072,11 +1050,7 @@
# See Africa/Abidjan.
# Somalia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Mogadishu 3:01:28 - LMT 1893 Nov
- 3:00 - EAT 1931
- 2:30 - BEAT 1957
- 3:00 - EAT
+# See Africa/Nairobi.
# South Africa
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -1119,11 +1093,7 @@
# See Africa/Johannesburg.
# Tanzania
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Dar_es_Salaam 2:37:08 - LMT 1931
- 3:00 - EAT 1948
- 2:45 - BEAUT 1961
- 3:00 - EAT
+# See Africa/Nairobi.
# Togo
# See Africa/Abidjan.
@@ -1229,12 +1199,7 @@
1:00 Tunisia CE%sT
# Uganda
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Kampala 2:09:40 - LMT 1928 Jul
- 3:00 - EAT 1930
- 2:30 - BEAT 1948
- 2:45 - BEAUT 1957
- 3:00 - EAT
+# See Africa/Nairobi.
# Zambia
# Zimbabwe
--- a/jdk/make/data/tzdata/asia Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/asia Mon Nov 17 12:32:27 2014 -0800
@@ -29,20 +29,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2013-08-11):
+# From Paul Eggert (2014-10-31):
#
-# A good source for time zone historical data outside the U.S. is
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Another source occasionally used is Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
@@ -1686,44 +1685,70 @@
# Korea (North and South)
# From Annie I. Bang (2006-07-10):
-# http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp
-# The Ministry of Commerce, Industry and Energy has already
-# commissioned a research project [to reintroduce DST] and has said
-# the system may begin as early as 2008.... Korea ran a daylight
-# saving program from 1949-61 but stopped it during the 1950-53 Korean War.
+# http://www.koreaherald.com/view.php?ud=200607100012
+# Korea ran a daylight saving program from 1949-61 but stopped it
+# during the 1950-53 Korean War. The system was temporarily enforced
+# between 1987 and 1988 ...
-# From Shanks & Pottenger:
+# From Sanghyuk Jung (2014-10-29):
+# http://mm.icann.org/pipermail/tz/2014-October/021830.html
+# According to the Korean Wikipedia
+# http://ko.wikipedia.org/wiki/한국_표준시
+# [oldid=12896437 2014-09-04 08:03 UTC]
+# DST in Republic of Korea was as follows.... And I checked old
+# newspapers in Korean, all articles correspond with data in Wikipedia.
+# For example, the article in 1948 (Korean Language) proved that DST
+# started at June 1 in that year. For another example, the article in
+# 1988 said that DST started at 2:00 AM in that year.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule ROK 1960 only - May 15 0:00 1:00 D
-Rule ROK 1960 only - Sep 13 0:00 0 S
-Rule ROK 1987 1988 - May Sun>=8 0:00 1:00 D
-Rule ROK 1987 1988 - Oct Sun>=8 0:00 0 S
+Rule ROK 1948 only - Jun 1 0:00 1:00 D
+Rule ROK 1948 only - Sep 13 0:00 0 S
+Rule ROK 1949 only - Apr 3 0:00 1:00 D
+Rule ROK 1949 1951 - Sep Sun>=8 0:00 0 S
+Rule ROK 1950 only - Apr 1 0:00 1:00 D
+Rule ROK 1951 only - May 6 0:00 1:00 D
+Rule ROK 1955 only - May 5 0:00 1:00 D
+Rule ROK 1955 only - Sep 9 0:00 0 S
+Rule ROK 1956 only - May 20 0:00 1:00 D
+Rule ROK 1956 only - Sep 30 0:00 0 S
+Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D
+Rule ROK 1957 1960 - Sep Sun>=18 0:00 0 S
+Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
+Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
-# From Paul Eggert (2014-07-01):
-# The following entries are from Shanks & Pottenger, except that I
-# guessed that time zone abbreviations through 1945 followed the same
+# From Paul Eggert (2014-10-30):
+# The Korean Wikipedia entry gives the following sources for UT offsets:
+#
+# 1908: Official Journal Article No. 3994 (Edict No. 5)
+# 1912: Governor-General of Korea Official Gazette Issue No. 367
+# (Announcement No. 338)
+# 1954: Presidential Decree No. 876 (1954-03-17)
+# 1961: Law No. 676 (1961-08-07)
+# 1987: Law No. 3919 (1986-12-31)
+#
+# The Wikipedia entry also has confusing information about a change
+# to UT+9 in April 1910, but then what would be the point of the later change
+# to UT+9 on 1912-01-01? Omit the 1910 change for now.
+#
+# I guessed that time zone abbreviations through 1945 followed the same
# rules as discussed under Taiwan, with nominal switches from JST to KST
# when the respective cities were taken over by the Allies after WWII.
+#
+# For Pyongyang we have no information; guess no changes since World War II.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Seoul 8:27:52 - LMT 1890
- 8:30 - KST 1904 Dec
- 9:00 - JCST 1928
- 8:30 - KST 1932
+Zone Asia/Seoul 8:27:52 - LMT 1908 Apr 1
+ 8:30 - KST 1912 Jan 1
9:00 - JCST 1937 Oct 1
9:00 - JST 1945 Sep 8
9:00 - KST 1954 Mar 21
- 8:00 ROK K%sT 1961 Aug 10
- 8:30 - KST 1968 Oct
+ 8:30 ROK K%sT 1961 Aug 10
9:00 ROK K%sT
-Zone Asia/Pyongyang 8:23:00 - LMT 1890
- 8:30 - KST 1904 Dec
- 9:00 - JCST 1928
- 8:30 - KST 1932
+Zone Asia/Pyongyang 8:23:00 - LMT 1908 Apr 1
+ 8:30 - KST 1912 Jan 1
9:00 - JCST 1937 Oct 1
9:00 - JST 1945 Aug 24
- 9:00 - KST 1954 Mar 21
- 8:00 - KST 1961 Aug 10
9:00 - KST
###############################################################################
--- a/jdk/make/data/tzdata/australasia Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/australasia Mon Nov 17 12:32:27 2014 -0800
@@ -820,19 +820,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2013-02-21):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Another source occasionally used is Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
--- a/jdk/make/data/tzdata/europe Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/europe Mon Nov 17 12:32:27 2014 -0800
@@ -29,16 +29,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2014-05-31):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
@@ -310,6 +313,14 @@
# "Timeball on the ballast office is down. Dunsink time."
# -- James Joyce, Ulysses
+# "Countess Markievicz ... claimed that the [1916] abolition of Dublin Mean Time
+# was among various actions undertaken by the 'English' government that
+# would 'put the whole country into the SF (Sinn Féin) camp'. She claimed
+# Irish 'public feeling (was) outraged by forcing of English time on us'."
+# -- Parsons M. Dublin lost its time zone - and 25 minutes - after 1916 Rising.
+# Irish Times 2014-10-27.
+# http://www.irishtimes.com/news/politics/dublin-lost-its-time-zone-and-25-minutes-after-1916-rising-1.1977411
+
# From Joseph S. Myers (2005-01-26):
# Irish laws are available online at <http://www.irishstatutebook.ie>.
# These include various relating to legal time, for example:
@@ -617,6 +628,7 @@
Rule Russia 1993 2010 - Mar lastSun 2:00s 1:00 S
Rule Russia 1993 1995 - Sep lastSun 2:00s 0 -
Rule Russia 1996 2010 - Oct lastSun 2:00s 0 -
+# As described below, Russia's 2014 change affects Zone data, not Rule data.
# From Alexander Krivenyshev (2011-06-14):
# According to Kremlin press service, Russian President Dmitry Medvedev
--- a/jdk/make/data/tzdata/leapseconds Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/leapseconds Mon Nov 17 12:32:27 2014 -0800
@@ -33,8 +33,8 @@
# The NTP Timescale and Leap Seconds
# http://www.eecis.udel.edu/~mills/leap.html
-# The International Earth Rotation Service periodically uses leap seconds
-# to keep UTC to within 0.9 s of UT1
+# The International Earth Rotation and Reference Systems Service
+# periodically uses leap seconds to keep UTC to within 0.9 s of UT1
# (which measures the true angular orientation of the earth in space); see
# Terry J Quinn, The BIPM and the accurate measure of time,
# Proc IEEE 79, 7 (July 1991), 894-905 <http://dx.doi.org/10.1109/5.84965>.
--- a/jdk/make/data/tzdata/northamerica Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/northamerica Mon Nov 17 12:32:27 2014 -0800
@@ -1014,19 +1014,19 @@
################################################################################
-# From Paul Eggert (2006-03-22):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Other sources occasionally used include:
#
@@ -3154,13 +3154,17 @@
# From Paul Eggert (2014-08-19):
# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round. See:
# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
-# Model this as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
+# Model this as a switch from EST/EDT to AST ...
+# From Chris Walton (2014-11-04):
+# ... the TCI government appears to have delayed the switch to
+# "permanent daylight saving time" by one year....
+# http://tcweeklynews.com/time-change-to-go-ahead-this-november-p5437-127.htm
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Grand_Turk -4:44:32 - LMT 1890
-5:07:11 - KMT 1912 Feb # Kingston Mean Time
-5:00 - EST 1979
- -5:00 US E%sT 2014 Nov 2 2:00
+ -5:00 US E%sT 2015 Nov Sun>=1 2:00
-4:00 - AST
# British Virgin Is
--- a/jdk/make/data/tzdata/southamerica Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/data/tzdata/southamerica Mon Nov 17 12:32:27 2014 -0800
@@ -29,23 +29,23 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2006-03-22):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
-#
-# For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
-# http://www.jstor.org/stable/1774359
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# For data circa 1899, a common source is:
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
#
# Earlier editions of these tables used the North American style (e.g. ARST and
# ARDT for Argentine Standard and Daylight Time), but the following quote
--- a/jdk/make/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/make/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java Mon Nov 17 12:32:27 2014 -0800
@@ -95,7 +95,17 @@
obj = zones.get(zoneId);
}
if (obj == null) {
- throw new ZoneRulesException("Unknown time-zone ID: " + zoneId0);
+ // Timezone link can be located in 'backward' file and it
+ // can refer to another link, so we need to check for
+ // link one more time, before throwing an exception
+ String zoneIdBack = zoneId;
+ if (links.containsKey(zoneId)) {
+ zoneId = links.get(zoneId);
+ obj = zones.get(zoneId);
+ }
+ if (obj == null) {
+ throw new ZoneRulesException("Unknown time-zone ID: " + zoneIdBack);
+ }
}
}
if (obj instanceof ZoneRules) {
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Mon Nov 17 12:32:27 2014 -0800
@@ -1533,7 +1533,8 @@
* 0.
*
* <p> If this {@code Class} object represents a class, then this method
- * returns the public fields of the class and of all its superclasses.
+ * returns the public fields of the class and of all its superclasses and
+ * superinterfaces.
*
* <p> If this {@code Class} object represents an interface, then this
* method returns the fields of the interface and of all its
--- a/jdk/src/java.base/share/classes/java/net/Authenticator.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/java/net/Authenticator.java Mon Nov 17 12:32:27 2014 -0800
@@ -60,7 +60,7 @@
class Authenticator {
// The system-wide authenticator object. See setDefault().
- private static Authenticator theAuthenticator;
+ private static volatile Authenticator theAuthenticator;
private String requestingHost;
private InetAddress requestingSite;
--- a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java Mon Nov 17 12:32:27 2014 -0800
@@ -771,6 +771,7 @@
} // end of while
}
}
+ DatagramPacket tmp = null;
if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) {
// We have to do the filtering the old fashioned way since
// the native impl doesn't support connect or the connect
@@ -795,11 +796,13 @@
if ((!connectedAddress.equals(peekAddress)) ||
(connectedPort != peekPort)) {
// throw the packet away and silently continue
- DatagramPacket tmp = new DatagramPacket(
+ tmp = new DatagramPacket(
new byte[1024], 1024);
getImpl().receive(tmp);
if (explicitFilter) {
- bytesLeftToFilter -= tmp.getLength();
+ if (checkFiltering(tmp)) {
+ stop = true;
+ }
}
} else {
stop = true;
@@ -809,18 +812,22 @@
// If the security check succeeds, or the datagram is
// connected then receive the packet
getImpl().receive(p);
- if (explicitFilter) {
- bytesLeftToFilter -= p.getLength();
- if (bytesLeftToFilter <= 0) {
- explicitFilter = false;
- } else {
- // break out of filter, if there is no more data queued
- explicitFilter = getImpl().dataAvailable() > 0;
- }
+ if (explicitFilter && tmp == null) {
+ // packet was not filtered, account for it here
+ checkFiltering(p);
}
}
}
+ private boolean checkFiltering(DatagramPacket p) throws SocketException {
+ bytesLeftToFilter -= p.getLength();
+ if (bytesLeftToFilter <= 0 || getImpl().dataAvailable() <= 0) {
+ explicitFilter = false;
+ return true;
+ }
+ return false;
+ }
+
/**
* Gets the local address to which the socket is bound.
*
--- a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java Mon Nov 17 12:32:27 2014 -0800
@@ -28,7 +28,7 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Collection;
@@ -47,6 +47,9 @@
* <a href="../../../../technotes/guides/jar/jar.html">JAR File Specification</a>
* for more information about valid attribute names and values.
*
+ * <p>This map and its views have a predictable iteration order, namely the
+ * order that keys were inserted into the map, as with {@link LinkedHashMap}.
+ *
* @author David Connelly
* @see Manifest
* @since 1.2
@@ -71,7 +74,7 @@
* @param size the initial number of attributes
*/
public Attributes(int size) {
- map = new HashMap<>(size);
+ map = new LinkedHashMap<>(size);
}
/**
@@ -81,7 +84,7 @@
* @param attr the specified Attributes
*/
public Attributes(Attributes attr) {
- map = new HashMap<>(attr);
+ map = new LinkedHashMap<>(attr);
}
--- a/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -88,6 +88,8 @@
private int ofinish = 0;
// stream status
private boolean closed = false;
+ // The stream has been read from. False if the stream has never been read.
+ private boolean read = false;
/**
* private convenience function.
@@ -103,6 +105,7 @@
private int getMoreData() throws IOException {
if (done) return -1;
int readin = input.read(ibuffer);
+ read = true;
if (readin == -1) {
done = true;
try {
@@ -306,7 +309,11 @@
}
}
catch (BadPaddingException | IllegalBlockSizeException ex) {
- throw new IOException(ex);
+ /* If no data has been read from the stream to be en/decrypted,
+ we supress any exceptions, and close quietly. */
+ if (read) {
+ throw new IOException(ex);
+ }
}
ostart = 0;
ofinish = 0;
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Mon Nov 17 12:32:27 2014 -0800
@@ -657,9 +657,10 @@
cachedHttpClient = false;
if (!failedOnce && requests != null) {
failedOnce = true;
- if (getRequestMethod().equals("CONNECT") ||
- (httpuc.getRequestMethod().equals("POST") &&
- (!retryPostProp || streaming))) {
+ if (getRequestMethod().equals("CONNECT")
+ || streaming
+ || (httpuc.getRequestMethod().equals("POST")
+ && !retryPostProp)) {
// do not retry the request
} else {
// try once more
@@ -769,9 +770,10 @@
} else if (nread != 8) {
if (!failedOnce && requests != null) {
failedOnce = true;
- if (getRequestMethod().equals("CONNECT") ||
- (httpuc.getRequestMethod().equals("POST") &&
- (!retryPostProp || streaming))) {
+ if (getRequestMethod().equals("CONNECT")
+ || streaming
+ || (httpuc.getRequestMethod().equals("POST")
+ && !retryPostProp)) {
// do not retry the request
} else {
closeServer();
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Mon Nov 17 12:32:27 2014 -0800
@@ -752,7 +752,7 @@
}
do {
tmpBuf.clear();
- } while (read(tmpBuf) > 0);
+ } while (receive(tmpBuf) != null);
} finally {
if (blocking) {
configureBlocking(true);
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -968,7 +968,7 @@
* 1. Prefer Suite B compliant cipher suites, see RFC6460 (To be
* changed later, see below).
* 2. Prefer the stronger bulk cipher, in the order of AES_256(GCM),
- * AES_128(GCM), AES_256, AES_128, RC-4, 3DES-EDE.
+ * AES_128(GCM), AES_256, AES_128, 3DES-EDE, RC-4.
* 3. Prefer the stronger MAC algorithm, in the order of SHA384,
* SHA256, SHA, MD5.
* 4. Prefer the better performance of key exchange and digital
@@ -1087,18 +1087,6 @@
add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
0x0032, --p, K_DHE_DSS, B_AES_128, T);
- // RC-4
- add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
- 0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
- add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
- 0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
- add("SSL_RSA_WITH_RC4_128_SHA",
- 0x0005, --p, K_RSA, B_RC4_128, N);
- add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
- 0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
- add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
- 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
-
// 3DES_EDE
add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
0xC008, --p, K_ECDHE_ECDSA, B_3DES, T);
@@ -1115,6 +1103,17 @@
add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
0x0013, --p, K_DHE_DSS, B_3DES, N);
+ // RC-4
+ add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ 0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
+ add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ 0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
+ add("SSL_RSA_WITH_RC4_128_SHA",
+ 0x0005, --p, K_RSA, B_RC4_128, N);
+ add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ 0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
+ add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
+ 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
add("SSL_RSA_WITH_RC4_128_MD5",
0x0004, --p, K_RSA, B_RC4_128, N);
@@ -1134,7 +1133,7 @@
* 2. If a cipher suite has been obsoleted, we put it at the end of
* the list.
* 3. Prefer the stronger bulk cipher, in the order of AES_256,
- * AES_128, RC-4, 3DES-EDE, DES, RC4_40, DES40, NULL.
+ * AES_128, 3DES-EDE, RC-4, DES, DES40, RC4_40, NULL.
* 4. Prefer the stronger MAC algorithm, in the order of SHA384,
* SHA256, SHA, MD5.
* 5. Prefer the better performance of key exchange and digital
@@ -1162,15 +1161,40 @@
add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
0x0034, --p, K_DH_ANON, B_AES_128, N);
+ add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+ 0xC017, --p, K_ECDH_ANON, B_3DES, N);
+ add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
+ 0x001b, --p, K_DH_ANON, B_3DES, N);
+
add("TLS_ECDH_anon_WITH_RC4_128_SHA",
0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
add("SSL_DH_anon_WITH_RC4_128_MD5",
0x0018, --p, K_DH_ANON, B_RC4_128, N);
- add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
- 0xC017, --p, K_ECDH_ANON, B_3DES, N);
- add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
- 0x001b, --p, K_DH_ANON, B_3DES, N);
+ // weak cipher suites obsoleted in TLS 1.2
+ add("SSL_RSA_WITH_DES_CBC_SHA",
+ 0x0009, --p, K_RSA, B_DES, N, tls12);
+ add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ 0x0015, --p, K_DHE_RSA, B_DES, N, tls12);
+ add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ 0x0012, --p, K_DHE_DSS, B_DES, N, tls12);
+ add("SSL_DH_anon_WITH_DES_CBC_SHA",
+ 0x001a, --p, K_DH_ANON, B_DES, N, tls12);
+
+ // weak cipher suites obsoleted in TLS 1.1
+ add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0008, --p, K_RSA_EXPORT, B_DES_40, N, tls11);
+ add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0014, --p, K_DHE_RSA, B_DES_40, N, tls11);
+ add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0011, --p, K_DHE_DSS, B_DES_40, N, tls11);
+ add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ 0x0019, --p, K_DH_ANON, B_DES_40, N, tls11);
+
+ add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ 0x0003, --p, K_RSA_EXPORT, B_RC4_40, N, tls11);
+ add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+ 0x0017, --p, K_DH_ANON, B_RC4_40, N, tls11);
add("TLS_RSA_WITH_NULL_SHA256",
0x003b, --p, K_RSA, B_NULL, N, max, tls12, P_SHA256);
@@ -1189,52 +1213,27 @@
add("SSL_RSA_WITH_NULL_MD5",
0x0001, --p, K_RSA, B_NULL, N);
- // weak cipher suites obsoleted in TLS 1.2
- add("SSL_RSA_WITH_DES_CBC_SHA",
- 0x0009, --p, K_RSA, B_DES, N, tls12);
- add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
- 0x0015, --p, K_DHE_RSA, B_DES, N, tls12);
- add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
- 0x0012, --p, K_DHE_DSS, B_DES, N, tls12);
- add("SSL_DH_anon_WITH_DES_CBC_SHA",
- 0x001a, --p, K_DH_ANON, B_DES, N, tls12);
-
- // weak cipher suites obsoleted in TLS 1.1
- add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
- 0x0003, --p, K_RSA_EXPORT, B_RC4_40, N, tls11);
- add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
- 0x0017, --p, K_DH_ANON, B_RC4_40, N, tls11);
-
- add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
- 0x0008, --p, K_RSA_EXPORT, B_DES_40, N, tls11);
- add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
- 0x0014, --p, K_DHE_RSA, B_DES_40, N, tls11);
- add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
- 0x0011, --p, K_DHE_DSS, B_DES_40, N, tls11);
- add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
- 0x0019, --p, K_DH_ANON, B_DES_40, N, tls11);
-
// Supported Kerberos ciphersuites from RFC2712
+ add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
+ 0x001f, --p, K_KRB5, B_3DES, N);
+ add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
+ 0x0023, --p, K_KRB5, B_3DES, N);
add("TLS_KRB5_WITH_RC4_128_SHA",
0x0020, --p, K_KRB5, B_RC4_128, N);
add("TLS_KRB5_WITH_RC4_128_MD5",
0x0024, --p, K_KRB5, B_RC4_128, N);
- add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
- 0x001f, --p, K_KRB5, B_3DES, N);
- add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
- 0x0023, --p, K_KRB5, B_3DES, N);
add("TLS_KRB5_WITH_DES_CBC_SHA",
0x001e, --p, K_KRB5, B_DES, N, tls12);
add("TLS_KRB5_WITH_DES_CBC_MD5",
0x0022, --p, K_KRB5, B_DES, N, tls12);
+ add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
+ 0x0026, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
+ add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
+ 0x0029, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
- add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
- 0x0026, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
- add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
- 0x0029, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
/*
* Other values from the TLS Cipher Suite Registry, as of August 2010.
--- a/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c Mon Nov 17 12:32:27 2014 -0800
@@ -32,9 +32,11 @@
#include "java_net_AbstractPlainDatagramSocketImpl.h"
-static jfieldID IO_fd_fdID;
+static jfieldID IO_fd_fdID = NULL;
+static jfieldID apdsi_fdID = NULL;
-static jfieldID apdsi_fdID;
+static jfieldID apdsi_fd1ID = NULL;
+static jclass two_stacks_clazz = NULL;
/*
@@ -48,10 +50,21 @@
apdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
"Ljava/io/FileDescriptor;");
CHECK_NULL(apdsi_fdID);
-
IO_fd_fdID = NET_GetFileDescriptorID(env);
CHECK_NULL(IO_fd_fdID);
+ two_stacks_clazz = (*env)->FindClass(env, "java/net/TwoStacksPlainDatagramSocketImpl");
+ CHECK_NULL(two_stacks_clazz);
+
+ /* Handle both TwoStacks and DualStack here */
+
+ if (JNU_Equals(env, cls, two_stacks_clazz)) {
+ /* fd1 present only in TwoStack.. */
+ apdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1",
+ "Ljava/io/FileDescriptor;");
+ CHECK_NULL(apdsi_fd1ID);
+ }
+
JNU_CHECK_EXCEPTION(env);
}
@@ -63,20 +76,38 @@
JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable
(JNIEnv *env, jobject this) {
SOCKET fd;
- int retval;
-
+ SOCKET fd1;
+ int rv = -1, rv1 = -1;
jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID);
- if (IS_NULL(fdObj)) {
+ if (!IS_NULL(fdObj)) {
+ int retval = 0;
+ fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ rv = ioctlsocket(fd, FIONREAD, &retval);
+ if (retval > 0) {
+ return retval;
+ }
+ }
+
+ if (!IS_NULL(apdsi_fd1ID)) {
+ /* TwoStacks */
+ jobject fd1Obj = (*env)->GetObjectField(env, this, apdsi_fd1ID);
+ if (!IS_NULL(fd1Obj)) {
+ int retval = 0;
+ fd1 = (SOCKET)(*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
+ rv1 = ioctlsocket(fd1, FIONREAD, &retval);
+ if (retval > 0) {
+ return retval;
+ }
+ }
+ }
+
+ if (rv < 0 && rv1 < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Socket closed");
+ "Socket closed");
return -1;
}
- fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID);
- if (ioctlsocket(fd, FIONREAD, &retval) < 0) {
- return -1;
- }
- return retval;
+ return 0;
}
--- a/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java Mon Nov 17 12:32:27 2014 -0800
@@ -1882,6 +1882,9 @@
public synchronized void setWindowDeactivationTime(Window w, long time) {
AppContext ctx = getAppContext(w);
+ if (ctx == null) {
+ return;
+ }
@SuppressWarnings("unchecked")
WeakHashMap<Window, Long> map = (WeakHashMap<Window, Long>)ctx.get(DEACTIVATION_TIMES_MAP_KEY);
if (map == null) {
@@ -1893,6 +1896,9 @@
public synchronized long getWindowDeactivationTime(Window w) {
AppContext ctx = getAppContext(w);
+ if (ctx == null) {
+ return -1;
+ }
@SuppressWarnings("unchecked")
WeakHashMap<Window, Long> map = (WeakHashMap<Window, Long>)ctx.get(DEACTIVATION_TIMES_MAP_KEY);
if (map == null) {
--- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/KeystoreImpl.m Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/jdk.deploy.osx/macosx/native/libosx/KeystoreImpl.m Mon Nov 17 12:32:27 2014 -0800
@@ -300,11 +300,21 @@
// Make a java array of certificate data from the chain.
jclass byteArrayClass = (*env)->FindClass(env, "[B");
+ if (byteArrayClass == NULL) {
+ goto errOut;
+ }
jobjectArray javaCertArray = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
+ // Cleanup first then check for a NULL return code
(*env)->DeleteLocalRef(env, byteArrayClass);
+ if (javaCertArray == NULL) {
+ goto errOut;
+ }
// And, make an array of the certificate refs.
jlongArray certRefArray = (*env)->NewLongArray(env, certCount);
+ if (certRefArray == NULL) {
+ goto errOut;
+ }
SecCertificateRef currCertRef = NULL;
@@ -319,6 +329,9 @@
bzero(&currCertData, sizeof(CSSM_DATA));
err = SecCertificateGetData(currCertRef, &currCertData);
jbyteArray encodedCertData = (*env)->NewByteArray(env, currCertData.Length);
+ if (encodedCertData == NULL) {
+ goto errOut;
+ }
(*env)->SetByteArrayRegion(env, encodedCertData, 0, currCertData.Length, (jbyte *)currCertData.Data);
(*env)->SetObjectArrayElement(env, javaCertArray, i, encodedCertData);
jlong certRefElement = ptr_to_jlong(currCertRef);
@@ -331,6 +344,9 @@
// Find the label. It's a 'blob', but we interpret as characters.
jstring alias = getLabelFromItem(env, (SecKeychainItemRef)certificate);
+ if (alias == NULL) {
+ goto errOut;
+ }
// Find the creation date.
jlong creationDate = getModDateFromItem(env, (SecKeychainItemRef)certificate);
@@ -341,6 +357,7 @@
}
} while (searchResult == noErr);
+errOut:
if (identitySearch != NULL) {
CFRelease(identitySearch);
}
@@ -363,10 +380,16 @@
CSSM_DATA currCertificate;
err = SecCertificateGetData(certRef, &currCertificate);
jbyteArray certData = (*env)->NewByteArray(env, currCertificate.Length);
+ if (certData == NULL) {
+ goto errOut;
+ }
(*env)->SetByteArrayRegion(env, certData, 0, currCertificate.Length, (jbyte *)currCertificate.Data);
// Find the label. It's a 'blob', but we interpret as characters.
jstring alias = getLabelFromItem(env, theItem);
+ if (alias == NULL) {
+ goto errOut;
+ }
// Find the creation date.
jlong creationDate = getModDateFromItem(env, theItem);
@@ -377,6 +400,7 @@
}
} while (searchResult == noErr);
+errOut:
if (keychainItemSearch != NULL) {
CFRelease(keychainItemSearch);
}
@@ -405,6 +429,9 @@
if (passwordLen > 0) {
passwordChars = (*env)->GetCharArrayElements(env, passwordObj, NULL);
+ if (passwordChars == NULL) {
+ goto errOut;
+ }
passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
}
}
@@ -424,9 +451,13 @@
if (err == noErr) {
CFIndex size = CFDataGetLength(exportedData);
returnValue = (*env)->NewByteArray(env, size);
+ if (returnValue == NULL) {
+ goto errOut;
+ }
(*env)->SetByteArrayRegion(env, returnValue, 0, size, (jbyte *)CFDataGetBytePtr(exportedData));
}
+errOut:
if (exportedData) CFRelease(exportedData);
if (passwordStrRef) CFRelease(passwordStrRef);
@@ -467,6 +498,9 @@
jsize dataSize = (*env)->GetArrayLength(env, rawDataObj);
jbyte *rawData = (*env)->GetByteArrayElements(env, rawDataObj, NULL);
+ if (rawData == NULL) {
+ goto errOut;
+ }
CFDataRef cfDataToImport = CFDataCreate(kCFAllocatorDefault, (UInt8 *)rawData, dataSize);
CFArrayRef createdItems = NULL;
@@ -523,6 +557,8 @@
CFRelease(createdItems);
}
+errOut: ;
+
JNF_COCOA_EXIT(env);
return returnValue;
--- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -82,6 +82,7 @@
private Timer timer, timer1;
private Logger logger;
+ private Thread dispatcherThread;
ServerImpl (
HttpServer wrapper, String protocol, InetSocketAddress addr, int backlog
@@ -141,9 +142,9 @@
if (executor == null) {
executor = new DefaultExecutor();
}
- Thread t = new Thread (dispatcher);
+ dispatcherThread = new Thread (dispatcher);
started = true;
- t.start();
+ dispatcherThread.start();
}
public void setExecutor (Executor executor) {
@@ -205,6 +206,12 @@
if (timer1Enabled) {
timer1.cancel();
}
+ try {
+ dispatcherThread.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ logger.log(Level.FINER, "ServerImpl.stop: ", e);
+ }
}
Dispatcher dispatcher;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/net/httpserver/SimpleHttpServerTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
+ * @bug 8015692
+ * @summary Test HttpServer instantiation, start, and stop repeated in a loop
+ * Testing for Bind exception on Windows
+ */
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+
+import com.sun.net.httpserver.HttpServer;
+
+
+public class SimpleHttpServerTest {
+
+ public static void main(String[] args) throws Exception {
+
+ System.out.println(System.getProperty("java.version"));
+ InetSocketAddress serverAddr = new InetSocketAddress(0);
+ HttpServer server = HttpServer.create(serverAddr, 0);
+ final int serverPort = server.getAddress().getPort();
+ server.start();
+ server.stop(0);
+ serverAddr = new InetSocketAddress(serverPort);
+ int exceptionCount = 0;
+ System.out.println("Using serverPort == " + serverPort);
+ for (int i = 0; i < 100; i++) {
+ try {
+ server = HttpServer.create(serverAddr, 0);
+ server.start();
+ server.stop(0);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ exceptionCount++;
+ }
+ }
+ if (exceptionCount > 0) {
+ throw new RuntimeException("Test Failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Class/getFields/Sanity.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2014 Google, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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 8063147
+ * @summary Tests for Class.getFields().
+ * @run testng Sanity
+ */
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class Sanity {
+ public interface EmptyInterface {}
+ class EmptyClass {}
+ interface BI1 {
+ public int i = 1;
+ int j = 2;
+ }
+ interface BI2 {
+ int k = 1;
+ }
+ public interface DI extends BI1, BI2, EmptyInterface {
+ int m = 5;
+ }
+ interface DDI extends DI {
+ int n = 6;
+ }
+
+ public class D extends EmptyClass {
+ public int publicDField;
+ protected int protectedDField;
+ private int privateDField;
+ }
+
+ class DD extends D {
+ public int publicDDField;
+ protected int protectedDDField;
+ private int privateDDField;
+ }
+
+ public class Universe extends DD implements DDI {
+ public int publicUniverseField;
+ protected int protectedUniverseField;
+ private int privateUniverseField;
+ }
+
+ void assertContainsNoFields(Class<?> clazz) {
+ assertEquals(clazz.getFields().length, 0);
+ }
+
+ @Test
+ public void primitiveTypesHaveNoFields() throws Exception {
+ assertContainsNoFields(byte.class);
+ assertContainsNoFields(char.class);
+ assertContainsNoFields(short.class);
+ assertContainsNoFields(int.class);
+ assertContainsNoFields(long.class);
+ assertContainsNoFields(boolean.class);
+ assertContainsNoFields(void.class);
+ assertContainsNoFields(double.class);
+ assertContainsNoFields(float.class);
+ }
+
+ @Test
+ public void arrayTypesHaveNoFields() throws Exception {
+ assertContainsNoFields(byte[].class);
+ assertContainsNoFields(Object[].class);
+ assertContainsNoFields(java.util.Map[].class);
+ assertContainsNoFields(java.util.HashMap[].class);
+ }
+
+ @Test
+ public void emptyInterfacesHaveNoFields() throws Exception {
+ assertContainsNoFields(EmptyInterface.class);
+ }
+
+ @Test
+ public void emptyClassesHaveNoFields() throws Exception {
+ assertContainsNoFields(EmptyClass.class);
+ class EmptyLocalClass {}
+ assertContainsNoFields(EmptyLocalClass.class);
+ }
+
+ void assertContainsFields(Class<?> clazz, int count) {
+ assertEquals(clazz.getFields().length, count);
+ }
+
+ @Test
+ public void checkFieldCounts() throws Exception {
+ assertContainsFields(BI1.class, 2);
+ assertContainsFields(BI2.class, 1);
+ assertContainsFields(DI.class, 4);
+ assertContainsFields(DDI.class, 5);
+ assertContainsFields(D.class, 1);
+ assertContainsFields(DD.class, 2);
+ assertContainsFields(Universe.class, 8);
+ }
+
+ void assertContainsFields(Class<?> derived, Class<?> base) {
+ List<Field> derivedFields = Arrays.asList(derived.getFields());
+ List<Field> baseFields = Arrays.asList(base.getFields());
+ assertTrue(derivedFields.containsAll(baseFields));
+ }
+
+ List<Class<?>> directSupers(Class<?> clazz) {
+ List<Class<?>> directSupers = new ArrayList<>();
+ directSupers.addAll(Arrays.asList(clazz.getInterfaces()));
+ if (clazz.getSuperclass() != null) {
+ directSupers.add(clazz.getSuperclass());
+ }
+ return directSupers;
+ }
+
+ void assertContainsSuperFields(Class<?> clazz) {
+ for (Class<?> directSuper : directSupers(clazz)) {
+ assertContainsFields(clazz, directSuper);
+ }
+ }
+
+ List<Class<?>> testClasses() {
+ List<Class<?>> testClasses = new ArrayList<>();
+ testClasses.add(Sanity.class);
+ testClasses.addAll(Arrays.asList(Sanity.class.getDeclaredClasses()));
+ assertEquals(testClasses.size(), 10);
+ return testClasses;
+ }
+
+ @Test
+ public void fieldsAreInheritedFromSupers() throws Exception {
+ for (Class clazz : testClasses()) {
+ assertContainsSuperFields(clazz);
+ }
+ }
+
+ @Test
+ public void getFieldIsConsistentWithGetFields() throws Exception {
+ for (Class clazz : testClasses()) {
+ for (Field field : clazz.getFields()) {
+ assertEquals(field, clazz.getField(field.getName()));
+ }
+ }
+ }
+}
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Mon Nov 17 12:32:27 2014 -0800
@@ -2269,9 +2269,10 @@
fail("Test failed: Process exited prematurely");
}
long end = System.nanoTime();
- // give waitFor(timeout) a wide berth (200ms)
- // Old AIX machines my need a little longer.
- if ((end - start) > 200000000L * (AIX.is() ? 2 : 1))
+ // give waitFor(timeout) a wide berth (2s)
+ System.out.printf(" waitFor process: delta: %d%n",(end - start) );
+
+ if ((end - start) > TimeUnit.SECONDS.toNanos(2))
fail("Test failed: waitFor took too long (" + (end - start) + "ns)");
p.destroy();
@@ -2295,19 +2296,23 @@
final Process p = new ProcessBuilder(childArgs).start();
long start = System.nanoTime();
- p.waitFor(1000, TimeUnit.MILLISECONDS);
+ p.waitFor(10, TimeUnit.MILLISECONDS);
long end = System.nanoTime();
- if ((end - start) < 500000000)
+ if ((end - start) < TimeUnit.MILLISECONDS.toNanos(10))
fail("Test failed: waitFor didn't take long enough (" + (end - start) + "ns)");
p.destroy();
start = System.nanoTime();
- p.waitFor(1000, TimeUnit.MILLISECONDS);
+ p.waitFor(8, TimeUnit.SECONDS);
end = System.nanoTime();
- if ((end - start) > 900000000)
- fail("Test failed: waitFor took too long on a dead process. (" + (end - start) + "ns)");
+
+ int exitValue = p.exitValue();
+
+ if ((end - start) > TimeUnit.SECONDS.toNanos(7))
+ fail("Test failed: waitFor took too long on a dead process. (" + (end - start) + "ns)"
+ + ", exitValue: " + exitValue);
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
--- a/jdk/test/java/util/Formatter/Basic-X.java.template Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/Basic-X.java.template Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -572,6 +580,14 @@
test("%(10d", " (12345)", negate(oneToFive));
test("%-10d", "12345 ", oneToFive);
test("%-10d", "-12345 ", negate(oneToFive));
+ // , variations:
+ test("% ,d", " 12,345", oneToFive);
+ test("% ,d", "-12,345", negate(oneToFive));
+ test("%0,10d", "000012,345", oneToFive);
+ test("%0,10d", "-00012,345", negate(oneToFive));
+ test("%(,10d", " (12,345)", negate(oneToFive));
+ test("%-,10d", "12,345 ", oneToFive);
+ test("%-,10d", "-12,345 ", negate(oneToFive));
#else[short]
#if[prim]
@@ -594,6 +610,16 @@
test("%(10d", " (1234567)", negate(oneToSeven));
test("%-10d", "1234567 ", oneToSeven);
test("%-10d", "-1234567 ", negate(oneToSeven));
+ // , variations:
+ test("% ,d", " 1,234,567", oneToSeven);
+ test("% ,d", "-1,234,567", negate(oneToSeven));
+ test("%+,10d", "+1,234,567", oneToSeven);
+ test("%0,10d", "01,234,567", oneToSeven);
+ test("%0,10d", "-1,234,567", negate(oneToSeven));
+ test("%(,10d", "(1,234,567)", negate(oneToSeven));
+ test("%-,10d", "1,234,567 ", oneToSeven);
+ test("%-,10d", "-1,234,567", negate(oneToSeven));
+
#end[prim]
#end[short]
#end[byte]
@@ -781,6 +807,14 @@
test("%+d", "-1234567", new BigInteger("-1234567", 10));
test("%-10d", "1234567 ", new BigInteger("1234567", 10));
test("%-10d", "-1234567 ", new BigInteger("-1234567", 10));
+ // , variations:
+ test("%0,10d", "01,234,567", new BigInteger("1234567", 10));
+ test("%0,10d", "-1,234,567", new BigInteger("-1234567", 10));
+ test("%(,10d", "(1,234,567)", new BigInteger("-1234567", 10));
+ test("%+,d", "+1,234,567", new BigInteger("1234567", 10));
+ test("%+,d", "-1,234,567", new BigInteger("-1234567", 10));
+ test("%-,10d", "1,234,567 ", new BigInteger("1234567", 10));
+ test("%-,10d", "-1,234,567", new BigInteger("-1234567", 10));
//---------------------------------------------------------------------
// %o - BigInteger
@@ -1039,6 +1073,14 @@
test("%3.0f", "1000000", 1000000.00);
test("%3.0f", "10000000", 10000000.00);
test("%3.0f", "100000000", 100000000.00);
+ test("%10.0f", " 1000000", 1000000.00);
+ test("%,10.0f", " 1,000,000", 1000000.00);
+ test("%,10.1f", "1,000,000.0", 1000000.00);
+ test("%,3.0f", "1,000,000", 1000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
#if[BigDecimal]
//---------------------------------------------------------------------
// %f - BigDecimal
--- a/jdk/test/java/util/Formatter/BasicBigDecimal.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -831,6 +839,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %s - BigDecimal
//---------------------------------------------------------------------
@@ -1039,6 +1073,14 @@
test("%3.0f", "1000000", 1000000.00);
test("%3.0f", "10000000", 10000000.00);
test("%3.0f", "100000000", 100000000.00);
+ test("%10.0f", " 1000000", 1000000.00);
+ test("%,10.0f", " 1,000,000", 1000000.00);
+ test("%,10.1f", "1,000,000.0", 1000000.00);
+ test("%,3.0f", "1,000,000", 1000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
//---------------------------------------------------------------------
// %f - BigDecimal
@@ -1351,6 +1393,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %f, %e, %g, %a - Boundaries
//---------------------------------------------------------------------
--- a/jdk/test/java/util/Formatter/BasicBigInteger.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicBigInteger.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -754,6 +762,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// BigInteger - errors
//---------------------------------------------------------------------
@@ -781,6 +807,14 @@
test("%+d", "-1234567", new BigInteger("-1234567", 10));
test("%-10d", "1234567 ", new BigInteger("1234567", 10));
test("%-10d", "-1234567 ", new BigInteger("-1234567", 10));
+ // , variations:
+ test("%0,10d", "01,234,567", new BigInteger("1234567", 10));
+ test("%0,10d", "-1,234,567", new BigInteger("-1234567", 10));
+ test("%(,10d", "(1,234,567)", new BigInteger("-1234567", 10));
+ test("%+,d", "+1,234,567", new BigInteger("1234567", 10));
+ test("%+,d", "-1,234,567", new BigInteger("-1234567", 10));
+ test("%-,10d", "1,234,567 ", new BigInteger("1234567", 10));
+ test("%-,10d", "-1,234,567", new BigInteger("-1234567", 10));
//---------------------------------------------------------------------
// %o - BigInteger
@@ -1573,6 +1607,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicBoolean.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicBoolean.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -1573,6 +1581,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicBooleanObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicBooleanObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -1573,6 +1581,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicByte.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicByte.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -597,6 +605,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %d - errors
//---------------------------------------------------------------------
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicByteObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicByteObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -597,6 +605,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %d - errors
//---------------------------------------------------------------------
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicChar.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicChar.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -1573,6 +1581,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicCharObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicCharObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -1573,6 +1581,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicDateTime.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicDateTime.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -1573,6 +1581,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicDouble.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicDouble.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -36,6 +36,9 @@
import java.text.DateFormatSymbols;
import java.util.*;
+import sun.misc.DoubleConsts;
+
+
import static java.util.Calendar.*;
@@ -48,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -55,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -859,6 +870,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %s - double
//---------------------------------------------------------------------
@@ -1036,6 +1073,14 @@
test("%3.0f", "1000000", 1000000.00);
test("%3.0f", "10000000", 10000000.00);
test("%3.0f", "100000000", 100000000.00);
+ test("%10.0f", " 1000000", 1000000.00);
+ test("%,10.0f", " 1,000,000", 1000000.00);
+ test("%,10.1f", "1,000,000.0", 1000000.00);
+ test("%,3.0f", "1,000,000", 1000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
@@ -1310,12 +1355,12 @@
test("%.1a", "-0x1.0p0", -1.0);
test("%.11a", "0x1.80000000000p1", 3.0);
test("%.1a", "0x1.8p1", 3.0);
- test("%.11a", "0x1.00000000000p-1022", Double.MIN_NORMAL);
- test("%.1a", "0x1.0p-1022", Double.MIN_NORMAL);
+ test("%.11a", "0x1.00000000000p-1022", DoubleConsts.MIN_NORMAL);
+ test("%.1a", "0x1.0p-1022", DoubleConsts.MIN_NORMAL);
test("%.11a", "0x1.00000000000p-1022",
- Math.nextDown(Double.MIN_NORMAL));
+ Math.nextDown(DoubleConsts.MIN_NORMAL));
test("%.1a", "0x1.0p-1022",
- Math.nextDown(Double.MIN_NORMAL));
+ Math.nextDown(DoubleConsts.MIN_NORMAL));
test("%.11a", "0x1.ffffffffffep-1023", 0x0.fffffffffffp-1022);
test("%.1a", "0x1.0p-1022", 0x0.fffffffffffp-1022);
test("%.30a", "0x0.000000000000100000000000000000p-1022", Double.MIN_VALUE);
--- a/jdk/test/java/util/Formatter/BasicDoubleObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicDoubleObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -872,6 +880,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %s - Double
//---------------------------------------------------------------------
@@ -1039,6 +1073,14 @@
test("%3.0f", "1000000", 1000000.00);
test("%3.0f", "10000000", 10000000.00);
test("%3.0f", "100000000", 100000000.00);
+ test("%10.0f", " 1000000", 1000000.00);
+ test("%,10.0f", " 1,000,000", 1000000.00);
+ test("%,10.1f", "1,000,000.0", 1000000.00);
+ test("%,3.0f", "1,000,000", 1000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
@@ -1351,6 +1393,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %f, %e, %g, %a - Boundaries
//---------------------------------------------------------------------
--- a/jdk/test/java/util/Formatter/BasicFloat.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicFloat.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -842,6 +850,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %s - float
//---------------------------------------------------------------------
@@ -1039,6 +1073,14 @@
test("%3.0f", "1000000", 1000000.00);
test("%3.0f", "10000000", 10000000.00);
test("%3.0f", "100000000", 100000000.00);
+ test("%10.0f", " 1000000", 1000000.00);
+ test("%,10.0f", " 1,000,000", 1000000.00);
+ test("%,10.1f", "1,000,000.0", 1000000.00);
+ test("%,3.0f", "1,000,000", 1000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
@@ -1351,6 +1393,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %f, %e, %g, %a - Boundaries
//---------------------------------------------------------------------
--- a/jdk/test/java/util/Formatter/BasicFloatObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicFloatObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -852,6 +860,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %s - Float
//---------------------------------------------------------------------
@@ -1039,6 +1073,14 @@
test("%3.0f", "1000000", 1000000.00);
test("%3.0f", "10000000", 10000000.00);
test("%3.0f", "100000000", 100000000.00);
+ test("%10.0f", " 1000000", 1000000.00);
+ test("%,10.0f", " 1,000,000", 1000000.00);
+ test("%,10.1f", "1,000,000.0", 1000000.00);
+ test("%,3.0f", "1,000,000", 1000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
+ test("%,3.0f", "10,000,000", 10000000.00);
+ test("%,3.0f", "100,000,000", 100000000.00);
@@ -1351,6 +1393,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %f, %e, %g, %a - Boundaries
//---------------------------------------------------------------------
--- a/jdk/test/java/util/Formatter/BasicInt.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicInt.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -575,6 +583,14 @@
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %d - int and long
//---------------------------------------------------------------------
@@ -594,6 +610,16 @@
test("%(10d", " (1234567)", negate(oneToSeven));
test("%-10d", "1234567 ", oneToSeven);
test("%-10d", "-1234567 ", negate(oneToSeven));
+ // , variations:
+ test("% ,d", " 1,234,567", oneToSeven);
+ test("% ,d", "-1,234,567", negate(oneToSeven));
+ test("%+,10d", "+1,234,567", oneToSeven);
+ test("%0,10d", "01,234,567", oneToSeven);
+ test("%0,10d", "-1,234,567", negate(oneToSeven));
+ test("%(,10d", "(1,234,567)", negate(oneToSeven));
+ test("%-,10d", "1,234,567 ", oneToSeven);
+ test("%-,10d", "-1,234,567", negate(oneToSeven));
+
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicIntObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicIntObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -597,6 +605,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %d - errors
//---------------------------------------------------------------------
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicLong.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicLong.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -575,6 +583,14 @@
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %d - int and long
//---------------------------------------------------------------------
@@ -594,6 +610,16 @@
test("%(10d", " (1234567)", negate(oneToSeven));
test("%-10d", "1234567 ", oneToSeven);
test("%-10d", "-1234567 ", negate(oneToSeven));
+ // , variations:
+ test("% ,d", " 1,234,567", oneToSeven);
+ test("% ,d", "-1,234,567", negate(oneToSeven));
+ test("%+,10d", "+1,234,567", oneToSeven);
+ test("%0,10d", "01,234,567", oneToSeven);
+ test("%0,10d", "-1,234,567", negate(oneToSeven));
+ test("%(,10d", "(1,234,567)", negate(oneToSeven));
+ test("%-,10d", "1,234,567 ", oneToSeven);
+ test("%-,10d", "-1,234,567", negate(oneToSeven));
+
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicLongObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicLongObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -597,6 +605,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %d - errors
//---------------------------------------------------------------------
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicShort.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicShort.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -572,6 +580,24 @@
test("%(10d", " (12345)", negate(oneToFive));
test("%-10d", "12345 ", oneToFive);
test("%-10d", "-12345 ", negate(oneToFive));
+ // , variations:
+ test("% ,d", " 12,345", oneToFive);
+ test("% ,d", "-12,345", negate(oneToFive));
+ test("%0,10d", "000012,345", oneToFive);
+ test("%0,10d", "-00012,345", negate(oneToFive));
+ test("%(,10d", " (12,345)", negate(oneToFive));
+ test("%-,10d", "12,345 ", oneToFive);
+ test("%-,10d", "-12,345 ", negate(oneToFive));
+
+
+
+
+
+
+
+
+
+
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/BasicShortObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/BasicShortObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, 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
@@ -51,6 +51,10 @@
Formatter f = new Formatter(new StringBuilder(), Locale.US);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), Locale.US);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(Locale l, String fs, String exp, Object ... args)
@@ -58,6 +62,10 @@
Formatter f = new Formatter(new StringBuilder(), l);
f.format(fs, args);
ck(fs, exp, f.toString());
+
+ f = new Formatter(new StringBuilder(), l);
+ f.format("foo " + fs + " bar", args);
+ ck(fs, "foo " + exp + " bar", f.toString());
}
private static void test(String fs, Object ... args) {
@@ -597,6 +605,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %d - errors
//---------------------------------------------------------------------
@@ -1573,6 +1599,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
//---------------------------------------------------------------------
// %t
//
--- a/jdk/test/java/util/Formatter/genBasic.sh Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/java/util/Formatter/genBasic.sh Mon Nov 17 12:32:27 2014 -0800
@@ -23,7 +23,7 @@
# questions.
#
-javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java
+javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java
gen() {
# if [ $3 = "true" ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/Attributes/IterationOrder.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2014 Google, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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 8062194
+ * @summary Ensure Attribute iteration order is the insertion order.
+ */
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.Attributes.Name;
+
+public class IterationOrder {
+ static void checkOrder(Attributes.Name k0, String v0,
+ Attributes.Name k1, String v1,
+ Attributes.Name k2, String v2) {
+ Attributes x = new Attributes();
+ x.put(k0, v0);
+ x.put(k1, v1);
+ x.put(k2, v2);
+ Map.Entry<?,?>[] entries
+ = x.entrySet().toArray(new Map.Entry<?,?>[3]);
+ if (!(entries.length == 3
+ && entries[0].getKey() == k0
+ && entries[0].getValue() == v0
+ && entries[1].getKey() == k1
+ && entries[1].getValue() == v1
+ && entries[2].getKey() == k2
+ && entries[2].getValue() == v2)) {
+ throw new AssertionError(Arrays.toString(entries));
+ }
+
+ Object[] keys = x.keySet().toArray();
+ if (!(keys.length == 3
+ && keys[0] == k0
+ && keys[1] == k1
+ && keys[2] == k2)) {
+ throw new AssertionError(Arrays.toString(keys));
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ Attributes.Name k0 = Name.MANIFEST_VERSION;
+ Attributes.Name k1 = Name.MAIN_CLASS;
+ Attributes.Name k2 = Name.SEALED;
+ String v0 = "42.0";
+ String v1 = "com.google.Hello";
+ String v2 = "yes";
+ checkOrder(k0, v0, k1, v1, k2, v2);
+ checkOrder(k1, v1, k0, v0, k2, v2);
+ checkOrder(k2, v2, k1, v1, k0, v0);
+ }
+}
--- a/jdk/test/javax/net/ssl/sanity/ciphersuites/CipherSuitesInOrder.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/javax/net/ssl/sanity/ciphersuites/CipherSuitesInOrder.java Mon Nov 17 12:32:27 2014 -0800
@@ -85,11 +85,6 @@
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
- "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
- "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
- "SSL_RSA_WITH_RC4_128_SHA",
- "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
- "TLS_ECDH_RSA_WITH_RC4_128_SHA",
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
@@ -98,6 +93,12 @@
"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+
+ "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ "SSL_RSA_WITH_RC4_128_SHA",
+ "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ "TLS_ECDH_RSA_WITH_RC4_128_SHA",
"SSL_RSA_WITH_RC4_128_MD5",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
@@ -111,10 +112,23 @@
"TLS_DH_anon_WITH_AES_128_CBC_SHA256",
"TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
"TLS_DH_anon_WITH_AES_128_CBC_SHA",
+ "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+ "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
"TLS_ECDH_anon_WITH_RC4_128_SHA",
"SSL_DH_anon_WITH_RC4_128_MD5",
- "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
- "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
+
+ "SSL_RSA_WITH_DES_CBC_SHA",
+ "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "SSL_DH_anon_WITH_DES_CBC_SHA",
+ "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+
+ "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+
"TLS_RSA_WITH_NULL_SHA256",
"TLS_ECDHE_ECDSA_WITH_NULL_SHA",
"TLS_ECDHE_RSA_WITH_NULL_SHA",
@@ -123,26 +137,17 @@
"TLS_ECDH_RSA_WITH_NULL_SHA",
"TLS_ECDH_anon_WITH_NULL_SHA",
"SSL_RSA_WITH_NULL_MD5",
- "SSL_RSA_WITH_DES_CBC_SHA",
- "SSL_DHE_RSA_WITH_DES_CBC_SHA",
- "SSL_DHE_DSS_WITH_DES_CBC_SHA",
- "SSL_DH_anon_WITH_DES_CBC_SHA",
- "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
- "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
- "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
- "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
- "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
- "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+
+ "TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
+ "TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
"TLS_KRB5_WITH_RC4_128_SHA",
"TLS_KRB5_WITH_RC4_128_MD5",
- "TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
- "TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
"TLS_KRB5_WITH_DES_CBC_SHA",
"TLS_KRB5_WITH_DES_CBC_MD5",
+ "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
+ "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
"TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
- "TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
- "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
- "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"
+ "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"
);
private final static String[] protocols = {
--- a/jdk/test/sun/java2d/cmm/ColorConvertOp/ColConvCCMTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/java2d/cmm/ColorConvertOp/ColConvCCMTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6476665 7033534 6830714
+ * @bug 6476665 7033534 6830714 8052162
* @summary Verifies color conversion of Component Color Model based images
* @run main ColConvCCMTest
*/
--- a/jdk/test/sun/net/www/http/HttpClient/StreamingRetry.java Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/net/www/http/HttpClient/StreamingRetry.java Mon Nov 17 12:32:27 2014 -0800
@@ -23,8 +23,8 @@
/*
* @test
- * @bug 6672144
- * @summary HttpURLConnection.getInputStream sends POST request after failed chunked send
+ * @bug 6672144 8050983
+ * @summary Do not retry failed request with a streaming body.
*/
import java.net.HttpURLConnection;
@@ -33,6 +33,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import static java.lang.System.out;
public class StreamingRetry implements Runnable {
static final int ACCEPT_TIMEOUT = 20 * 1000; // 20 seconds
@@ -43,11 +44,17 @@
}
void instanceMain() throws IOException {
- test();
+ out.println("Test with default method");
+ test(null);
+ out.println("Test with POST method");
+ test("POST");
+ out.println("Test with PUT method");
+ test("PUT");
+
if (failed > 0) throw new RuntimeException("Some tests failed");
}
- void test() throws IOException {
+ void test(String method) throws IOException {
ss = new ServerSocket(0);
ss.setSoTimeout(ACCEPT_TIMEOUT);
int port = ss.getLocalPort();
@@ -58,6 +65,8 @@
URL url = new URL("http://localhost:" + port + "/");
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.setDoOutput(true);
+ if (method != null)
+ uc.setRequestMethod(method);
uc.setChunkedStreamingMode(4096);
OutputStream os = uc.getOutputStream();
os.write("Hello there".getBytes());
@@ -79,7 +88,7 @@
ss.close();
fail("The server shouldn't accept a second connection");
} catch (IOException e) {
- //OK, the clien will close the server socket if successfull
+ //OK, the client will close the server socket if successful
}
}
--- a/jdk/test/sun/util/calendar/zi/tzdata/VERSION Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/VERSION Mon Nov 17 12:32:27 2014 -0800
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2014g
+tzdata2014j
--- a/jdk/test/sun/util/calendar/zi/tzdata/africa Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/africa Mon Nov 17 12:32:27 2014 -0800
@@ -29,20 +29,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2013-02-21):
+# From Paul Eggert (2014-10-31):
#
-# A good source for time zone historical data outside the U.S. is
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Another source occasionally used is Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
@@ -88,7 +87,6 @@
# 3:00 CAST Central Africa Summer Time (no longer used)
# 3:00 SAST South Africa Summer Time (no longer used)
# 3:00 EAT East Africa Time
-# 4:00 EAST East Africa Summer Time (no longer used)
# Algeria
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -133,23 +131,13 @@
# See Africa/Lagos.
# Botswana
-# From Paul Eggert (2013-02-21):
-# Milne says they were regulated by the Cape Town Signal in 1899;
-# assume they switched to 2:00 when Cape Town did.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Gaborone 1:43:40 - LMT 1885
- 1:30 - SAST 1903 Mar
- 2:00 - CAT 1943 Sep 19 2:00
- 2:00 1:00 CAST 1944 Mar 19 2:00
- 2:00 - CAT
+# See Africa/Maputo.
# Burkina Faso
# See Africa/Abidjan.
# Burundi
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Bujumbura 1:57:28 - LMT 1890
- 2:00 - CAT
+# See Africa/Maputo.
# Cameroon
# See Africa/Lagos.
@@ -179,15 +167,10 @@
1:00 - WAT
# Comoros
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Comoro 2:53:04 - LMT 1911 Jul # Moroni, Gran Comoro
- 3:00 - EAT
+# See Africa/Nairobi.
# Democratic Republic of the Congo
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Lubumbashi 1:49:52 - LMT 1897 Nov 9
- 2:00 - CAT
-# The above is for the eastern part; see Africa/Lagos for the western part.
+# See Africa/Lagos for the western part and Africa/Maputo for the eastern.
# Republic of the Congo
# See Africa/Lagos.
@@ -208,9 +191,7 @@
Link Africa/Abidjan Atlantic/St_Helena # St Helena
# Djibouti
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Djibouti 2:52:36 - LMT 1911 Jul
- 3:00 - EAT
+# See Africa/Nairobi.
###############################################################################
@@ -339,7 +320,7 @@
# Egypt is to change back to Daylight system on May 15
# http://english.ahram.org.eg/NewsContent/1/64/100735/Egypt/Politics-/Egypts-government-to-reapply-daylight-saving-time-.aspx
-# From Gunther Vermier (2015-05-13):
+# From Gunther Vermier (2014-05-13):
# our Egypt office confirms that the change will be at 15 May "midnight" (24:00)
# From Imed Chihi (2014-06-04):
@@ -423,27 +404,8 @@
# See Africa/Lagos.
# Eritrea
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Asmara 2:35:32 - LMT 1870
- 2:35:32 - AMT 1890 # Asmara Mean Time
- 2:35:20 - ADMT 1936 May 5 # Adis Dera MT
- 3:00 - EAT
-
# Ethiopia
-# From Paul Eggert (2014-07-31):
-# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a
-# 12-hour clock starting at our 06:00, so their "8 o'clock" is our
-# 02:00 or 14:00. Keep this in mind when you ask the time in Amharic.
-#
-# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time
-# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in
-# 1890, and that they switched to 3:00 on 1936-05-05. Perhaps 38E50
-# was for Adis Dera. Quite likely the Shanks data entries are wrong
-# anyway.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Addis_Ababa 2:34:48 - LMT 1870
- 2:35:20 - ADMT 1936 May 5 # Adis Dera MT
- 3:00 - EAT
+# See Africa/Nairobi.
# Gabon
# See Africa/Lagos.
@@ -487,13 +449,18 @@
2:30 - BEAT 1940
2:45 - BEAUT 1960
3:00 - EAT
+Link Africa/Nairobi Africa/Addis_Ababa # Ethiopia
+Link Africa/Nairobi Africa/Asmara # Eritrea
+Link Africa/Nairobi Africa/Dar_es_Salaam # Tanzania
+Link Africa/Nairobi Africa/Djibouti
+Link Africa/Nairobi Africa/Kampala # Uganda
+Link Africa/Nairobi Africa/Mogadishu # Somalia
+Link Africa/Nairobi Indian/Antananarivo # Madagascar
+Link Africa/Nairobi Indian/Comoro
+Link Africa/Nairobi Indian/Mayotte
# Lesotho
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Maseru 1:50:00 - LMT 1903 Mar
- 2:00 - SAST 1943 Sep 19 2:00
- 2:00 1:00 SAST 1944 Mar 19 2:00
- 2:00 - SAST
+# See Africa/Johannesburg.
# Liberia
# From Paul Eggert (2006-03-22):
@@ -568,16 +535,10 @@
2:00 - EET
# Madagascar
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Antananarivo 3:10:04 - LMT 1911 Jul
- 3:00 - EAT 1954 Feb 27 23:00s
- 3:00 1:00 EAST 1954 May 29 23:00s
- 3:00 - EAT
+# See Africa/Nairobi.
# Malawi
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Blantyre 2:20:00 - LMT 1903 Mar
- 2:00 - CAT
+# See Africa/Maputo.
# Mali
# Mauritania
@@ -677,9 +638,7 @@
# no information; probably like Indian/Mauritius
# Mayotte
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou
- 3:00 - EAT
+# See Africa/Nairobi.
# Morocco
# See the 'europe' file for Spanish Morocco (Africa/Ceuta).
@@ -987,6 +946,13 @@
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Maputo 2:10:20 - LMT 1903 Mar
2:00 - CAT
+Link Africa/Maputo Africa/Blantyre # Malawi
+Link Africa/Maputo Africa/Bujumbura # Burundi
+Link Africa/Maputo Africa/Gaborone # Botswana
+Link Africa/Maputo Africa/Harare # Zimbabwe
+Link Africa/Maputo Africa/Kigali # Rwanda
+Link Africa/Maputo Africa/Lubumbashi # E Dem. Rep. of Congo
+Link Africa/Maputo Africa/Lusaka # Zambia
# Namibia
# The 1994-04-03 transition is from Shanks & Pottenger.
@@ -1054,9 +1020,7 @@
# Tromelin - inhabited until at least 1958
# Rwanda
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Kigali 2:00:16 - LMT 1935 Jun
- 2:00 - CAT
+# See Africa/Maputo.
# St Helena
# See Africa/Abidjan.
@@ -1086,11 +1050,7 @@
# See Africa/Abidjan.
# Somalia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Mogadishu 3:01:28 - LMT 1893 Nov
- 3:00 - EAT 1931
- 2:30 - BEAT 1957
- 3:00 - EAT
+# See Africa/Nairobi.
# South Africa
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -1100,6 +1060,9 @@
Zone Africa/Johannesburg 1:52:00 - LMT 1892 Feb 8
1:30 - SAST 1903 Mar
2:00 SA SAST
+Link Africa/Johannesburg Africa/Maseru # Lesotho
+Link Africa/Johannesburg Africa/Mbabane # Swaziland
+#
# Marion and Prince Edward Is
# scientific station since 1947
# no information
@@ -1127,16 +1090,10 @@
Link Africa/Khartoum Africa/Juba
# Swaziland
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Mbabane 2:04:24 - LMT 1903 Mar
- 2:00 - SAST
+# See Africa/Johannesburg.
# Tanzania
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Dar_es_Salaam 2:37:08 - LMT 1931
- 3:00 - EAT 1948
- 2:45 - BEAUT 1961
- 3:00 - EAT
+# See Africa/Nairobi.
# Togo
# See Africa/Abidjan.
@@ -1242,19 +1199,8 @@
1:00 Tunisia CE%sT
# Uganda
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Kampala 2:09:40 - LMT 1928 Jul
- 3:00 - EAT 1930
- 2:30 - BEAT 1948
- 2:45 - BEAUT 1957
- 3:00 - EAT
+# See Africa/Nairobi.
# Zambia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Lusaka 1:53:08 - LMT 1903 Mar
- 2:00 - CAT
-
# Zimbabwe
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Harare 2:04:12 - LMT 1903 Mar
- 2:00 - CAT
+# See Africa/Maputo.
--- a/jdk/test/sun/util/calendar/zi/tzdata/asia Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/asia Mon Nov 17 12:32:27 2014 -0800
@@ -29,20 +29,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2013-08-11):
+# From Paul Eggert (2014-10-31):
#
-# A good source for time zone historical data outside the U.S. is
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Another source occasionally used is Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
@@ -70,10 +69,11 @@
# 3:30 IRST IRDT Iran
# 4:00 GST Gulf*
# 5:30 IST India
-# 7:00 ICT Indochina*
+# 7:00 ICT Indochina, most times and locations*
# 7:00 WIB west Indonesia (Waktu Indonesia Barat)
# 8:00 WITA central Indonesia (Waktu Indonesia Tengah)
# 8:00 CST China
+# 8:00 IDT Indochina, 1943-45, 1947-55, 1960-75 (some locations)*
# 8:00 JWST Western Standard Time (Japan, 1896/1937)*
# 9:00 JCST Central Standard Time (Japan, 1896/1937)
# 9:00 WIT east Indonesia (Waktu Indonesia Timur)
@@ -294,12 +294,8 @@
6:30 - MMT # Myanmar Time
# Cambodia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Phnom_Penh 6:59:40 - LMT 1906 Jun 9
- 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT?
- 7:00 - ICT 1912 May
- 8:00 - ICT 1931 May
- 7:00 - ICT
+# See Asia/Bangkok.
+
# China
@@ -916,6 +912,10 @@
# Indonesia
#
+# From Paul Eggert (2014-09-06):
+# The 1876 Report of the Secretary of the [US] Navy, p 306 says that Batavia
+# civil time was 7:07:12.5; round to even for Jakarta.
+#
# From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
# http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime
# says that Indonesia's time zones changed on 1988-01-01. Looking at some
@@ -1685,44 +1685,70 @@
# Korea (North and South)
# From Annie I. Bang (2006-07-10):
-# http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp
-# The Ministry of Commerce, Industry and Energy has already
-# commissioned a research project [to reintroduce DST] and has said
-# the system may begin as early as 2008.... Korea ran a daylight
-# saving program from 1949-61 but stopped it during the 1950-53 Korean War.
+# http://www.koreaherald.com/view.php?ud=200607100012
+# Korea ran a daylight saving program from 1949-61 but stopped it
+# during the 1950-53 Korean War. The system was temporarily enforced
+# between 1987 and 1988 ...
-# From Shanks & Pottenger:
+# From Sanghyuk Jung (2014-10-29):
+# http://mm.icann.org/pipermail/tz/2014-October/021830.html
+# According to the Korean Wikipedia
+# http://ko.wikipedia.org/wiki/한국_표준시
+# [oldid=12896437 2014-09-04 08:03 UTC]
+# DST in Republic of Korea was as follows.... And I checked old
+# newspapers in Korean, all articles correspond with data in Wikipedia.
+# For example, the article in 1948 (Korean Language) proved that DST
+# started at June 1 in that year. For another example, the article in
+# 1988 said that DST started at 2:00 AM in that year.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule ROK 1960 only - May 15 0:00 1:00 D
-Rule ROK 1960 only - Sep 13 0:00 0 S
-Rule ROK 1987 1988 - May Sun>=8 0:00 1:00 D
-Rule ROK 1987 1988 - Oct Sun>=8 0:00 0 S
+Rule ROK 1948 only - Jun 1 0:00 1:00 D
+Rule ROK 1948 only - Sep 13 0:00 0 S
+Rule ROK 1949 only - Apr 3 0:00 1:00 D
+Rule ROK 1949 1951 - Sep Sun>=8 0:00 0 S
+Rule ROK 1950 only - Apr 1 0:00 1:00 D
+Rule ROK 1951 only - May 6 0:00 1:00 D
+Rule ROK 1955 only - May 5 0:00 1:00 D
+Rule ROK 1955 only - Sep 9 0:00 0 S
+Rule ROK 1956 only - May 20 0:00 1:00 D
+Rule ROK 1956 only - Sep 30 0:00 0 S
+Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D
+Rule ROK 1957 1960 - Sep Sun>=18 0:00 0 S
+Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
+Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
-# From Paul Eggert (2014-07-01):
-# The following entries are from Shanks & Pottenger, except that I
-# guessed that time zone abbreviations through 1945 followed the same
+# From Paul Eggert (2014-10-30):
+# The Korean Wikipedia entry gives the following sources for UT offsets:
+#
+# 1908: Official Journal Article No. 3994 (Edict No. 5)
+# 1912: Governor-General of Korea Official Gazette Issue No. 367
+# (Announcement No. 338)
+# 1954: Presidential Decree No. 876 (1954-03-17)
+# 1961: Law No. 676 (1961-08-07)
+# 1987: Law No. 3919 (1986-12-31)
+#
+# The Wikipedia entry also has confusing information about a change
+# to UT+9 in April 1910, but then what would be the point of the later change
+# to UT+9 on 1912-01-01? Omit the 1910 change for now.
+#
+# I guessed that time zone abbreviations through 1945 followed the same
# rules as discussed under Taiwan, with nominal switches from JST to KST
# when the respective cities were taken over by the Allies after WWII.
+#
+# For Pyongyang we have no information; guess no changes since World War II.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Seoul 8:27:52 - LMT 1890
- 8:30 - KST 1904 Dec
- 9:00 - JCST 1928
- 8:30 - KST 1932
+Zone Asia/Seoul 8:27:52 - LMT 1908 Apr 1
+ 8:30 - KST 1912 Jan 1
9:00 - JCST 1937 Oct 1
9:00 - JST 1945 Sep 8
9:00 - KST 1954 Mar 21
- 8:00 ROK K%sT 1961 Aug 10
- 8:30 - KST 1968 Oct
+ 8:30 ROK K%sT 1961 Aug 10
9:00 ROK K%sT
-Zone Asia/Pyongyang 8:23:00 - LMT 1890
- 8:30 - KST 1904 Dec
- 9:00 - JCST 1928
- 8:30 - KST 1932
+Zone Asia/Pyongyang 8:23:00 - LMT 1908 Apr 1
+ 8:30 - KST 1912 Jan 1
9:00 - JCST 1937 Oct 1
9:00 - JST 1945 Aug 24
- 9:00 - KST 1954 Mar 21
- 8:00 - KST 1961 Aug 10
9:00 - KST
###############################################################################
@@ -1733,12 +1759,8 @@
3:00 - AST
# Laos
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Vientiane 6:50:24 - LMT 1906 Jun 9 # or Viangchan
- 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT?
- 7:00 - ICT 1912 May
- 8:00 - ICT 1931 May
- 7:00 - ICT
+# See Asia/Bangkok.
+
# Lebanon
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
@@ -2751,6 +2773,8 @@
Zone Asia/Bangkok 6:42:04 - LMT 1880
6:42:04 - BMT 1920 Apr # Bangkok Mean Time
7:00 - ICT
+Link Asia/Bangkok Asia/Phnom_Penh # Cambodia
+Link Asia/Bangkok Asia/Vientiane # Laos
# Turkmenistan
# From Shanks & Pottenger.
@@ -2788,22 +2812,65 @@
# Vietnam
-# From Paul Eggert (2013-02-21):
+# From Paul Eggert (2014-10-04):
# Milne gives 7:16:56 for the meridian of Saigon in 1899, as being
# used in Lower Laos, Cambodia, and Annam. But this is quite a ways
# from Saigon's location. For now, ignore this and stick with Shanks
-# and Pottenger.
+# and Pottenger for LMT before 1906.
# From Arthur David Olson (2008-03-18):
# The English-language name of Vietnam's most populous city is "Ho Chi Minh
# City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters.
-# From Shanks & Pottenger:
+# From Paul Eggert (2014-10-21) after a heads-up from Trần Ngọc Quân:
+# Trần Tiến Bình's authoritative book "Lịch Việt Nam: thế kỷ XX-XXI (1901-2100)"
+# (Nhà xuất bản Văn Hoá - Thông Tin, Hanoi, 2005), pp 49-50,
+# is quoted verbatim in:
+# http://www.thoigian.com.vn/?mPage=P80D01
+# is translated by Brian Inglis in:
+# http://mm.icann.org/pipermail/tz/2014-October/021654.html
+# and is the basis for the information below.
+#
+# The 1906 transition was effective July 1 and standardized Indochina to
+# Phù Liễn Observatory, legally 104 deg. 17'17" east of Paris.
+# It's unclear whether this meant legal Paris Mean Time (00:09:21) or
+# the Paris Meridian (2 deg. 20'14.03" E); the former yields 07:06:30.1333...
+# and the latter 07:06:29.333... so either way it rounds to 07:06:30,
+# which is used below even though the modern-day Phù Liễn Observatory
+# is closer to 07:06:31. Abbreviate Phù Liễn Mean Time as PLMT.
+#
+# The following transitions occurred in Indochina in general (before 1954)
+# and in South Vietnam in particular (after 1954):
+# To 07:00 on 1911-05-01.
+# To 08:00 on 1942-12-31 at 23:00.
+# To 09:00 in 1945-03-14 at 23:00.
+# To 07:00 on 1945-09-02 in Vietnam.
+# To 08:00 on 1947-04-01 in French-controlled Indochina.
+# To 07:00 on 1955-07-01 in South Vietnam.
+# To 08:00 on 1959-12-31 at 23:00 in South Vietnam.
+# To 07:00 on 1975-06-13 in South Vietnam.
+#
+# Trần cites the following sources; it's unclear which supplied the info above.
+#
+# Hoàng Xuân Hãn: "Lịch và lịch Việt Nam". Tập san Khoa học Xã hội,
+# No. 9, Paris, February 1982.
+#
+# Lê Thành Lân: "Lịch và niên biểu lịch sử hai mươi thế kỷ (0001-2010)",
+# NXB Thống kê, Hanoi, 2000.
+#
+# Lê Thành Lân: "Lịch hai thế kỷ (1802-2010) và các lịch vĩnh cửu",
+# NXB Thuận Hoá, Huế, 1995.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jun 9
- 7:06:20 - SMT 1911 Mar 11 0:01 # Saigon MT?
- 7:00 - ICT 1912 May
- 8:00 - ICT 1931 May
+Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jul 1
+ 7:06:30 - PLMT 1911 May 1
+ 7:00 - ICT 1942 Dec 31 23:00
+ 8:00 - IDT 1945 Mar 14 23:00
+ 9:00 - JST 1945 Sep 2
+ 7:00 - ICT 1947 Apr 1
+ 8:00 - IDT 1955 Jul 1
+ 7:00 - ICT 1959 Dec 31 23:00
+ 8:00 - IDT 1975 Jun 13
7:00 - ICT
# Yemen
--- a/jdk/test/sun/util/calendar/zi/tzdata/australasia Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/australasia Mon Nov 17 12:32:27 2014 -0800
@@ -354,20 +354,27 @@
# Fiji will end DST on 2014-01-19 02:00:
# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVINGS-TO-END-THIS-MONTH-%281%29.aspx
-# From Paul Eggert (2014-01-10):
-# For now, guess that Fiji springs forward the Sunday before the fourth
-# Monday in October, and springs back the penultimate Sunday in January.
-# This is ad hoc, but matches recent practice.
+# From Ken Rylander (2014-10-20):
+# DST will start Nov. 2 this year.
+# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-SUNDAY,-NOVEMBER-2ND.aspx
+
+# From Paul Eggert (2014-10-20):
+# For now, guess DST from 02:00 the first Sunday in November to
+# 03:00 the first Sunday on or after January 18. Although ad hoc, it
+# matches this year's plan and seems more likely to match future
+# practice than guessing no DST.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S
Rule Fiji 1999 2000 - Feb lastSun 3:00 0 -
Rule Fiji 2009 only - Nov 29 2:00 1:00 S
Rule Fiji 2010 only - Mar lastSun 3:00 0 -
-Rule Fiji 2010 max - Oct Sun>=21 2:00 1:00 S
+Rule Fiji 2010 2013 - Oct Sun>=21 2:00 1:00 S
Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
Rule Fiji 2012 2013 - Jan Sun>=18 3:00 0 -
-Rule Fiji 2014 max - Jan Sun>=18 2:00 0 -
+Rule Fiji 2014 only - Jan Sun>=18 2:00 0 -
+Rule Fiji 2014 max - Nov Sun>=1 2:00 1:00 S
+Rule Fiji 2015 max - Jan Sun>=18 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva
12:00 Fiji FJ%sT # Fiji Time
@@ -542,6 +549,30 @@
Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
9:48:32 - PMMT 1895 # Port Moresby Mean Time
10:00 - PGT # Papua New Guinea Time
+#
+# From Paul Eggert (2014-10-13):
+# Base the Bougainville entry on the Arawa-Kieta region, which appears to have
+# the most people even though it was devastated in the Bougainville Civil War.
+#
+# Although Shanks gives 1942-03-15 / 1943-11-01 for JST, these dates
+# are apparently rough guesswork from the starts of military campaigns.
+# The World War II entries below are instead based on Arawa-Kieta.
+# The Japanese occupied Kieta in July 1942,
+# according to the Pacific War Online Encyclopedia
+# http://pwencycl.kgbudge.com/B/o/Bougainville.htm
+# and seem to have controlled it until their 1945-08-21 surrender.
+#
+# The Autonomous Region of Bougainville plans to switch from UTC+10 to UTC+11
+# on 2014-12-28 at 02:00. They call UTC+11 "Bougainville Standard Time";
+# abbreviate this as BST. See:
+# http://www.bougainville24.com/bougainville-issues/bougainville-gets-own-timezone/
+#
+Zone Pacific/Bougainville 10:22:16 - LMT 1880
+ 9:48:32 - PMMT 1895
+ 10:00 - PGT 1942 Jul
+ 9:00 - JST 1945 Aug 21
+ 10:00 - PGT 2014 Dec 28 2:00
+ 11:00 - BST
# Pitcairn
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -789,19 +820,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2013-02-21):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Another source occasionally used is Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
@@ -826,6 +857,7 @@
# 10:00 AEST AEDT Eastern Australia
# 10:00 ChST Chamorro
# 10:30 LHST LHDT Lord Howe*
+# 11:00 BST Bougainville*
# 11:30 NZMT NZST New Zealand through 1945
# 12:00 NZST NZDT New Zealand 1946-present
# 12:15 CHAST Chatham through 1945*
--- a/jdk/test/sun/util/calendar/zi/tzdata/europe Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/europe Mon Nov 17 12:32:27 2014 -0800
@@ -29,16 +29,19 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2014-05-31):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
@@ -91,10 +94,11 @@
# 0:00 WET WEST WEMT Western Europe
# 0:19:32.13 AMT NST Amsterdam, Netherlands Summer (1835-1937)*
# 0:20 NET NEST Netherlands (1937-1940)*
+# 1:00 BST British Standard (1968-1971)
# 1:00 CET CEST CEMT Central Europe
# 1:00:14 SET Swedish (1879-1899)*
# 2:00 EET EEST Eastern Europe
-# 3:00 FET Further-eastern Europe*
+# 3:00 FET Further-eastern Europe (2011-2014)*
# 3:00 MSK MSD MSM* Moscow
# From Peter Ilieve (1994-12-04),
@@ -309,6 +313,14 @@
# "Timeball on the ballast office is down. Dunsink time."
# -- James Joyce, Ulysses
+# "Countess Markievicz ... claimed that the [1916] abolition of Dublin Mean Time
+# was among various actions undertaken by the 'English' government that
+# would 'put the whole country into the SF (Sinn Féin) camp'. She claimed
+# Irish 'public feeling (was) outraged by forcing of English time on us'."
+# -- Parsons M. Dublin lost its time zone - and 25 minutes - after 1916 Rising.
+# Irish Times 2014-10-27.
+# http://www.irishtimes.com/news/politics/dublin-lost-its-time-zone-and-25-minutes-after-1916-rising-1.1977411
+
# From Joseph S. Myers (2005-01-26):
# Irish laws are available online at <http://www.irishstatutebook.ie>.
# These include various relating to legal time, for example:
@@ -616,6 +628,7 @@
Rule Russia 1993 2010 - Mar lastSun 2:00s 1:00 S
Rule Russia 1993 1995 - Sep lastSun 2:00s 0 -
Rule Russia 1996 2010 - Oct lastSun 2:00s 0 -
+# As described below, Russia's 2014 change affects Zone data, not Rule data.
# From Alexander Krivenyshev (2011-06-14):
# According to Kremlin press service, Russian President Dmitry Medvedev
@@ -746,6 +759,13 @@
# http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
# http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
# http://news.tut.by/society/250578.html
+#
+# From Alexander Bokovoy (2014-10-09):
+# Belarussian government decided against changing to winter time....
+# http://eng.belta.by/all_news/society/Belarus-decides-against-adjusting-time-in-Russias-wake_i_76335.html
+# From Paul Eggert (2014-10-08):
+# Hence Belarus can share time zone abbreviations with Moscow again.
+#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Minsk 1:50:16 - LMT 1880
1:50 - MMT 1924 May 2 # Minsk Mean Time
@@ -758,7 +778,8 @@
2:00 - EET 1992 Mar 29 0:00s
2:00 1:00 EEST 1992 Sep 27 0:00s
2:00 Russia EE%sT 2011 Mar 27 2:00s
- 3:00 - FET
+ 3:00 - FET 2014 Oct 26 1:00s
+ 3:00 - MSK
# Belgium
#
@@ -2524,7 +2545,7 @@
# The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus
# realigning itself with KRAT.
-Zone Asia/Novokuznetsk 5:48:48 - NMT 1920 Jan 6
+Zone Asia/Novokuznetsk 5:48:48 - LMT 1924 May 1
6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time
7:00 Russia KRA%sT 1991 Mar 31 2:00s
6:00 Russia KRA%sT 1992 Jan 19 2:00s
--- a/jdk/test/sun/util/calendar/zi/tzdata/leapseconds Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/leapseconds Mon Nov 17 12:32:27 2014 -0800
@@ -33,8 +33,8 @@
# The NTP Timescale and Leap Seconds
# http://www.eecis.udel.edu/~mills/leap.html
-# The International Earth Rotation Service periodically uses leap seconds
-# to keep UTC to within 0.9 s of UT1
+# The International Earth Rotation and Reference Systems Service
+# periodically uses leap seconds to keep UTC to within 0.9 s of UT1
# (which measures the true angular orientation of the earth in space); see
# Terry J Quinn, The BIPM and the accurate measure of time,
# Proc IEEE 79, 7 (July 1991), 894-905 <http://dx.doi.org/10.1109/5.84965>.
--- a/jdk/test/sun/util/calendar/zi/tzdata/northamerica Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/northamerica Mon Nov 17 12:32:27 2014 -0800
@@ -300,6 +300,12 @@
# time zone, but we do go by the Eastern time zone because so many people work
# in Columbus."
+# From Paul Eggert (2014-09-06):
+# Monthly Notices of the Royal Astronomical Society 44, 4 (1884-02-08), 208
+# says that New York City Hall time was 3 minutes 58.4 seconds fast of
+# Eastern time (i.e., -4:56:01.6) just before the 1883 switch. Round to the
+# nearest second.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule NYC 1920 only - Mar lastSun 2:00 1:00 D
Rule NYC 1920 only - Oct lastSun 2:00 0 S
@@ -1008,19 +1014,19 @@
################################################################################
-# From Paul Eggert (2006-03-22):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
-#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
# Other sources occasionally used include:
#
@@ -1118,17 +1124,16 @@
# An amendment to the Interpretation Act was registered on February 19/2007....
# http://action.attavik.ca/home/justice-gn/attach/2007/gaz02part2.pdf
-# From Paul Eggert (2006-04-25):
+# From Paul Eggert (2014-10-18):
# H. David Matthews and Mary Vincent's map
# "It's about TIME", _Canadian Geographic_ (September-October 1998)
-# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
+# http://www.canadiangeographic.ca/Magazine/SO98/alacarte.asp
# contains detailed boundaries for regions observing nonstandard
# time and daylight saving time arrangements in Canada circa 1998.
#
-# INMS, the Institute for National Measurement Standards in Ottawa, has
-# information about standard and daylight saving time zones in Canada.
-# http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php
-# (updated periodically).
+# National Research Council Canada maintains info about time zones and DST.
+# http://www.nrc-cnrc.gc.ca/eng/services/time/time_zones.html
+# http://www.nrc-cnrc.gc.ca/eng/services/time/faq/index.html#Q5
# Its unofficial information is often taken from Matthews and Vincent.
# From Paul Eggert (2006-06-27):
@@ -1993,10 +1998,7 @@
# [Also see <http://www.nunatsiaq.com/nunavut/nvt10309_06.html> (2001-03-09).]
# From Gwillim Law (2005-05-21):
-# According to maps at
-# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SWE.jpg
-# http://inms-ienm.nrc-cnrc.gc.ca/images/time_services/TZ01SSE.jpg
-# (both dated 2003), and
+# According to ...
# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
# (from a 1998 Canadian Geographic article), the de facto and de jure time
# for Southampton Island (at the north end of Hudson Bay) is UTC-5 all year
@@ -2005,9 +2007,11 @@
# predates the creation of Nunavut, it probably goes back many years....
# The Inuktitut name of Coral Harbour is Sallit, but it's rarely used.
#
-# From Paul Eggert (2005-07-26):
+# From Paul Eggert (2014-10-17):
# For lack of better information, assume that Southampton Island observed
-# daylight saving only during wartime.
+# daylight saving only during wartime. Gwillim Law's email also
+# mentioned maps now maintained by National Research Council Canada;
+# see above for an up-to-date link.
# From Chris Walton (2007-03-01):
# ... the community of Resolute (located on Cornwallis Island in
@@ -3008,10 +3012,21 @@
# Shanks & Pottenger give -5:07:12, but Milne records -5:07:10.41 from an
# unspecified official document, and says "This time is used throughout the
# island". Go with Milne. Round to the nearest second as required by zic.
+#
+# Shanks & Pottenger give April 28 for the 1974 spring-forward transition, but
+# Lance Neita writes that Prime Minister Michael Manley decreed it January 5.
+# Assume Neita meant Jan 6 02:00, the same as the US. Neita also writes that
+# Manley's supporters associated this act with Manley's nickname "Joshua"
+# (recall that in the Bible the sun stood still at Joshua's request),
+# and with the Rod of Correction which Manley said he had received from
+# Haile Selassie, Emperor of Ethiopia. See:
+# Neita L. The politician in all of us. Jamaica Observer 2014-09-20
+# http://www.jamaicaobserver.com/columns/The-politician-in-all-of-us_17573647
+#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Jamaica -5:07:11 - LMT 1890 # Kingston
-5:07:11 - KMT 1912 Feb # Kingston Mean Time
- -5:00 - EST 1974 Apr 28 2:00
+ -5:00 - EST 1974
-5:00 US E%sT 1984
-5:00 - EST
@@ -3139,13 +3154,17 @@
# From Paul Eggert (2014-08-19):
# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round. See:
# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
-# Model this as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
+# Model this as a switch from EST/EDT to AST ...
+# From Chris Walton (2014-11-04):
+# ... the TCI government appears to have delayed the switch to
+# "permanent daylight saving time" by one year....
+# http://tcweeklynews.com/time-change-to-go-ahead-this-november-p5437-127.htm
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Grand_Turk -4:44:32 - LMT 1890
-5:07:11 - KMT 1912 Feb # Kingston Mean Time
-5:00 - EST 1979
- -5:00 US E%sT 2014 Nov 2 2:00
+ -5:00 US E%sT 2015 Nov Sun>=1 2:00
-4:00 - AST
# British Virgin Is
--- a/jdk/test/sun/util/calendar/zi/tzdata/southamerica Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/southamerica Mon Nov 17 12:32:27 2014 -0800
@@ -29,23 +29,23 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2006-03-22):
-# A good source for time zone historical data outside the U.S. is
+# From Paul Eggert (2014-10-31):
+#
+# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
# San Diego: ACS Publications, Inc. (2003).
-#
-# For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
-# http://www.jstor.org/stable/1774359
+# Unfortunately this book contains many errors and cites no sources.
#
# Gwillim Law writes that a good source
# for recent time zone data is the International Air Transport
# Association's Standard Schedules Information Manual (IATA SSIM),
# published semiannually. Law sent in several helpful summaries
-# of the IATA's data after 1990.
+# of the IATA's data after 1990. Except where otherwise noted,
+# IATA SSIM is the source for entries after 1990.
#
-# Except where otherwise noted, Shanks & Pottenger is the source for
-# entries through 1990, and IATA SSIM is the source for entries afterwards.
+# For data circa 1899, a common source is:
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
#
# Earlier editions of these tables used the North American style (e.g. ARST and
# ARDT for Argentine Standard and Daylight Time), but the following quote
--- a/jdk/test/sun/util/calendar/zi/tzdata/zone.tab Fri Nov 14 17:53:46 2014 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab Mon Nov 17 12:32:27 2014 -0800
@@ -330,7 +330,8 @@
PF -1732-14934 Pacific/Tahiti Society Islands
PF -0900-13930 Pacific/Marquesas Marquesas Islands
PF -2308-13457 Pacific/Gambier Gambier Islands
-PG -0930+14710 Pacific/Port_Moresby
+PG -0930+14710 Pacific/Port_Moresby most locations
+PG -0613+15534 Pacific/Bougainville Bougainville
PH +1435+12100 Asia/Manila
PK +2452+06703 Asia/Karachi
PL +5215+02100 Europe/Warsaw
--- a/langtools/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -281,3 +281,4 @@
c536541235e566701ff772700c15de14b75e2979 jdk9-b36
478972d90f7bf5002615c5b2fb1ec3e0338fcadd jdk9-b37
5ad591bc3ef6d1b30b215cb9c228bf94aac6dc7c jdk9-b38
+5ff1cd07bd9297e82cfea5ec01249d162260fe4e jdk9-b39
--- a/langtools/make/build.properties Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/build.properties Mon Nov 17 12:32:27 2014 -0800
@@ -23,25 +23,46 @@
# questions.
#
-# This is the JDK used to build and run the bootstrap version of javac.
-# The bootstrap javac is used to compile both boostrap versions of the
-# other tools, and product versions of all the tools.
-# Override this path as needed, either on the command line or in
-# one of the standard user build.properties files (see build.xml)
+#javac configuration for "normal build" (these will be passed to the bootstrap compiler):
+javac.debug = true
+javac.debuglevel = source,lines,vars
+javac.extra.opts=-XDignore.symbol.file=true
+javac.includes=
+javac.lint.opts = -Xlint:all,-deprecation -Werror
+javac.source = 8
+javac.target = 8
-# boot.java.home = /opt/jdk/1.7.0
-boot.java = ${boot.java.home}/bin/java
-boot.javac = ${boot.java.home}/bin/javac
+#javac configuration for bootstrap build (these will be passed to the compiler from the given boot JDK):
+boot.javac.extra.opts=-XDignore.symbol.file=true
+boot.javac.includes = \
+ javax/annotation/processing/ \
+ javax/lang/model/ \
+ javax/tools/ \
+ jdk/ \
+ com/sun/source/ \
+ com/sun/tools/javac/ \
+ com/sun/tools/doclint/
+boot.javac.lint.opts=
boot.javac.source = 8
boot.javac.target = 8
-# This is the JDK used to run the product version of the tools,
-# for example, for testing. If you're building a complete JDK, specify that.
-# Override this path as needed, either on the command line or in
-# one of the standard user build.properties files (see build.xml)
+#configuration of submodules (share by both the bootstrap and normal compilation):
+langtools.modules=java.base:java.compiler:jdk.compiler:jdk.dev:jdk.javadoc
+java.base.dependencies=
+java.compiler.dependencies=java.base
+jdk.compiler.dependencies=java.base:java.compiler
+jdk.javadoc.dependencies=java.base:java.compiler:jdk.compiler
+jdk.dev.dependencies=java.base:java.compiler:jdk.compiler
-# target.java.home = /opt/jdk/1.8.0
-target.java = ${target.java.home}/bin/java
+#test configuration:
+jtreg.tests=
+boot.javac.tests = tools/javac
+crules.tests = ../make/test/crules
+
+#javadoc configuration
+javadoc.jls.cite=The Java™ Language Specification
+javadoc.jls.option=-tag "jls:a:See <cite>${javadoc.jls.cite}</cite>:" \
+ -tag "implNote:a:Implementation Note:"
# Version info -- override as needed
jdk.version = 1.9.0
@@ -55,146 +76,4 @@
# timestamps
# FIXME -- need to include openjdk as needed
release = ${jdk.version}-${milestone}
-bootstrap.release = ${release}_bootstrap
full.version = ${release}-${build.number}
-bootstrap.full.version = ${bootstrap.release}-${build.number}
-
-# options for the <javac> tasks used to compile the tools
-javac.source = 8
-javac.target = 8
-javac.debug = true
-javac.debuglevel = source,lines
-javac.no.jdk.warnings = -XDignore.symbol.file=true
-# set the following to -version to verify the versions of javac being used
-javac.version.opt =
-# in time, there should be no exceptions to -Xlint:all
-javac.lint.opts = -Xlint:all,-deprecation -Werror
-
-# options for the <javadoc> task for javac
-#javadoc.jls3.url=http://java.sun.com/docs/books/jls/
-#javadoc.jls3.cite=<a href="${javadoc.jls3.url}">The Java Language Specification, Third Edition</a>
-#javadoc.jls3.option=-tag "jls3:a:See <cite>${javadoc.jls3.cite}</cite>:"
-
-
-javadoc.jls.cite=The Java™ Language Specification
-
-javadoc.jls.option=-tag "jls:a:See <cite>${javadoc.jls.cite}</cite>:"
-
-
-
-
-
-# jtreg, used to run the JDK regression tests
-# See http://openjdk.java.net/jtreg/
-# Override this path as needed, either on the command line or in
-# one of the standard user build.properties files (see build.xml)
-
-# jtreg.home = /opt/jtreg/4.1
-
-# findbugs
-# See http://findbugs.sourceforge.net/
-# Override this path as needed, either on the command line or in
-# one of the standard user build.properties files (see build.xml)
-
-# findbugs.home = /opt/findbugs/1.2.1
-
-# vizant (graph visualization tool for Ant)
-# See http://vizant.sourceforge.net/
-# Override this path as needed, either on the command line or in
-# one of the standard user build.properties files (see build.xml)
-
-# vizant.jar = /opt/vizant/0.1.2/vizant-0.1.2.jar
-# dot = dot
-
-#------------------------------------------------------------
-
-# The following properties define the packages for each of the tools.
-# Syntactically, they should be suitable as arguments for the "includes"
-# parameter of Ant filesets. In particular, note the trailing '/'.
-
-javac.includes = \
- javax/annotation/processing/ \
- javax/lang/model/ \
- javax/tools/ \
- jdk/ \
- com/sun/source/ \
- com/sun/tools/javac/ \
- com/sun/tools/doclint/
-
-javac.tests = \
- tools/javac
-
-#
-
-javadoc.includes = \
- com/sun/javadoc/ \
- com/sun/tools/javadoc/ \
- com/sun/tools/doclets/
-
-javadoc.tests = \
- tools/javadoc/ \
- com/sun/javadoc/
-
-#
-
-javah.includes = \
- com/sun/tools/javah/
-
-javah.tests = \
- tools/javah/
-
-#
-
-javap.includes = \
- com/sun/tools/classfile/ \
- com/sun/tools/javap/ \
- com/sun/tools/jdeps/ \
- sun/tools/javap/
-
-javap.tests = \
- tools/javap/
-
-#
-
-sjavac.includes = \
- com/sun/tools/sjavac/
-
-sjavac.tests = \
- tools/sjavac
-
-crules.tests = ../make/test/crules
-
-#
-
-# The following files require the latest JDK to be available.
-# The API can be provided by using a suitable boot.java.home
-# or by setting import.jdk
-require.latest.jdk.files = \
- com/sun/tools/javac/nio/*.java
-
-# The following files in the import jdk source directory are required
-# in order to compile the files defined in ${require.latest.jdk.files}
-#
-# For NIO, the list of stub files is defined by the contents of the primary
-# API packages, together with such types that may be required in order to
-# compile the stubs. Some of these dependencies would go away if the stub
-# generator were to be improved -- e.g. by removing unnecessary imports.
-#
-import.jdk.stub.files = \
- java/io/File.java \
- java/nio/file/**.java \
- java/nio/file/attribute/**.java \
- java/nio/file/spi/**.java \
- java/nio/channels/AsynchronousChannel.java \
- java/nio/channels/AsynchronousFileChannel.java \
- java/nio/channels/CompletionHandler.java \
- java/nio/channels/SeekableByteChannel.java
-
-# The following value is used by the main jtreg target.
-# An empty value means all tests
-# Override as desired to run a specific set of tests
-jtreg.tests =
-
-# Check style configuration
-# overridable name and version
-checkstyle.name.version = checkstyle-5.4
--- a/langtools/make/build.xml Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/build.xml Mon Nov 17 12:32:27 2014 -0800
@@ -25,10 +25,10 @@
-->
<!--
- This is the main build file for the complete langtools repository.
- It is used when building JDK (in which case it is invoked from the
- Makefile), and it can be used when working on the tools themselves,
- in an IDE such as NetBeans.
+ This is a convenience build file supporting development in the langtools
+ repository. It can be run either standalone, or from IDEs. This build script
+ is for a developer use only, it is not used to build the production version
+ of javac or other langtools tools.
External dependencies are specified via properties. These can be given
on the command line, or by providing a local build.properties file.
@@ -39,58 +39,27 @@
For example, to run any of the jtreg tests you must set jtreg.home,
to run findbugs on the code you must set findbugs.home, and so on.
- For the most part, javac can be built using the previous version of JDK.
- However, a small number of javac files require access to the latest JDK,
- which may not yet have been compiled. To compile these files, you can do
- one of the following:
- - Set boot.java.home to a recent build of the latest version of JDK.
- - Set import.jdk to either a recent build (containing jre/lib/rt.jar)
- or to jdk source repository. In the latter case, stub files will
- automatically be generated and used for the required API, to avoid
- unnecessary compilation of the source repository.
- If you do neither, the relevant files will not be built.
-
The main build happens in two phases:
- - First, javac and other tools as needed are built using ${boot.java.home}.
- (This implies a constraint on the source code that they can be compiled
- with the previous version of JDK.
+ - First, javac is built using ${boot.java.home}. (This implies a constraint
+ on the source code that they can be compiled with the previous version of JDK.
- Second, all required classes are compiled with the latest javac, created
in the previous step.
- The first phase is called the bootstrap phase. All targets, properties and
- tasks that are specific to that phase have "bootstrap" in their name.
+ The build generally builds one module at time.
- For more details on the JDK build, see
- http://blogs.sun.com/kto/entry/anatomy_of_the_jdk_build
- http://openjdk.java.net/groups/build/
For more details on the stub generator, see
http://blogs.sun.com/jjg/entry/building_javac_for_jdk7
Internal details ...
- Interim build products are created in the build/ directory.
- Final build products are created in the dist/ directory.
- When building JDK, the dist/directory will contain:
- - A bootstrap compiler suitable for running with ${boot.java.home}
- suitable for compiling downstream parts of JDK
- - Source files and class files for inclusion in the JDK being built
- When building standalone, the dist/directory will contain:
- - Separate jar files for each of the separate langtools components
- - Simple scripts to invoke the tools by executing the corresponding
- jar files.
- These jar files and scripts are "for developer use only".
+ Bootstrap classes are built into the build/bootstrap/<module-name>/classes directory.
+ Final classes are built into the build/<module-name>/classes directory.
+ Final runnable javac is in dist/bin and dist/lib. Bootstrap javac (if requested by
+ using the build-bootstrap-javac target) is built into dist/bootstrap.
This file is organized into sections as follows:
- global property definitions
- - general top level targets
- - general diagnostic/debugging targets
- - groups of targets for each tool: javac, javadoc, javah, javap
- Within each group, the following targets are provided, where applicable
- build-bootstrap-TOOL build the bootstrap version of the tool
- build-classes-TOOL build the classes for the tool
- build-TOOL build the jar file and script for the tool
- jtreg-TOOL build the tool and run the appropriate tests
- findbugs-TOOL run findbugs on the tool's source code
- TOOL build the tool, run the tests, and run findbugs
+ - primary top level targets (cleaning, building, testing, producing javac)
+ - secondary top level targets (code analysis, diagnostics, extra documentation, etc.)
- utility definitions
-->
@@ -99,13 +68,6 @@
**** Global property definitions.
-->
- <!-- Force full debuginfo for javac if the debug.classfiles
- property is set. This must be BEFORE the include of
- build.properties because it sets javac.debuglevel. -->
- <condition property="javac.debuglevel" value="source,lines,vars">
- <equals arg1="${debug.classfiles}" arg2="true"/>
- </condition>
-
<!-- The following locations can be used to override default property values. -->
<!-- Use this location for customizations specific to this instance of this workspace -->
@@ -119,36 +81,24 @@
<!-- Convenient shorthands for standard locations within the workspace. -->
<property name="build.dir" location="build"/>
- <property name="build.bootstrap.dir" location="${build.dir}/bootstrap"/>
- <property name="build.coverage.dir" location="${build.dir}/coverage"/>
- <property name="build.classes.dir" location="${build.dir}/classes"/>
- <property name="build.gensrc.dir" location="${build.dir}/gensrc"/>
- <property name="build.genstubs.dir" location="${build.dir}/genstubs"/>
- <property name="build.javadoc.dir" location="${build.dir}/javadoc"/>
+ <property name="build.crules.dir" location="${build.dir}/crules"/>
<property name="build.jtreg.dir" location="${build.dir}/jtreg"/>
<property name="build.toolclasses.dir" location="${build.dir}/toolclasses"/>
+ <property name="build.javadoc.dir" location="${build.dir}/javadoc"/>
<property name="dist.dir" location="dist"/>
<property name="dist.bin.dir" location="${dist.dir}/bin"/>
- <property name="dist.coverage.dir" location="${dist.dir}/coverage"/>
+ <property name="dist.lib.dir" location="${dist.dir}/lib"/>
<property name="dist.findbugs.dir" location="${dist.dir}/findbugs"/>
<property name="dist.checkstyle.dir" location="${dist.dir}/checkstyle"/>
- <property name="dist.lib.dir" location="${dist.dir}/lib"/>
<property name="make.dir" location="make"/>
<property name="make.conf.dir" location="${make.dir}/conf"/>
<property name="make.tools.dir" location="${make.dir}/tools"/>
- <property name="src.dir" location="src"/>
- <property name="src.bin.dir" location="${src.dir}/share/bin"/>
<property name="test.dir" location="test"/>
- <path id="src.dirs">
- <pathelement path="${src.dir}/java.base/share/classes"/>
- <pathelement path="${src.dir}/java.compiler/share/classes"/>
- <pathelement path="${src.dir}/jdk.compiler/share/classes"/>
- <pathelement path="${src.dir}/jdk.dev/share/classes"/>
- <pathelement path="${src.dir}/jdk.javadoc/share/classes"/>
- </path>
-
- <pathconvert pathsep="," property="src.dirs.property" refid="src.dirs" />
+ <property name="boot.build.dir" location="${build.dir}/bootstrap"/>
+ <property name="boot.dist.dir" location="${dist.dir}/bootstrap"/>
+ <property name="boot.dist.bin.dir" location="${boot.dist.dir}/bin"/>
+ <property name="boot.dist.lib.dir" location="${boot.dist.dir}/lib"/>
<!-- java.marker is set to a marker file to check for within a Java install dir.
The best file to check for across Solaris/Linux/Windows/MacOS is one of the
@@ -172,110 +122,89 @@
<isset property="target.java.home"/>
</condition>
- <!-- Logic for handling access import jdk classes, if available.
- import.jdk should be unset, or set to jdk home (to use rt.jar)
- or to jdk repo (to use src/share/classes).
- Based on the value, if any, set up default values for javac's sourcepath,
- classpath and bootclasspath. Note: the default values are overridden
- in the build-bootstrap-classes macro. -->
-
- <available property="import.jdk.src.dir" value="${import.jdk}/src/share/classes"
- filepath="${import.jdk}/src/share/classes" file="java/nio/file/Path.java"/>
- <available property="import.jdk.jar" value="${import.jdk}/jre/lib/rt.jar"
- ignoresystemclasses="true"
- classpath="${import.jdk}/jre/lib/rt.jar" classname="java.nio.file.Path"/>
-
- <!-- Set the default bootclasspath option used for javac.
- Note that different variants of the option are used, meaning we can't just
- define the value for the option.
- Note the explicit use of the standard property ${path.separator} in the following.
- This is because Ant is not clever enough to handle direct use of : or ; -->
- <condition property="javac.bootclasspath.opt"
- value="-Xbootclasspath:${build.classes.dir}${path.separator}${import.jdk.jar}"
- else="-Xbootclasspath/p:${build.classes.dir}">
- <isset property="import.jdk.jar"/>
- </condition>
-
- <condition property="boot.java.provides.latest.jdk">
- <available
- ignoresystemclasses="true"
- classpath="${boot.java.home}/jre/lib/rt.jar" classname="java.nio.file.Path"/>
- </condition>
-
- <condition property="bootstrap.exclude.files" value="" else="${require.latest.jdk.files}">
- <isset property="boot.java.provides.latest.jdk"/>
- </condition>
-
- <condition property="exclude.files" value="" else="${require.latest.jdk.files}">
- <or>
- <isset property="boot.java.provides.latest.jdk"/>
- <isset property="import.jdk"/>
- </or>
- </condition>
-
- <condition property="require.import.jdk.stubs">
- <and>
- <not>
- <isset property="boot.java.provides.latest.jdk"/>
- </not>
- <isset property="import.jdk.src.dir"/>
- </and>
- </condition>
-
- <!-- Set the default value of the sourcepath used for javac. -->
- <condition property="javac.sourcepath" value="${build.genstubs.dir}" else="">
- <isset property="require.import.jdk.stubs"/>
- </condition>
-
- <!-- Set the default value of the classpath used for javac. -->
- <property name="javac.classpath" value=""/>
-
+ <!-- setup basic properties holding paths to all sources, generated source and class directories
+ (both boot and non-boot) -->
+ <pathconvert property="langtools.sources">
+ <path>
+ <pathelement path="${langtools.modules}" />
+ </path>
+ <map from="${basedir}/" to="${basedir}/src/" />
+ <mapper type="glob" from="*" to="*/share/classes"/>
+ </pathconvert>
+ <pathconvert property="langtools.gensrc">
+ <path>
+ <pathelement path="${langtools.modules}" />
+ </path>
+ <map from="${basedir}/" to="${build.dir}/" />
+ <mapper type="glob" from="*" to="*/gensrc"/>
+ </pathconvert>
+ <pathconvert property="langtools.boot.classes">
+ <path>
+ <pathelement path="${langtools.modules}" />
+ </path>
+ <map from="${basedir}/" to="${boot.build.dir}/" />
+ <mapper type="glob" from="*" to="*/classes"/>
+ </pathconvert>
+ <pathconvert property="langtools.classes">
+ <path>
+ <pathelement path="${langtools.modules}" />
+ </path>
+ <map from="${basedir}/" to="${build.dir}/" />
+ <mapper type="glob" from="*" to="*/classes"/>
+ </pathconvert>
<!--
- **** General top level targets.
+ **** Primary targets
-->
- <!-- Standard target to build deliverables for JDK build. -->
-
- <target name="build" depends="build-bootstrap-tools,build-all-classes">
- <copy todir="${dist.dir}/bootstrap">
- <fileset dir="${build.bootstrap.dir}" includes="bin/,lib/"/>
- </copy>
- <chmod dir="${dist.dir}/bootstrap/bin" perm="ugo+rx">
- <include name="*"/>
- </chmod>
- <mkdir dir="${dist.lib.dir}"/>
- <jar file="${dist.lib.dir}/classes.jar" basedir="${build.classes.dir}"/>
- <zip file="${dist.lib.dir}/src.zip">
- <multirootfileset basedirs="${src.dirs.property}" />
- </zip>
- </target>
-
- <target name="build-bootstrap-tools"
- depends="build-bootstrap-javac,build-bootstrap-javadoc,build-bootstrap-javah,build-bootstrap-sjavac"
- />
-
- <target name="build-all-tools"
- depends="build-javac,build-javadoc,build-javah,build-javap,build-sjavac"
- />
-
- <target name="build-all-classes" depends="build-bootstrap-javac,-create-import-jdk-stubs">
- <build-classes includes="${javac.includes} ${javadoc.includes} ${javah.includes} ${javap.includes} ${sjavac.includes}"/>
- </target>
-
- <!-- clean -->
-
<target name="clean" description="Delete all generated files">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
</target>
- <!-- Additional targets for running tools on the build -->
+ <target name="build" depends="build-all-tools">
+ </target>
+
+ <target name="build-all-tools" depends="build-all-classes,-def-build-all-module-jars,-def-build-tool">
+ <build-all-module-jars />
+ <build-tool name="javac"/>
+ <build-tool name="javadoc"/>
+ <build-tool name="javap"/>
+ <build-tool name="javah"/>
+ <build-tool name="sjavac"/>
+ </target>
+
+ <target name="build-all-classes" depends="-def-build-all-module-classes,build-bootstrap-javac-classes">
+ <build-all-module-classes />
+ </target>
<target name="jtreg" depends="build-all-tools,-def-jtreg">
<jtreg-tool name="all" tests="${jtreg.tests}"/>
</target>
+ <target name="javadoc" depends="build-all-classes,-def-javadoc-tool">
+ <javadoc-tool options="${javadoc.jls.option}"/>
+ </target>
+
+ <target name="build-bootstrap-javac-classes" depends="-check-boot.java.home,-def-build-all-module-classes">
+ <build-all-module-classes compilation.kind="boot." />
+ </target>
+
+ <!--
+ **** Extra targets
+ -->
+
+ <target name="build-bootstrap-javac" depends="build-bootstrap-javac-classes,-def-build-all-module-jars,-def-build-tool">
+ <build-all-module-jars compilation.kind="boot." />
+ <build-tool name="javac" compilation.kind="boot." />
+ </target>
+
+ <target name="jtreg-bootstrap-javac" depends="build-bootstrap-javac,-def-jtreg">
+ <jtreg-tool name="bootstrap-javac"
+ tests="${boot.javac.tests}"
+ langtools.classes="${langtools.boot.classes}"/>
+ </target>
+
<target name="checkstyle" depends="-def-checkstyle"
description="Generates reports for code convention violations.">
<mkdir dir="${dist.checkstyle.dir}"/>
@@ -325,9 +254,13 @@
warningsProperty="findbugs.all.warnings"
jvm="${target.java.home}/bin/java"
jvmargs="-Xmx512M">
- <class location="${build.classes.dir}"/>
+ <class location="${build.dir}/java.base/classes"/>
+ <class location="${build.dir}/java.compiler/classes"/>
+ <class location="${build.dir}/jdk.compiler/classes"/>
+ <class location="${build.dir}/jdk.javadoc/classes"/>
+ <class location="${build.dir}/jdk.dev/classes"/>
<sourcePath>
- <path refid="src.dirs"/>
+ <pathelement path="${langtools.sources}"/>
</sourcePath>
</findbugs>
<exec executable="sh">
@@ -339,49 +272,7 @@
</exec>
</target>
- <target name="coverage" depends="-def-cobertura,build-all-classes,instrument-classes,jtreg,coverage-report"/>
-
- <target name="instrument-classes" depends="-def-cobertura">
- <!-- only define the following property when we want coverage info -->
- <path id="coverage.classpath">
- <pathelement location="${build.coverage.dir}/classes"/>
- <path refid="cobertura.classpath"/>
- </path>
- <property name="coverage.options" value="-Dnet.sourceforge.cobertura.datafile=${build.coverage.dir}/cobertura.ser"/>
- <property name="coverage.classpath" refid="coverage.classpath"/>
- <mkdir dir="${build.coverage.dir}/classes"/>
- <delete file="${build.coverage.dir}/cobertura.ser"/>
- <cobertura-instrument todir="${build.coverage.dir}/classes"
- datafile="${build.coverage.dir}/cobertura.ser">
- <fileset dir="${build.classes.dir}"
- includes="**/*.class" excludes="**/resources/*.class"/>
- </cobertura-instrument>
- </target>
-
- <target name="coverage-report" depends="-def-cobertura">
- <mkdir dir="${dist.coverage.dir}"/>
- <cobertura-report
- destdir="${dist.coverage.dir}"
- datafile="${build.coverage.dir}/cobertura.ser">
- <fileset dir="${src.dir}/java.base/share/classes"/>
- <fileset dir="${src.dir}/java.compiler/share/classes"/>
- <fileset dir="${src.dir}/jdk.compiler/share/classes"/>
- <fileset dir="${src.dir}/jdk.dev/share/classes"/>
- <fileset dir="${src.dir}/jdk.javadoc/share/classes"/>
- </cobertura-report>
- <cobertura-report
- format="xml"
- destdir="${dist.coverage.dir}"
- datafile="${build.coverage.dir}/cobertura.ser">
- <fileset dir="${src.dir}/java.base/share/classes"/>
- <fileset dir="${src.dir}/java.compiler/share/classes"/>
- <fileset dir="${src.dir}/jdk.compiler/share/classes"/>
- <fileset dir="${src.dir}/jdk.dev/share/classes"/>
- <fileset dir="${src.dir}/jdk.javadoc/share/classes"/>
- </cobertura-report>
- </target>
-
- <target name="diags-examples" depends="build-javac,build-javap">
+ <target name="diags-examples" depends="build-all-tools">
<!-- can override the following on the command line if desired. -->
<property name="diags.examples.out" location="${build.dir}/diag-examples/diags-examples.html"/>
<mkdir dir="${build.dir}/diag-examples/classes"/>
@@ -391,7 +282,7 @@
destdir="${build.dir}/diag-examples/classes"
includes="ArgTypeCompilerFactory.java,Example.java,FileManager.java,HTMLWriter.java,RunExamples.java,DocCommentProcessor.java"
sourcepath=""
- classpath="${dist.lib.dir}/javac.jar;${dist.lib.dir}/javap.jar"
+ classpath="${langtools.classes}"
includeAntRuntime="no"
debug="${javac.debug}"
debuglevel="${javac.debuglevel}">
@@ -400,7 +291,7 @@
<java fork="true"
jvm="${target.java.home}/bin/java"
dir="test/tools/javac/diags"
- classpath="${build.dir}/diag-examples/classes;${dist.lib.dir}/javac.jar;${dist.lib.dir}/javap.jar"
+ classpath="${build.dir}/diag-examples/classes;${langtools.classes}"
classname="RunExamples">
<jvmarg value="-Dtest.classes=${build.dir}/diag-examples/classes"/>
<arg value="-examples"/>
@@ -413,56 +304,16 @@
</java>
</target>
- <!-- a patching facility to speed up incorporating the langtools' classfiles
- into a jdk of your choice. Either target.java.home or patch.jdk can be
- set on the command line; setting target.java.home has the advantage of
- patching the jdk used for jtreg and other tests.
- -->
- <target name="patch" depends="build-all-classes">
- <condition property="patch.jdk" value="${target.java.home}">
- <available file="${target.java.home}" type="dir"/>
- </condition>
- <fail message="patch.jdk or target.java.home is not set, please set target.java.home, or patch.jdk for an alternate jdk image to patch">
- <condition>
- <not>
- <isset property="patch.jdk"/>
- </not>
- </condition>
- </fail>
- <property name="patch.tools.jar" location="${patch.jdk}/lib/tools.jar"/>
- <property name="patch.rt.jar" location="${patch.jdk}/jre/lib/rt.jar"/>
- <fail message="patch.jdk or target.java.home must point to a valid jdk image: missing tools.jar">
- <condition>
- <not>
- <available file="${patch.tools.jar}" type="file"/>
- </not>
- </condition>
- </fail>
- <fail message="patch.jdk or target.java.home must point to a valid jdk image: missing rt.jar">
- <condition>
- <not>
- <available file="${patch.rt.jar}" type="file"/>
- </not>
- </condition>
- </fail>
- <zip zipfile="${patch.tools.jar}" update="true">
- <zipfileset dir="${build.classes.dir}" includes="com/**"/>
- </zip>
- <zip zipfile="${patch.rt.jar}" update="true">
- <zipfileset dir="${build.classes.dir}" includes="javax/**"/>
- </zip>
- </target>
-
<target name="doclint-api" depends="build-all-classes">
<delete dir="${build.dir}/doclint/classes"/>
<mkdir dir="${build.dir}/doclint/classes"/>
<javac fork="true"
- executable="${boot.javac}"
+ executable="${boot.java.home}/bin/javac"
destdir="${build.dir}/doclint/classes"
includes="javax/lang/model/** com/sun/javadoc/** com/sun/source/**"
excludes=""
- sourcepath="${javac.sourcepath}"
- classpath="${javac.classpath}"
+ sourcepath=""
+ classpath="${langtools.classes}"
includeAntRuntime="no"
source="${javac.source}"
target="${javac.target}"
@@ -471,12 +322,11 @@
<compilerarg value="-implicit:none"/>
<compilerarg value="-Xprefer:source"/>
<compilerarg value="-J-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
- <compilerarg line="${javac.no.jdk.warnings}"/>
- <compilerarg line="${javac.version.opt}"/>
+ <compilerarg line="${javac.extra.opts}"/>
<compilerarg line="-Xdoclint:all/protected,-missing"/>
<src>
- <path refid="src.dirs"/>
- <path location="${build.gensrc.dir}"/>
+ <pathelement path="${langtools.sources}"/>
+ <pathelement path="${langtools.gensrc}"/>
</src>
</javac>
</target>
@@ -515,17 +365,12 @@
</classpath>
<!-- platform classes used for documentation -->
<bootclasspath>
- <pathelement path="${build.dir}/classes"/>
+ <pathelement path="${langtools.classes}"/>
<pathelement path="${target.java.home}/jre/lib/rt.jar"/>
</bootclasspath>
</javadoc>
</target>
- <!--
- **** Debugging/diagnostic targets.
- -->
-
- <!-- standard JDK target -->
<target name="sanity"
description="display settings of configuration values">
<echo level="info">ant.home = ${ant.home}</echo>
@@ -536,257 +381,32 @@
<echo level="info">checkstyle.home = ${checkstyle.home}</echo>
</target>
- <target name="post-sanity" depends="-def-jtreg,sanity,build"
- description="perform basic validation after a standard build">
- <jtreg
- dir="make/test"
- workDir="${build.jtreg.dir}/post-sanity/work"
- reportDir="${build.jtreg.dir}/post-sanity/report"
- jdk="${target.java.home}"
- verbose="summary"
- failonerror="false" resultproperty="jtreg.post-sanity.result">
- </jtreg>
- </target>
-
- <!-- use vizant tool to generate graphical image of this Ant file.-->
- <target name="vizant" depends="-def-vizant">
- <mkdir dir="${build.dir}"/>
- <echo message="Generating ${build.dir}/build.dot"/>
- <vizant antfile="${make.dir}/build.xml" outfile="${build.dir}/build.dot"/>
- <echo message="Generating ${build.dir}/build.png"/>
- <exec executable="${dot}" >
- <arg value="-Tpng"/>
- <arg value="-o"/>
- <arg file="${build.dir}/build.png"/>
- <arg file="${build.dir}/build.dot"/>
- </exec>
- </target>
-
- <target name="check-import.jdk">
- <echo message="import.jdk: ${import.jdk}"/>
- <echo message="import.jdk.jar: ${import.jdk.jar}"/>
- <echo message="import.jdk.src.dir: ${import.jdk.src.dir}"/>
- </target>
-
<target name="diagnostics">
<diagnostics/>
</target>
-
- <!--
- **** javac targets.
- -->
-
- <target name="build-bootstrap-javac"
- depends="-def-build-bootstrap-classes,-def-build-bootstrap-jar,-def-build-bootstrap-tool">
- <build-bootstrap-classes includes="${javac.includes}"/>
- <build-bootstrap-jar name="javac" includes="${javac.includes}"/>
- <build-bootstrap-tool name="javac"/>
- </target>
-
- <target name="build-classes-javac" depends="build-bootstrap-javac,-create-import-jdk-stubs">
- <build-classes includes="${javac.includes}"/>
- </target>
-
- <target name="build-javac" depends="build-classes-javac">
- <build-jar name="javac" includes="${javac.includes}"/>
- <build-tool name="javac"/>
- </target>
-
- <target name="javadoc-javac" depends="build-javac,-def-javadoc-tool">
- <javadoc-tool name="javac" includes="${javac.includes}" options="${javadoc.jls.option}"/>
- </target>
-
- <target name="jtreg-javac" depends="build-javac,build-javap,-def-jtreg">
- <jtreg-tool name="javac" tests="${javac.tests}"/>
- </target>
-
- <target name="findbugs-javac" depends="build-javac,-def-findbugs">
- <findbugs-tool name="javac"/>
- </target>
-
- <target name="javac" depends="build-javac,jtreg-javac,findbugs-javac"/>
-
-
- <!--
- **** javadoc targets.
- -->
-
- <target name="build-bootstrap-javadoc" depends="build-bootstrap-javac">
- <build-bootstrap-classes includes="${javadoc.includes}"/>
- <build-bootstrap-jar name="javadoc" includes="${javadoc.includes}"
- jarclasspath="javac.jar"/>
- <build-bootstrap-tool name="javadoc"/>
- </target>
-
- <target name="build-classes-javadoc" depends="build-classes-javac">
- <build-classes includes="${javadoc.includes}"/>
- </target>
-
- <target name="build-javadoc" depends="build-javac,build-classes-javadoc">
- <build-jar name="javadoc" includes="${javadoc.includes}"
- jarclasspath="javac.jar"/>
- <build-tool name="javadoc"/>
- </target>
-
- <target name="javadoc-javadoc" depends="build-javadoc,-def-javadoc-tool">
- <javadoc-tool name="javadoc" includes="${javadoc.includes}"/>
- </target>
-
- <target name="jtreg-javadoc" depends="build-javadoc,-def-jtreg">
- <jtreg-tool name="javadoc" tests="${javadoc.tests}"/>
- </target>
-
- <target name="findbugs-javadoc" depends="build-javadoc,-def-findbugs">
- <findbugs-tool name="javadoc"/>
- </target>
-
- <target name="javadoc" depends="build-javadoc,jtreg-javadoc,findbugs-javadoc"/>
-
- <!--
- **** javah targets.
- -->
-
- <target name="build-bootstrap-javah" depends="build-bootstrap-javadoc">
- <build-bootstrap-classes includes="${javah.includes}"/>
- <build-bootstrap-jar name="javah" includes="${javah.includes}"
- jarclasspath="javadoc.jar javac.jar"/>
- <build-bootstrap-tool name="javah"/>
- </target>
-
- <target name="build-javah" depends="build-javac,build-classes-javah">
- <build-jar name="javah" includes="${javah.includes}" jarclasspath="javac.jar"/>
- <build-tool name="javah"/>
- </target>
-
- <target name="build-classes-javah" depends="build-classes-javadoc">
- <build-classes includes="${javah.includes}"/>
- </target>
-
- <!-- (no javadoc for javah) -->
-
- <target name="jtreg-javah" depends="build-javah,-def-jtreg">
- <jtreg-tool name="javah" tests="${javah.tests}"/>
- </target>
-
- <target name="findbugs-javah" depends="build-javah,-def-findbugs">
- <findbugs-tool name="javah"/>
- </target>
-
- <target name="javah" depends="build-javah,jtreg-javah,findbugs-javah"/>
-
-
- <!--
- **** javap targets.
- -->
-
- <target name="build-bootstrap-javap"
- depends="-def-build-bootstrap-classes,-def-build-bootstrap-jar,-def-build-bootstrap-tool">
- <build-bootstrap-classes includes="${javap.includes}"/>
- <build-bootstrap-jar name="javap" includes="${javap.includes}"
- jarmainclass="sun.tools.javap.Main"/>
- <build-bootstrap-tool name="javap"/>
- </target>
-
- <target name="build-classes-javap" depends="build-classes-javac">
- <build-classes includes="${javap.includes}"/>
- </target>
-
- <target name="build-javap" depends="build-javac,build-classes-javap">
- <build-jar name="javap" includes="${javap.includes}"
- jarmainclass="com.sun.tools.javap.Main"
- jarclasspath="javac.jar"/>
- <build-tool name="javap"/>
- </target>
-
- <!-- (no javadoc for javap) -->
-
- <target name="jtreg-javap" depends="build-javap,-def-jtreg">
- <jtreg-tool name="javap" tests="${javap.tests}"/>
- </target>
-
- <target name="findbugs-javap" depends="build-javap,-def-findbugs">
- <findbugs-tool name="javap"/>
- </target>
-
- <target name="javap" depends="build-javap,jtreg-javap,findbugs-javap"/>
-
- <!--
- **** sjavac targets.
- -->
-
- <target name="build-bootstrap-sjavac"
- depends="-def-build-bootstrap-classes,-def-build-bootstrap-jar,-def-build-bootstrap-tool">
- <build-bootstrap-classes includes="${sjavac.includes}"/>
- <build-bootstrap-jar name="sjavac" includes="${sjavac.includes}"
- jarmainclass="com.sun.tools.sjavac.Main"/>
- <build-bootstrap-tool name="sjavac"/>
- </target>
-
- <target name="build-classes-sjavac" depends="build-classes-javac">
- <build-classes includes="${sjavac.includes}"/>
- </target>
-
- <target name="build-sjavac" depends="build-classes-sjavac">
- <build-jar name="sjavac" includes="${sjavac.includes}"
- jarmainclass="com.sun.tools.sjavac.Main"
- jarclasspath="sjavac.jar"/>
- <build-tool name="sjavac"/>
- </target>
-
- <!-- (no javadoc for javap) -->
-
- <target name="jtreg-sjavac" depends="build-sjavac,-def-jtreg">
- <jtreg-tool name="sjavac" tests="${sjavac.tests}"/>
- </target>
-
- <target name="findbugs-sjavac" depends="build-sjavac,-def-findbugs">
- <findbugs-tool name="sjavac"/>
- </target>
-
- <target name="sjavac" depends="build-sjavac,jtreg-sjavac,findbugs-sjavac"/>
-
- <!--
- **** crules targets.
- -->
-
- <target name="build-crules"
- depends="-def-compilecrules,-def-build-jar-with-services,build-bootstrap-javac,-create-import-jdk-stubs">
- <compilecrules/>
- <build-jar-with-services
- name="crules"
- includes="crules/* crules/resources/*"
- classes.dir="${build.toolclasses.dir}"
- lib.dir="${build.toolclasses.dir}"
- jarmainclass=""
- jarclasspath="crules.jar"
- service.type="com.sun.source.util.Plugin"
- service.provider="crules.CodingRulesAnalyzerPlugin"/>
- <build-tool name="crules"/>
- </target>
-
- <target name="jtreg-crules" depends="build-javac,build-crules,-def-jtreg">
+ <target name="jtreg-crules" depends="build-all-classes,-def-jtreg">
+ <mkdir dir="${build.crules.dir}/classes"/>
+ <javac fork="true"
+ source="${boot.javac.source}"
+ target="${boot.javac.target}"
+ executable="${boot.java.home}/bin/javac"
+ srcdir="${make.tools.dir}"
+ includes="crules/*"
+ destdir="${build.crules.dir}/classes"
+ includeantruntime="false">
+ <compilerarg value="-Xbootclasspath/p:${langtools.classes}"/>
+ <compilerarg line="${javac.lint.opts}"/>
+ </javac>
+ <copy todir="${build.crules.dir}/classes" includeemptydirs="false">
+ <fileset dir="${make.tools.dir}">
+ <include name="**/*.properties"/>
+ </fileset>
+ </copy>
+ <echo file="${build.crules.dir}/classes/META-INF/services/com.sun.source.util.Plugin">crules.CodingRulesAnalyzerPlugin</echo>
<jtreg-tool name="crules"
tests="${crules.tests}"
- extra.jvmargs="-Xbootclasspath/a:${build.toolclasses.dir}/crules.jar" />
- </target>
-
- <target name="check-coding-rules" depends="build-bootstrap-javac,-create-import-jdk-stubs,build-crules">
- <build-classes includes="${javac.includes}"
- plugin.options="-J-Xbootclasspath/a:${build.toolclasses.dir}/crules.jar -Xplugin:coding_rules" />
- </target>
-
- <!--
- **** Create import JDK stubs.
- -->
-
- <target name="-create-import-jdk-stubs" depends="-def-genstubs" if="require.import.jdk.stubs">
- <mkdir dir="${build.genstubs.dir}"/>
- <genstubs
- srcdir="${import.jdk.src.dir}" destdir="${build.genstubs.dir}"
- includes="${import.jdk.stub.files}"
- fork="true" classpath="${build.toolclasses.dir}:${build.bootstrap.dir}/classes:${ant.core.lib}"
- />
+ extra.jvmargs="-Xbootclasspath/a:${build.crules.dir}/classes" />
</target>
<!--
@@ -821,8 +441,8 @@
<check name="target java" property="target.java.home" marker="${java.marker}"/>
</target>
- <target name="-check-cobertura.home" depends="-def-check">
- <check name="cobertura" property="cobertura.home" marker="cobertura.jar"/>
+ <target name="-check-jtreg.home" depends="-def-check">
+ <check name="jtreg" property="jtreg.home" marker="lib/jtreg.jar"/>
</target>
<target name="-check-findbugs.home" depends="-def-check">
@@ -830,27 +450,57 @@
</target>
<target name="-check-checkstyle.home" depends="-def-check">
- <check name="checkstyle" property="checkstyle.home" marker="${checkstyle.name.version}.jar"/>
+ <check name="checkstyle" property="checkstyle.home" marker=""/> <!--TODO: better checkstyle verification-->
</target>
- <target name="-check-jtreg.home" depends="-def-check">
- <check name="jtreg" property="jtreg.home" marker="lib/jtreg.jar"/>
+ <!-- Definitions -->
+
+ <target name="-def-build-all-module-jars" depends="-def-build-module-jar">
+ <macrodef name="build-all-module-jars">
+ <attribute name="compilation.kind" default=""/>
+ <sequential>
+ <build-module-jar module.name="java.base" compilation.kind="@{compilation.kind}" />
+ <build-module-jar module.name="java.compiler" compilation.kind="@{compilation.kind}" />
+ <build-module-jar module.name="jdk.compiler" compilation.kind="@{compilation.kind}" />
+ <build-module-jar module.name="jdk.javadoc" compilation.kind="@{compilation.kind}" />
+ <build-module-jar module.name="jdk.dev" compilation.kind="@{compilation.kind}" />
+ </sequential>
+ </macrodef>
</target>
- <target name="-check-vizant" depends="-def-check">
- <check name="vizant" property="vizant.jar"/>
- <check name="dot" property="dot"/>
+ <target name="-def-build-module-jar">
+ <macrodef name="build-module-jar">
+ <attribute name="module.name"/>
+ <attribute name="compilation.kind"/>
+ <attribute name="dependencies" default="${@{compilation.kind}@{module.name}.dependencies}"/>
+ <attribute name="build.dir" default="${@{compilation.kind}build.dir}"/>
+ <attribute name="lib.dir" default="${@{compilation.kind}dist.lib.dir}"/>
+ <attribute name="classes.dir" default="@{build.dir}/@{module.name}/classes"/>
+ <sequential>
+ <mkdir dir="@{lib.dir}"/>
+ <local name="jarclasspath" />
+ <pathconvert property="jarclasspath">
+ <path>
+ <pathelement path="@{dependencies}" />
+ </path>
+ <map from="${basedir}/" to="" />
+ <mapper type="glob" from="*" to="*.jar"/>
+ </pathconvert>
+ <jar destfile="@{lib.dir}/@{module.name}.jar"
+ basedir="@{classes.dir}">
+ <manifest>
+ <attribute name="Class-Path" value="@{jarclasspath}"/>
+ </manifest>
+ </jar>
+ </sequential>
+ </macrodef>
</target>
-
- <!--
- **** Targets for Ant macro and task definitions.
- -->
-
<target name="-def-build-tool">
<macrodef name="build-tool">
<attribute name="name"/>
- <attribute name="bin.dir" default="${dist.bin.dir}"/>
+ <attribute name="compilation.kind" default=""/>
+ <attribute name="bin.dir" default="${@{compilation.kind}dist.bin.dir}"/>
<attribute name="java" default="${launcher.java}"/>
<sequential>
<mkdir dir="@{bin.dir}"/>
@@ -866,84 +516,73 @@
</macrodef>
</target>
- <target name="-def-build-jar">
- <macrodef name="build-jar">
- <attribute name="name"/>
- <attribute name="includes"/>
- <attribute name="classes.dir" default="${build.classes.dir}"/>
- <attribute name="lib.dir" default="${dist.lib.dir}"/>
- <attribute name="jarmainclass" default="com.sun.tools.@{name}.Main"/>
- <attribute name="jarclasspath" default=""/>
+ <target name="-def-build-all-module-classes" depends="-def-build-module-classes">
+ <macrodef name="build-all-module-classes">
+ <attribute name="compilation.kind" default=""/>
<sequential>
- <mkdir dir="@{lib.dir}"/>
- <jar destfile="@{lib.dir}/@{name}.jar"
- basedir="@{classes.dir}"
- includes="@{includes}">
- <manifest>
- <attribute name="Main-Class" value="@{jarmainclass}"/>
- <attribute name="Class-Path" value="@{jarclasspath}"/>
- </manifest>
- </jar>
+ <build-module-classes module.name="java.base"
+ compilation.kind="@{compilation.kind}" />
+ <build-module-classes module.name="java.compiler"
+ compilation.kind="@{compilation.kind}" />
+ <build-module-classes module.name="jdk.compiler"
+ compilation.kind="@{compilation.kind}" />
+ <build-module-classes module.name="jdk.javadoc"
+ compilation.kind="@{compilation.kind}" />
+ <build-module-classes module.name="jdk.dev"
+ compilation.kind="@{compilation.kind}" />
</sequential>
</macrodef>
</target>
- <target name="-def-build-jar-with-services">
- <macrodef name="build-jar-with-services">
- <attribute name="name"/>
- <attribute name="includes"/>
- <attribute name="classes.dir" default="${build.classes.dir}"/>
- <attribute name="lib.dir" default="${dist.lib.dir}"/>
- <attribute name="jarmainclass" default="com.sun.tools.@{name}.Main"/>
- <attribute name="jarclasspath" default=""/>
- <attribute name="service.type" default=""/>
- <attribute name="service.provider" default=""/>
- <sequential>
- <mkdir dir="${build.toolclasses.dir}"/>
- <jar destfile="@{lib.dir}/@{name}.jar"
- basedir="@{classes.dir}"
- includes="@{includes}">
- <service type="@{service.type}" provider="@{service.provider}"/>
- <manifest>
- <attribute name="Main-Class" value="@{jarmainclass}"/>
- <attribute name="Class-Path" value="@{jarclasspath}"/>
- </manifest>
- </jar>
- </sequential>
- </macrodef>
- </target>
-
- <target name="-def-build-classes" depends="-def-pcompile">
- <macrodef name="build-classes">
- <attribute name="includes"/>
+ <target name="-def-build-module-classes" depends="-def-pcompile">
+ <macrodef name="build-module-classes">
+ <attribute name="module.name"/>
+ <attribute name="compilation.kind" default=""/>
+ <attribute name="dependencies" default="${@{module.name}.dependencies}"/>
+ <attribute name="includes" default="${@{compilation.kind}javac.includes}"/>
+ <attribute name="javac.lint.opts" default="${@{compilation.kind}javac.lint.opts}"/>
+ <attribute name="javac.extra.opts" default="${@{compilation.kind}javac.extra.opts}"/>
+ <attribute name="build.dir" default="${@{compilation.kind}build.dir}"/>
<attribute name="excludes" default="${exclude.files} **/package-info.java"/>
- <attribute name="classes.dir" default="${build.classes.dir}"/>
- <attribute name="gensrc.dir" default="${build.gensrc.dir}"/>
- <attribute name="javac.bootclasspath" default="${build.bootstrap.dir}/classes"/>
- <attribute name="bootclasspath.opt" default="${javac.bootclasspath.opt}"/>
- <attribute name="classpath" default="${javac.classpath}"/>
- <attribute name="sourcepath" default="${javac.sourcepath}"/>
+ <attribute name="classes.dir" default="@{build.dir}/@{module.name}/classes"/>
+ <attribute name="gensrc.dir" default="@{build.dir}/@{module.name}/gensrc"/>
+ <attribute name="depcache.dir" default="@{build.dir}/@{module.name}/depcache"/>
<attribute name="java.home" default="${boot.java.home}"/>
- <attribute name="source" default="${javac.source}"/>
- <attribute name="target" default="${javac.target}"/>
+ <attribute name="source" default="${@{compilation.kind}javac.source}"/>
+ <attribute name="target" default="${@{compilation.kind}javac.target}"/>
<attribute name="release" default="${release}"/>
<attribute name="full.version" default="${full.version}"/>
<attribute name="plugin.options" default=""/>
<sequential>
<echo level="verbose" message="build-classes: excludes=@{excludes}"/>
- <echo level="verbose" message="build-classes: bootclasspath.opt=@{bootclasspath.opt}"/>
<echo level="verbose" message="build-classes: classpath=@{classpath}"/>
<echo level="verbose" message="build-classes: sourcepath=@{sourcepath}"/>
+ <echo level="verbose" message="build-classes: dependencies=@{dependencies}"/>
+ <local name="src.dir" />
+ <property name="src.dir" location="${basedir}/src/@{module.name}/share/classes"/>
+ <local name="classpath" />
+ <pathconvert property="classpath">
+ <path>
+ <pathelement path="@{dependencies}" />
+ </path>
+ <map from="${basedir}/" to="@{build.dir}/" />
+ <mapper type="glob" from="*" to="*/classes"/>
+ </pathconvert>
+ <local name="bootclasspath.prepend"/>
+ <condition property="bootclasspath.prepend" value="" else="${langtools.boot.classes}">
+ <equals arg1="@{compilation.kind}" arg2="boot."/>
+ </condition>
+ <mkdir dir="@{classes.dir}"/>
<mkdir dir="@{gensrc.dir}"/>
- <mkdir dir="@{classes.dir}"/>
+ <mkdir dir="@{depcache.dir}"/>
<pcompile destdir="@{gensrc.dir}"
includes="@{includes}">
<src>
- <path refid="src.dirs"/>
+ <path location="${src.dir}"/>
</src>
</pcompile>
<copy todir="@{gensrc.dir}">
- <multirootfileset basedirs="${src.dirs.property}" includes="@{includes}" />
+ <fileset dir="${src.dir}" includes="@{includes}" />
<globmapper from="*.properties-template" to="*.properties"/>
<filterset begintoken="$(" endtoken=")">
<filter token="JDK_VERSION" value="${jdk.version}"/>
@@ -957,13 +596,20 @@
<pathelement location="@{gensrc.dir}"/>
</src>
</pcompile>
+ <antcall target="-do-depend">
+ <param name="src.dir" value="${src.dir}" />
+ <param name="classes.dir" value="@{classes.dir}" />
+ <param name="gensrc.dir" value="@{gensrc.dir}" />
+ <param name="depcache.dir" value="@{depcache.dir}" />
+ <param name="classpath" value="${classpath}" />
+ </antcall>
<javac fork="true"
executable="@{java.home}/bin/javac"
destdir="@{classes.dir}"
includes="@{includes}"
excludes="@{excludes}"
- sourcepath="@{sourcepath}"
- classpath="@{classpath}"
+ sourcepath="${src.dir}:@{gensrc.dir}"
+ classpath="${classpath}"
includeAntRuntime="no"
source="@{source}"
target="@{target}"
@@ -971,19 +617,18 @@
debuglevel="${javac.debuglevel}">
<compilerarg value="-implicit:none"/>
<compilerarg value="-Xprefer:source"/>
- <compilerarg value="-J-Xbootclasspath/p:@{javac.bootclasspath}"/>
- <compilerarg line="@{bootclasspath.opt}"/>
- <compilerarg line="${javac.no.jdk.warnings}"/>
- <compilerarg line="${javac.version.opt}"/>
- <compilerarg line="${javac.lint.opts}"/>
+ <compilerarg value="-J-Xbootclasspath/p:${bootclasspath.prepend}"/>
+ <compilerarg value="-Xbootclasspath/p:${classpath}"/>
+ <compilerarg line="@{javac.extra.opts}"/>
+ <compilerarg line="@{javac.lint.opts}"/>
<compilerarg line="@{plugin.options}"/>
<src>
- <path refid="src.dirs"/>
+ <path location="${src.dir}"/>
<path location="@{gensrc.dir}"/>
</src>
</javac>
<copy todir="@{classes.dir}" includeemptydirs="false">
- <multirootfileset basedirs="${src.dirs.property}" includes="@{includes}" excludes="@{excludes}">
+ <fileset dir="${src.dir}" includes="@{includes}" excludes="@{excludes}">
<exclude name="**/*.java"/>
<exclude name="**/*.properties"/>
<exclude name="**/*-template"/>
@@ -991,42 +636,15 @@
<exclude name="**/*.orig"/>
<exclude name="**/overview.html"/>
<exclude name="**/package.html"/>
- </multirootfileset>
+ </fileset>
</copy>
</sequential>
</macrodef>
</target>
- <target name="-def-build-bootstrap-tool" depends="-check-boot.java.home,-def-build-tool">
- <presetdef name="build-bootstrap-tool">
- <build-tool
- bin.dir="${build.bootstrap.dir}/bin"
- java="${boot.java}"/>
- </presetdef>
- </target>
-
- <target name="-def-build-bootstrap-jar" depends="-def-build-jar">
- <presetdef name="build-bootstrap-jar">
- <build-jar
- classes.dir="${build.bootstrap.dir}/classes"
- lib.dir="${build.bootstrap.dir}/lib"/>
- </presetdef>
- </target>
-
- <target name="-def-build-bootstrap-classes" depends="-def-build-classes">
- <presetdef name="build-bootstrap-classes">
- <build-classes
- source="${boot.javac.source}"
- target="${boot.javac.target}"
- gensrc.dir="${build.bootstrap.dir}/gensrc"
- classes.dir="${build.bootstrap.dir}/classes"
- javac.bootclasspath=""
- bootclasspath.opt="-Xbootclasspath/p:${build.bootstrap.dir}/classes"
- sourcepath=""
- release="${bootstrap.release}"
- full.version="${bootstrap.full.version}"
- excludes="${bootstrap.exclude.files} **/package-info.java"/>
- </presetdef>
+ <target name="-do-depend" if="do.depend">
+ <depend srcdir="${src.dir}:${gensrc.dir}" destdir="${classes.dir}" classpath="${classpath}"
+ cache="${depcache.dir}"/>
</target>
<target name="-def-pcompile">
@@ -1048,55 +666,9 @@
classpath="${build.toolclasses.dir}/"/>
</target>
- <target name="-def-compilecrules">
- <macrodef name="compilecrules">
- <sequential>
- <mkdir dir="${build.toolclasses.dir}"/>
- <javac fork="true"
- source="${boot.javac.source}"
- target="${boot.javac.target}"
- executable="${boot.java.home}/bin/javac"
- srcdir="${make.tools.dir}"
- includes="crules/*"
- destdir="${build.toolclasses.dir}/"
- classpath="${ant.core.lib}"
- bootclasspath="${boot.java.home}/jre/lib/rt.jar"
- includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
- <compilerarg line="${javac.lint.opts}"/>
- </javac>
- <copy todir="${build.toolclasses.dir}/" includeemptydirs="false">
- <fileset dir="${make.tools.dir}">
- <include name="**/*.properties"/>
- </fileset>
- </copy>
- </sequential>
- </macrodef>
- </target>
-
- <target name="-def-genstubs" depends="build-bootstrap-javac" if="require.import.jdk.stubs">
- <mkdir dir="${build.toolclasses.dir}"/>
- <javac fork="true"
- source="${boot.javac.source}"
- target="${boot.javac.target}"
- executable="${boot.java.home}/bin/javac"
- srcdir="${make.tools.dir}"
- includes="genstubs/* anttasks/GenStubs*"
- destdir="${build.toolclasses.dir}/"
- classpath="${ant.core.lib}"
- includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
- <compilerarg line="${javac.lint.opts}"/>
- </javac>
- <taskdef name="genstubs"
- classname="anttasks.GenStubsTask"
- classpath="${build.toolclasses.dir}/"/>
- </target>
-
<target name="-def-javadoc-tool" depends="-check-target.java.home">
<macrodef name="javadoc-tool">
- <attribute name="name"/>
- <attribute name="includes"/>
+ <attribute name="includes" default="${javac.includes}"/>
<attribute name="options" default=""/>
<attribute name="source" default="${javac.source}"/>
<sequential>
@@ -1106,7 +678,7 @@
<property name="javadoc.packagenames" value="none"/> <!-- default, can be overridden per user or per project -->
<javadoc
executable="${target.java.home}/bin/javadoc"
- destdir="${build.javadoc.dir}/@{name}"
+ destdir="${build.javadoc.dir}"
source="@{source}"
windowtitle="UNOFFICIAL"
failonerror="true"
@@ -1116,57 +688,30 @@
packagenames="${javadoc.packagenames}" >
<header><![CDATA[<strong>Unofficial Javadoc</strong> generated from developer sources for preview purposes only]]></header>
<arg line="@{options}"/>
- <arg value="-tag" />
- <arg value="implNote:a:Implementation Note:"/>
<bootclasspath>
- <path location="${build.classes.dir}"/>
+ <pathelement path="${langtools.classes}"/>
<path location="${target.java.home}/jre/lib/rt.jar"/>
</bootclasspath>
<sourcepath>
- <path refid="src.dirs"/>
+ <pathelement path="${langtools.sources}"/>
</sourcepath>
<!-- XXX just <fileset> (restricted further to **/*.java) and no <packageset> -->
<!-- means that {@link some.package} will not work, which is no good. -->
<!-- (It correctly skips excluded single classes, but not if packageset is also included, -->
<!-- which also causes duplicates in the class index for included files.) -->
- <packageset dir="${src.dir}/java.base/share/classes" includes="@{includes}">
+ <packageset dir="${basedir}/src/java.compiler/share/classes" includes="@{includes}">
<or>
- <filename name="java/"/>
<filename name="javax/"/>
- <filename name="com/sun/javadoc/"/>
- <filename name="com/sun/source/"/>
</or>
</packageset>
- <packageset dir="${src.dir}/java.compiler/share/classes" includes="@{includes}">
+ <packageset dir="${basedir}/src/jdk.compiler/share/classes" includes="@{includes}">
<or>
- <filename name="java/"/>
- <filename name="javax/"/>
- <filename name="com/sun/javadoc/"/>
<filename name="com/sun/source/"/>
</or>
</packageset>
- <packageset dir="${src.dir}/jdk.compiler/share/classes" includes="@{includes}">
- <or>
- <filename name="java/"/>
- <filename name="javax/"/>
- <filename name="com/sun/javadoc/"/>
- <filename name="com/sun/source/"/>
- </or>
- </packageset>
- <packageset dir="${src.dir}/jdk.dev/share/classes" includes="@{includes}">
+ <packageset dir="${basedir}/src/jdk.javadoc/share/classes" includes="@{includes}">
<or>
- <filename name="java/"/>
- <filename name="javax/"/>
<filename name="com/sun/javadoc/"/>
- <filename name="com/sun/source/"/>
- </or>
- </packageset>
- <packageset dir="${src.dir}/jdk.javadoc/share/classes" includes="@{includes}">
- <or>
- <filename name="java/"/>
- <filename name="javax/"/>
- <filename name="com/sun/javadoc/"/>
- <filename name="com/sun/source/"/>
</or>
</packageset>
</javadoc>
@@ -1184,6 +729,7 @@
<macrodef name="jtreg-tool">
<attribute name="name"/>
<attribute name="tests"/>
+ <attribute name="langtools.classes" default="${langtools.classes}"/>
<attribute name="jdk" default="${target.java.home}"/>
<attribute name="samevm" default="true"/>
<attribute name="verbose" default="${default.jtreg.verbose}"/>
@@ -1191,6 +737,7 @@
<attribute name="keywords" default="-keywords:!ignore"/>
<attribute name="jpda.jvmargs" default=""/>
<attribute name="extra.jvmargs" default=""/>
+ <attribute name="build.dir" default="${build.dir}"/>
<sequential>
<property name="coverage.options" value=""/> <!-- default -->
<property name="coverage.classpath" value=""/> <!-- default -->
@@ -1204,7 +751,7 @@
samevm="@{samevm}" verbose="@{verbose}"
failonerror="false" resultproperty="jtreg.@{name}.result"
javacoptions="-g"
- vmoptions="${coverage.options} -Xbootclasspath/p:${coverage.classpath}${path.separator}${build.classes.dir} @{jpda.jvmargs} @{extra.jvmargs}">
+ vmoptions="${coverage.options} -Xbootclasspath/p:${coverage.classpath}${path.separator}@{langtools.classes} @{jpda.jvmargs} @{extra.jvmargs}">
<arg line="@{keywords}"/>
<arg line="@{options}"/>
<arg line="@{tests}"/>
@@ -1220,21 +767,12 @@
<property name="jtreg.defined" value="true"/>
</target>
- <target name="-def-cobertura" depends="-check-cobertura.home">
- <path id="cobertura.classpath">
- <fileset dir="${cobertura.home}">
- <include name="cobertura.jar"/>
- <include name="lib/**/*.jar"/>
- </fileset>
- </path>
- <taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>
- </target>
-
- <target name="-def-checkstyle" unless="checkstyle.defined"
- depends="-check-checkstyle.home">
+ <target name="-def-checkstyle" unless="checkstyle.defined" depends="-check-checkstyle.home">
<taskdef resource="checkstyletask.properties">
<classpath>
- <pathelement location="${checkstyle.home}/${checkstyle.name.version}-all.jar"/>
+ <fileset dir="${checkstyle.home}">
+ <include name="checkstyle-*-all.jar"/>
+ </fileset>
</classpath>
</taskdef>
<property name="checkstyle.defined" value="true"/>
@@ -1265,7 +803,7 @@
jvmargs="-Xmx512M" >
<class location="${dist.dir}/lib/@{name}.jar"/>
<auxClasspath>
- <pathelement location="${build.classes.dir}"/>
+ <pathelement location="${langtools.classes}"/>
</auxClasspath>
<sourcePath>
<path refid="src.dirs"/>
@@ -1276,11 +814,6 @@
<property name="findbugs.defined" value="true"/>
</target>
- <target name="-def-vizant" unless="vizant.defined" depends="-check-vizant">
- <taskdef name="vizant" classname="net.sourceforge.vizant.Vizant" classpath="${vizant.jar}"/>
- <property name="vizant.defined" value="true"/>
- </target>
-
<target name="-def-check">
<macrodef name="check">
<attribute name="name"/>
--- a/langtools/make/intellij/build.xml Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/intellij/build.xml Mon Nov 17 12:32:27 2014 -0800
@@ -2,10 +2,8 @@
<project name="langtools" basedir="..">
<script language="javascript" classpath=".idea/classes">
- var ideaListener = project.getBuildListeners().firstElement();
var LangtoolsLogger = Java.type("idea.LangtoolsIdeaAntLogger");
- project.removeBuildListener(ideaListener)
- project.addBuildListener(new LangtoolsLogger(ideaListener))
+ new LangtoolsLogger(project)
</script>
<import file="../make/build.xml"/>
--- a/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java Mon Nov 17 12:32:27 2014 -0800
@@ -26,7 +26,9 @@
package idea;
import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.DefaultLogger;
+import org.apache.tools.ant.Project;
import java.util.EnumSet;
import java.util.Stack;
@@ -166,21 +168,17 @@
}
},
/** build bootstrap tool target - executed when bootstrapping javac */
- BUILD_BOOTSTRAP_TOOL("build-bootstrap-.*") {
+ BUILD_BOOTSTRAP_JAVAC("build-bootstrap-javac-classes") {
@Override
String getDisplayMessage(BuildEvent e) {
- String targetName = e.getTarget().getName();
- String tool = targetName.split("-")[2];
- return "Building bootstrap " + tool + "...";
+ return "Building bootstrap javac...";
}
},
/** build classes target - executed when building classes of given tool */
- BUILD_TOOL("build-classes-.*") {
+ BUILD_ALL_CLASSES("build-all-classes") {
@Override
String getDisplayMessage(BuildEvent e) {
- String targetName = e.getTarget().getName();
- String tool = targetName.split("-")[2];
- return "Building " + tool + "...";
+ return "Building all classes...";
}
},
/** synthetic target catching any other target not in this list */
@@ -195,14 +193,14 @@
}
};
- String targetRegex;
+ String targetName;
- Target(String targetRegex) {
- this.targetRegex = targetRegex;
+ Target(String targetName) {
+ this.targetName = targetName;
}
boolean matches(String msg) {
- return msg.matches(targetRegex);
+ return msg.equals(targetName);
}
abstract String getDisplayMessage(BuildEvent e);
@@ -253,8 +251,14 @@
/** stack of pending tasks */
Stack<Task> tasks = new Stack<>();
- public LangtoolsIdeaAntLogger(DefaultLogger logger) {
- this.logger = logger;
+ public LangtoolsIdeaAntLogger(Project project) {
+ for (Object o : project.getBuildListeners()) {
+ if (o instanceof DefaultLogger) {
+ this.logger = (DefaultLogger)o;
+ project.removeBuildListener((BuildListener)o);
+ project.addBuildListener(this);
+ }
+ }
tasks.push(Task.ROOT);
}
--- a/langtools/make/intellij/workspace.xml Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/intellij/workspace.xml Mon Nov 17 12:32:27 2014 -0800
@@ -10,7 +10,7 @@
<!-- standard tools -->
<configuration default="false" name="javac" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.sun.tools.javac.Main" />
- <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/classes" />
+ <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -24,12 +24,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javac" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<configuration default="false" name="javadoc" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.sun.tools.javadoc.Main" />
- <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/classes" />
+ <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -43,12 +43,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javadoc" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<configuration default="false" name="javap" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.sun.tools.javap.Main" />
- <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/classes" />
+ <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -62,12 +62,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javap" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<configuration default="false" name="javah" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.sun.tools.javah.Main" />
- <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/classes" />
+ <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -81,12 +81,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javah" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<configuration default="false" name="sjavac" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.sun.tools.sjavac.Main" />
- <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/classes" />
+ <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -100,13 +100,13 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-sjavac" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<!-- bootstrap javac -->
<configuration default="false" name="javac (bootstrap)" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.sun.tools.javac.Main" />
- <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/bootstrap/classes" />
+ <option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/bootstrap/java.compiler/classes:build/bootstrap/jdk.compiler/classes:build/bootstrap/java.base/classes:build/bootstrap/jdk.javadoc/classes:build/bootstrap/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
--- a/langtools/make/launcher.sh-template Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/launcher.sh-template Mon Nov 17 12:32:27 2014 -0800
@@ -43,10 +43,9 @@
# dependent jar files for additional dependencies.
if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then
- cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF |
- grep "Class-Path:" |
- sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1#PS#|g'`
- bcp="$mylib/#PROGRAM#.jar#PS#$cp"
+ cp=`echo "$mylib"/*.jar |
+ sed -e 's|\([a-z.]*\.jar\) *|\1#PS#|g'`
+ bcp=$cp
fi
# tools currently assumes that assertions are enabled in the launcher
@@ -72,4 +71,4 @@
unset DUALCASE
IFS=$nl
-"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} -jar "${mylib}/#PROGRAM#.jar" ${toolOpts}
+"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} com.sun.tools.#PROGRAM#.Main ${toolOpts}
--- a/langtools/make/netbeans/langtools/build.xml Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/netbeans/langtools/build.xml Mon Nov 17 12:32:27 2014 -0800
@@ -46,48 +46,34 @@
-->
<import file="../../build.xml"/>
- <!-- Build project. (action: build; F11)
- If langtools.tool.name is set, then just build that tool; otherwise
- build all tools.
- -->
-
- <target name="build" depends="-get-tool-if-set,-build-tool,-build-all"
- description="Build one or all langtools tools"
- />
+ <!-- Build project. (action: build; F11) -->
- <condition property="use_bootstrap" value="bootstrap-" else="">
- <isset property="langtools.tool.bootstrap"/>
- </condition>
- <condition property="with_bootclasspath" value="${build.bootstrap.dir}/classes" else="${build.classes.dir}">
- <isset property="langtools.tool.bootstrap"/>
- </condition>
-
- <target name="-build-tool" if="langtools.tool.name">
- <echo level="info" message="Building ${use_bootstrap}${langtools.tool.name}"/>
- <echo level="verbose" message="(Unset langtools.tool.name to build all tools)"/>
- <antcall target="build-${use_bootstrap}${langtools.tool.name}"/>
+ <target name="build" depends="-get-tool-if-set,-build-bootstrap-javac,-build-all" />
+ <target name="-build-bootstrap-javac" if="langtools.tool.bootstrap">
+ <antcall target="build-bootstrap-javac"/>
</target>
-
- <target name="-build-all" unless="langtools.tool.name">
- <echo level="info" message="Building all tools"/>
- <echo level="verbose" message="(Set langtools.tool.name to build a single tool)"/>
+ <target name="-build-all" unless="langtools.tool.bootstrap">
<antcall target="build-all-tools"/>
</target>
<!-- Compile a single file. (action: compile.single; F9) -->
- <target name="compile-single" depends="build-bootstrap-javac">
+ <target name="compile-single" depends="-get-tool-if-set,build-bootstrap-javac-classes" unless="langtools.tool.bootstrap">
<fail unless="includes">Must set property 'includes'</fail>
- <javac fork="true" executable="${build.bootstrap.dir}/bin/javac"
- srcdir="${srcdir}"
- destdir="${build.classes.dir}"
+ <mkdir dir="${build.dir}/${module.name}/classes" />
+ <javac fork="true" executable="${boot.java.home}/bin/javac"
+ srcdir="${basedir}/src/${module.name}/share/classes"
+ destdir="${build.dir}/${module.name}/classes"
includes="${includes}"
sourcepath=""
+ classpath="${langtools.classes}"
includeAntRuntime="no"
source="${javac.source}"
target="${javac.target}"
debug="${javac.debug}"
- debuglevel="${javac.debuglevel}"/>
+ debuglevel="${javac.debuglevel}">
+ <compilerarg value="-J-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
+ </javac>
</target>
<!-- Run tool. (action: run; F6)
@@ -95,16 +81,24 @@
the user.
-->
- <target name="run" depends="-check-target.java.home,build,-def-run,-get-tool-and-args"
+ <target name="run" depends="-check-target.java.home,-build-classes,-def-run,-get-tool-and-args,-setup-bootclasspath"
description="run tool">
<echo level="info" message="${with_bootclasspath}"/>
<echo level="info" message="Run ${use_bootstrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
<run bcp="${with_bootclasspath}" mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}"/>
</target>
+ <target name="-build-classes" depends="-get-tool-if-set,-build-classes-bootstrap-javac,-build-classes-all" />
+ <target name="-build-classes-bootstrap-javac" if="langtools.tool.bootstrap">
+ <antcall target="build-bootstrap-javac-classes"/>
+ </target>
+ <target name="-build-classes-all" unless="langtools.tool.bootstrap">
+ <antcall target="build-all-classes"/>
+ </target>
+
<!-- Run a selected class. (action: run.single; shift-F6) -->
- <target name="run-single" depends="-check-target.java.home,-def-run">
+ <target name="run-single" depends="-check-target.java.home,-setup-bootclasspath,-def-run">
<fail unless="run.classname">Must set property 'run.classname' </fail>
<echo level="info" message="run ${run.classname}"/>
<run mainclass="${run.classname}" args=""/>
@@ -115,22 +109,22 @@
test all tools.
-->
- <target name="jtreg" depends="-get-tool-if-set,-jtreg-tool,-jtreg-all"
- description="Test one or all langtools tools"
+ <target name="jtreg" depends="-get-tool-if-set,-jtreg-bootstrap-javac,-jtreg-all"
+ description="Test langtools tools or bootstrap javac"
/>
- <target name="-jtreg-tool" if="langtools.tool.name">
- <echo level="info" message="Testing ${langtools.tool.name}"/>
- <echo level="verbose" message="(Unset langtools.tool.name to test all tools)"/>
+ <target name="-jtreg-bootstrap-javac" if="langtools.tool.bootstrap">
+ <echo level="info" message="Testing bootstrap javac"/>
+ <echo level="verbose" message="(Unset langtools.tool.bootstrap to test all tools)"/>
<antcall>
- <target name="jtreg-${langtools.tool.name}"/>
+ <target name="jtreg-bootstrap-javac"/>
<target name="-show-jtreg"/>
</antcall>
</target>
- <target name="-jtreg-all" unless="langtools.tool.name">
+ <target name="-jtreg-all" unless="langtools.tool.bootstrap">
<echo level="info" message="Testing all tools"/>
- <echo level="verbose" message="(Set langtools.tool.name to test a single tool)"/>
+ <echo level="verbose" message="(Set langtools.tool.bootstrap to test bootstrap javac)"/>
<antcall>
<target name="langtools.jtreg"/>
<target name="-show-jtreg"/>
@@ -165,7 +159,7 @@
<!-- Debug tool in NetBeans. -->
- <target name="debug" depends="-check-target.java.home,-def-run,-def-start-debugger,-get-tool-and-args,build" if="netbeans.home">
+ <target name="debug" depends="-check-target.java.home,-def-run,-def-start-debugger,-get-tool-and-args,-setup-bootclasspath,-build-classes" if="netbeans.home">
<echo level="info" message="Debug ${use_bootstrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
<start-debugger/>
<run bcp="${with_bootclasspath}" mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}" jpda.jvmargs="${jpda.jvmargs}"/>
@@ -179,20 +173,29 @@
</target>
<!-- Debug a jtreg test. -->
- <target name="debug-jtreg" depends="-check-target.java.home,-def-start-debugger,-def-jtreg">
+ <target name="debug-jtreg" depends="-check-target.java.home,-def-start-debugger,-def-jtreg,-get-tool-if-set,-setup-bootclasspath">
<fail unless="jtreg.tests">Must set property 'jtreg.tests'</fail>
<start-debugger/>
- <jtreg-tool name="debug" samevm="false" tests="${jtreg.tests}" jpda.jvmargs="${jpda.jvmargs}"/>
+ <jtreg-tool name="debug"
+ samevm="false"
+ tests="${jtreg.tests}"
+ jpda.jvmargs="${jpda.jvmargs}"
+ langtools.classes="${with_bootclasspath}"/>
</target>
<!-- Update a class being debugged. -->
- <target name="debug-fix">
+ <target name="debug-fix" depends="-get-tool-if-set">
<fail unless="class">Must set property 'class'
</fail>
<antcall target="compile-single">
<param name="includes" value="${class}.java"/>
</antcall>
+ <condition property="build.classes.dir"
+ value="${build.dir}/${module.name}/classes"
+ else="${boot.build.dir}/${module.name}/classes">
+ <isset property="use_bootstrap"/>
+ </condition>
<nbjpdareload>
<fileset dir="${build.classes.dir}">
<include name="${class}.class"/>
@@ -205,31 +208,10 @@
test all tools.
-->
- <target name="javadoc" depends="-javadoc-tool,-javadoc-all"
- description="Generate javadoc for one or all langtools tools"
- />
-
- <target name="-javadoc-tool" if="langtools.tool.name">
- <echo level="info" message="Generate javadoc for ${langtools.tool.name}"/>
- <echo level="verbose" message="(Unset langtools.tool.name to generate javadoc for all tools)"/>
- <antcall>
- <target name="javadoc-${langtools.tool.name}"/>
- <target name="-show-javadoc"/>
- </antcall>
- </target>
-
- <target name="-javadoc-all" unless="langtools.tool.name">
- <echo level="info" message="Generate javadoc for all tools"/>
- <echo level="verbose" message="(Set langtools.tool.name to generate javadoc for a single tool)"/>
- <antcall>
- <target name="langtools.javadoc"/>
- <target name="-show-javadoc"/>
- </antcall>
- </target>
+ <target name="javadoc" depends="langtools.javadoc,-show-javadoc" />
<target name="-show-javadoc" if="netbeans.home">
- <!-- what if doing javadoc for all? -->
- <nbbrowse file="${build.javadoc.dir}/${langtools.tool.name}/index.html"/>
+ <nbbrowse file="${build.javadoc.dir}/index.html"/>
</target>
<!-- Prompt for values. -->
@@ -253,6 +235,15 @@
/>
</target>
+ <target name="-setup-bootclasspath">
+ <condition property="use_bootstrap" value="bootstrap-" else="">
+ <isset property="langtools.tool.bootstrap"/>
+ </condition>
+ <condition property="with_bootclasspath" value="${langtools.boot.classes}" else="${langtools.classes}">
+ <isset property="langtools.tool.bootstrap"/>
+ </condition>
+ </target>
+
<!-- Macro to run a tool or selected class - used by run* and debug* tasks -->
<target name="-def-run">
<macrodef name="run">
@@ -262,7 +253,7 @@
<attribute name="jpda.jvmargs" default=""/>
<sequential>
- <java fork="true" jvm="${target.java}" classname="@{mainclass}">
+ <java fork="true" jvm="${target.java.home}/bin/java" classname="@{mainclass}">
<jvmarg line="-Xbootclasspath/p:@{bcp}"/>
<jvmarg line="@{jpda.jvmargs}"/>
<arg line="@{args}"/>
@@ -278,11 +269,11 @@
<sequential>
<nbjpdastart name="${ant.project.name}" addressproperty="jpda.address" transport="dt_socket">
<bootclasspath>
- <pathelement location="${build.classes.dir}"/>
+ <pathelement path="${langtools.classes}"/>
<pathelement location="${target.java.home}/jre/lib/rt.jar"/>
</bootclasspath>
<sourcepath>
- <path refid="src.dirs"/>
+ <pathelement path="${langtools.sources}"/>
</sourcepath>
</nbjpdastart>
<property
--- a/langtools/make/netbeans/langtools/nbproject/project.xml Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/netbeans/langtools/nbproject/project.xml Mon Nov 17 12:32:27 2014 -0800
@@ -107,7 +107,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
- <property name="srcdir">src/java.base/share/classes</property>
+ <property name="module.name">java.base</property>
<context>
<property>includes</property>
<folder>${root}/src/java.base/share/classes</folder>
@@ -120,7 +120,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
- <property name="srcdir">src/java.compiler/share/classes</property>
+ <property name="module.name">java.compiler</property>
<context>
<property>includes</property>
<folder>${root}/src/java.compiler/share/classes</folder>
@@ -133,7 +133,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
- <property name="srcdir">src/jdk.compiler/share/classes</property>
+ <property name="module.name">jdk.compiler</property>
<context>
<property>includes</property>
<folder>${root}/src/jdk.compiler/share/classes</folder>
@@ -146,7 +146,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
- <property name="srcdir">src/jdk.dev/share/classes</property>
+ <property name="module.name">jdk.dev</property>
<context>
<property>includes</property>
<folder>${root}/src/jdk.dev/share/classes</folder>
@@ -159,7 +159,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
- <property name="srcdir">src/jdk.javadoc/share/classes</property>
+ <property name="module.name">jdk.javadoc</property>
<context>
<property>includes</property>
<folder>${root}/src/jdk.javadoc/share/classes</folder>
@@ -333,7 +333,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
- <property name="srcdir">src/java.base/share/classes</property>
+ <property name="module.name">java.base</property>
<context>
<property>class</property>
<folder>${root}/src/java.base/share/classes</folder>
@@ -346,7 +346,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
- <property name="srcdir">src/java.compiler/share/classes</property>
+ <property name="module.name">java.compiler</property>
<context>
<property>class</property>
<folder>${root}/src/java.compiler/share/classes</folder>
@@ -359,7 +359,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
- <property name="srcdir">src/jdk.compiler/share/classes</property>
+ <property name="module.name">jdk.compiler</property>
<context>
<property>class</property>
<folder>${root}/src/jdk.compiler/share/classes</folder>
@@ -372,7 +372,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
- <property name="srcdir">src/jdk.dev/share/classes</property>
+ <property name="module.name">jdk.dev</property>
<context>
<property>class</property>
<folder>${root}/src/jdk.dev/share/classes</folder>
@@ -385,7 +385,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
- <property name="srcdir">src/jdk.dev/share/classes</property>
+ <property name="module.name">jdk.javadoc</property>
<context>
<property>class</property>
<folder>${root}/src/jdk.javadoc/share/classes</folder>
@@ -478,11 +478,31 @@
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
<compilation-unit>
<package-root>${root}/src/java.base/share/classes</package-root>
+ <built-to>${root}/build/java.base/classes</built-to>
+ <source-level>1.8</source-level>
+ </compilation-unit>
+ <compilation-unit>
<package-root>${root}/src/java.compiler/share/classes</package-root>
+ <classpath mode="compile">${root}/build/java.base/classes</classpath>
+ <built-to>${root}/build/java.compiler/classes</built-to>
+ <source-level>1.8</source-level>
+ </compilation-unit>
+ <compilation-unit>
<package-root>${root}/src/jdk.compiler/share/classes</package-root>
+ <classpath mode="compile">${root}/build/java.base/classes:${root}/build/java.compiler/classes</classpath>
+ <built-to>${root}/build/jdk.compiler/classes</built-to>
+ <source-level>1.8</source-level>
+ </compilation-unit>
+ <compilation-unit>
<package-root>${root}/src/jdk.dev/share/classes</package-root>
+ <classpath mode="compile">${root}/build/java.base/classes:${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes</classpath>
+ <built-to>${root}/build/jdk.dev/classes</built-to>
+ <source-level>1.8</source-level>
+ </compilation-unit>
+ <compilation-unit>
<package-root>${root}/src/jdk.javadoc/share/classes</package-root>
- <built-to>${root}/build/classes</built-to>
+ <classpath mode="compile">${root}/build/java.base/classes:${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes</classpath>
+ <built-to>${root}/build/jdk.javadoc/classes</built-to>
<source-level>1.8</source-level>
</compilation-unit>
</java-data>
--- a/langtools/make/tools/anttasks/SelectToolTask.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/make/tools/anttasks/SelectToolTask.java Mon Nov 17 12:32:27 2014 -0800
@@ -74,7 +74,18 @@
enum ToolChoices {
NONE(""),
- JAVAC("javac"),
+ BOOSTRAP_JAVAC("bootstrap-javac", true) {
+ @Override
+ public ToolChoices baseTool() {
+ return JAVAC;
+ }
+ },
+ JAVAC("javac") {
+ @Override
+ public ToolChoices asBootstrap() {
+ return BOOSTRAP_JAVAC;
+ }
+ },
JAVADOC("javadoc"),
JAVAH("javah"),
JAVAP("javap");
@@ -91,6 +102,14 @@
this.bootstrap = bootstrap;
}
+ public ToolChoices asBootstrap() {
+ return this;
+ }
+
+ public ToolChoices baseTool() {
+ return this;
+ }
+
@Override
public String toString() {
return toolName;
@@ -176,9 +195,11 @@
JOptionPane p = createPane(guiProps);
p.createDialog("Select Tool").setVisible(true);
- toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName;
+ ToolChoices tool = (ToolChoices)toolChoice.getSelectedItem();
+
+ toolName = tool.baseTool().toolName;
+ toolBootstrap = tool.bootstrap;
toolArgs = argsField.getText();
- toolBootstrap = bootstrapCheckbox.isSelected();
if (defaultCheck.isSelected()) {
if (toolName.equals("")) {
fileProps.remove("tool.name");
@@ -213,30 +234,31 @@
EnumSet<ToolChoices> toolChoices = toolProperty == null ?
EnumSet.allOf(ToolChoices.class) : EnumSet.range(ToolChoices.JAVAC, ToolChoices.JAVAP);
toolChoice = new JComboBox<>(toolChoices.toArray());
- if (toolName != null)
- toolChoice.setSelectedItem(ToolChoices.valueOf(toolName.toUpperCase()));
+ ToolChoices tool = toolName != null ? ToolChoices.valueOf(toolName.toUpperCase()) : null;
+ if (toolName != null) {
+ if (toolBootstrap)
+ tool = tool.asBootstrap();
+ toolChoice.setSelectedItem(tool);
+ }
toolChoice.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
- String tn = ((ToolChoices)e.getItem()).toolName;
- argsField.setText(getDefaultArgsForTool(props, tn));
+ ToolChoices tool = (ToolChoices)e.getItem();
+ argsField.setText(getDefaultArgsForTool(props, tool));
if (toolProperty != null)
- okButton.setEnabled(!tn.equals(""));
+ okButton.setEnabled(tool != ToolChoices.NONE);
}
});
- GridBagConstraints checkConstraint = new GridBagConstraints();
fc.anchor = GridBagConstraints.EAST;
GridBagConstraints toolConstraint = new GridBagConstraints();
fc.anchor = GridBagConstraints.WEST;
toolPane.add(toolChoice, toolConstraint);
- bootstrapCheckbox = new JCheckBox("bootstrap", toolBootstrap);
- toolPane.add(bootstrapCheckbox, checkConstraint);
body.add(toolPane, fc);
- argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40);
+ argsField = new JTextField(getDefaultArgsForTool(props, tool), 40);
if (toolProperty == null || argsProperty != null) {
JLabel argsLabel = new JLabel("Args:");
body.add(argsLabel, lc);
@@ -322,8 +344,11 @@
}
}
- String getDefaultArgsForTool(Properties props, String tn) {
- return (tn == null || tn.equals("")) ? "" : props.getProperty(tn + ".args", "");
+ String getDefaultArgsForTool(Properties props, ToolChoices tool) {
+ if (tool == null)
+ return "";
+ String toolName = tool.baseTool().toolName;
+ return toolName.equals("") ? "" : props.getProperty(toolName + ".args", "");
}
// Ant task parameters
@@ -335,7 +360,6 @@
// GUI components
private JComboBox<?> toolChoice;
- private JCheckBox bootstrapCheckbox;
private JTextField argsField;
private JCheckBox defaultCheck;
private JButton okButton;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TaskListener.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TaskListener.java Mon Nov 17 12:32:27 2014 -0800
@@ -37,13 +37,19 @@
{
/**
* Invoked when an event has begun.
+ *
+ * @implSpec The default implementation of this method does nothing.
+ *
* @param e the event
*/
- public void started(TaskEvent e);
+ default void started(TaskEvent e) { }
/**
* Invoked when an event has been completed.
+ *
+ * @implSpec The default implementation of this method does nothing.
+ *
* @param e the event
*/
- public void finished(TaskEvent e);
+ default void finished(TaskEvent e) { }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java Mon Nov 17 12:32:27 2014 -0800
@@ -305,7 +305,32 @@
* the table of its outer scope.
*/
public WriteableScope dupUnshared(Symbol newOwner) {
- return new ScopeImpl(this, newOwner, this.table.clone(), this.nelems);
+ if (shared > 0) {
+ //The nested Scopes might have already added something to the table, so all items
+ //that don't originate in this Scope or any of its outer Scopes need to be cleared:
+ Set<Scope> acceptScopes = Collections.newSetFromMap(new IdentityHashMap<>());
+ ScopeImpl c = this;
+ while (c != null) {
+ acceptScopes.add(c);
+ c = c.next;
+ }
+ int n = 0;
+ Entry[] oldTable = this.table;
+ Entry[] newTable = new Entry[this.table.length];
+ for (int i = 0; i < oldTable.length; i++) {
+ Entry e = oldTable[i];
+ while (e != null && e != sentinel && !acceptScopes.contains(e.scope)) {
+ e = e.shadowed;
+ }
+ if (e != null) {
+ n++;
+ newTable[i] = e;
+ }
+ }
+ return new ScopeImpl(this, newOwner, newTable, n);
+ } else {
+ return new ScopeImpl(this, newOwner, this.table.clone(), this.nelems);
+ }
}
/** Remove all entries of this scope from its table, if shared
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java Mon Nov 17 12:32:27 2014 -0800
@@ -145,7 +145,7 @@
public final int bound_index;
// For type parameter and method parameter
- public final int parameter_index;
+ public int parameter_index;
// For class extends, implements, and throws clauses
public final int type_index;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Mon Nov 17 12:32:27 2014 -0800
@@ -1196,35 +1196,35 @@
boolean hasDefault = false; // Is there a default label?
for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
JCCase c = l.head;
+ if (c.pat != null) {
+ if (enumSwitch) {
+ Symbol sym = enumConstant(c.pat, seltype);
+ if (sym == null) {
+ log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
+ } else if (!labels.add(sym)) {
+ log.error(c.pos(), "duplicate.case.label");
+ }
+ } else {
+ Type pattype = attribExpr(c.pat, switchEnv, seltype);
+ if (!pattype.hasTag(ERROR)) {
+ if (pattype.constValue() == null) {
+ log.error(c.pat.pos(),
+ (stringSwitch ? "string.const.req" : "const.expr.req"));
+ } else if (labels.contains(pattype.constValue())) {
+ log.error(c.pos(), "duplicate.case.label");
+ } else {
+ labels.add(pattype.constValue());
+ }
+ }
+ }
+ } else if (hasDefault) {
+ log.error(c.pos(), "duplicate.default.label");
+ } else {
+ hasDefault = true;
+ }
Env<AttrContext> caseEnv =
switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
try {
- if (c.pat != null) {
- if (enumSwitch) {
- Symbol sym = enumConstant(c.pat, seltype);
- if (sym == null) {
- log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
- } else if (!labels.add(sym)) {
- log.error(c.pos(), "duplicate.case.label");
- }
- } else {
- Type pattype = attribExpr(c.pat, switchEnv, seltype);
- if (!pattype.hasTag(ERROR)) {
- if (pattype.constValue() == null) {
- log.error(c.pat.pos(),
- (stringSwitch ? "string.const.req" : "const.expr.req"));
- } else if (labels.contains(pattype.constValue())) {
- log.error(c.pos(), "duplicate.case.label");
- } else {
- labels.add(pattype.constValue());
- }
- }
- }
- } else if (hasDefault) {
- log.error(c.pos(), "duplicate.default.label");
- } else {
- hasDefault = true;
- }
attribStats(c.stats, caseEnv);
} finally {
caseEnv.info.scope.leave();
@@ -1429,21 +1429,28 @@
case APPLY:
JCMethodInvocation speculativeMethodTree =
(JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo);
- Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType();
- return types.unboxedTypeOrType(owntype).isPrimitive();
+ Symbol msym = TreeInfo.symbol(speculativeMethodTree.meth);
+ Type receiverType = speculativeMethodTree.meth.hasTag(IDENT) ?
+ env.enclClass.type :
+ ((JCFieldAccess)speculativeMethodTree.meth).selected.type;
+ Type owntype = types.memberType(receiverType, msym).getReturnType();
+ return primitiveOrBoxed(owntype);
case NEWCLASS:
JCExpression className =
removeClassParams.translate(((JCNewClass)tree).clazz);
JCExpression speculativeNewClassTree =
(JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo);
- return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive();
+ return primitiveOrBoxed(speculativeNewClassTree.type);
default:
Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type;
- speculativeType = types.unboxedTypeOrType(speculativeType);
- return speculativeType.isPrimitive();
+ return primitiveOrBoxed(speculativeType);
}
}
//where
+ boolean primitiveOrBoxed(Type t) {
+ return (!t.hasTag(TYPEVAR) && types.unboxedTypeOrType(t).isPrimitive());
+ }
+
TreeTranslator removeClassParams = new TreeTranslator() {
@Override
public void visitTypeApply(JCTypeApply tree) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Mon Nov 17 12:32:27 2014 -0800
@@ -1213,7 +1213,10 @@
return;
}
scan(tree.falsepart);
- result = reduce(ArgumentExpressionKind.PRIMITIVE);
+ result = reduce(ArgumentExpressionKind.PRIMITIVE).isPrimitive() ?
+ ArgumentExpressionKind.PRIMITIVE :
+ ArgumentExpressionKind.POLY;
+
}
@Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Mon Nov 17 12:32:27 2014 -0800
@@ -2642,9 +2642,10 @@
syms.intType, tree.sym);
ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
+ MethodSymbol m = tree.sym;
tree.params = tree.params.prepend(ordParam).prepend(nameParam);
-
- MethodSymbol m = tree.sym;
+ incrementParamTypeAnnoIndexes(m, 2);
+
m.extraParams = m.extraParams.prepend(ordParam.sym);
m.extraParams = m.extraParams.prepend(nameParam.sym);
Type olderasure = m.erasure(types);
@@ -2667,6 +2668,17 @@
}
}
//where
+ private void incrementParamTypeAnnoIndexes(MethodSymbol m,
+ int amount) {
+ for (final Attribute.TypeCompound anno : m.getRawTypeAttributes()) {
+ // Increment the parameter_index of any existing formal
+ // parameter annotations.
+ if (anno.position.type == TargetType.METHOD_FORMAL_PARAMETER) {
+ anno.position.parameter_index += amount;
+ }
+ }
+ }
+
private void visitMethodDefInternal(JCMethodDecl tree) {
if (tree.name == names.init &&
(currentClass.isInner() || currentClass.isLocal())) {
@@ -2697,8 +2709,10 @@
// Add this$n (if needed) in front of and free variables behind
// constructor parameter list.
tree.params = tree.params.appendList(fvdefs);
- if (currentClass.hasOuterInstance())
+ if (currentClass.hasOuterInstance()) {
tree.params = tree.params.prepend(otdef);
+ incrementParamTypeAnnoIndexes(m, 1);
+ }
// If this is an initial constructor, i.e., it does not start with
// this(...), insert initializers for this$n and proxies
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java Mon Nov 17 12:32:27 2014 -0800
@@ -111,6 +111,8 @@
Collection<String> args = formatArguments(d, l);
String msg = localize(l, d.getCode(), args.toArray());
String[] lines = msg.split("\n");
+ if (lines.length == 0) // will happen when msg only contains one or more separators: "\n", "\n\n", etc.
+ lines = new String[] { "" };
if (getConfiguration().getVisible().contains(DiagnosticPart.SUMMARY)) {
currentIndentation += getConfiguration().getIndentation(DiagnosticPart.SUMMARY);
buf.append(indent(lines[0], currentIndentation)); //summary
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Mon Nov 17 12:32:27 2014 -0800
@@ -218,21 +218,21 @@
// Collect the name of all compiled packages.
Set<String> recently_compiled = new HashSet<>();
boolean[] rc = new boolean[1];
+ boolean background = Util.extractBooleanOption("background", options.getServerConf(), true);
Sjavac sjavac;
- boolean background = Util.extractBooleanOption("background", options.getServerConf(), true);
+ // Create an sjavac implementation to be used for compilation
+ if (background) {
+ sjavac = new SjavacClient(options);
+ } else {
+ int poolsize = Util.extractIntOption("poolsize", options.getServerConf());
+ if (poolsize <= 0)
+ poolsize = Runtime.getRuntime().availableProcessors();
+ sjavac = new PooledSjavac(new SjavacImpl(), poolsize);
+ }
+
do {
// Clean out artifacts in tainted packages.
javac_state.deleteClassArtifactsInTaintedPackages();
- // Create an sjavac implementation to be used for compilation
- if (background) {
- sjavac = new SjavacClient(options);
- } else {
- int poolsize = Util.extractIntOption("poolsize", options.getServerConf());
- if (poolsize <= 0)
- poolsize = Runtime.getRuntime().availableProcessors();
- sjavac = new PooledSjavac(new SjavacImpl(), poolsize);
- }
-
again = javac_state.performJavaCompilations(sjavac, options, recently_compiled, rc);
if (!rc[0]) break;
} while (again);
--- a/langtools/test/tools/javac/6508981/TestInferBinaryName.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/6508981/TestInferBinaryName.java Mon Nov 17 12:32:27 2014 -0800
@@ -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
@@ -26,7 +26,8 @@
* @bug 6508981
* @summary cleanup file separator handling in JavacFileManager
* (This test is specifically to test the new impl of inferBinaryName)
- * @build p.A
+ * @library /tools/lib
+ * @build ToolBox p.A
* @run main TestInferBinaryName
*/
@@ -61,51 +62,75 @@
//System.err.println(System.getProperties());
testDirectory();
testSymbolArchive();
- testZipArchive();
- testZipFileIndexArchive();
- testZipFileIndexArchive2();
+
+ File testJar = createJar();
+
+ testZipArchive(testJar);
+ testZipFileIndexArchive(testJar);
+ testZipFileIndexArchive2(testJar);
if (errors > 0)
throw new Exception(errors + " error found");
}
+ File createJar() throws IOException {
+ File f = new File("test.jar");
+ try (JavaFileManager fm = new JavacFileManager(new Context(), false, null)) {
+ ToolBox tb = new ToolBox();
+ tb.new JarTask(f.getPath())
+ .files(fm, StandardLocation.PLATFORM_CLASS_PATH, "java.lang.*")
+ .run();
+ }
+ return f;
+ }
+
void testDirectory() throws IOException {
String testClassName = "p.A";
- JavaFileManager fm =
- getFileManager("test.classes", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
- test("testDirectory",
- fm, testClassName, "com.sun.tools.javac.file.RegularFileObject");
+ List<File> testClasses = Arrays.asList(new File(System.getProperty("test.classes")));
+ try (JavaFileManager fm =
+ getFileManager(testClasses, USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) {
+ test("testDirectory",
+ fm, testClassName, "com.sun.tools.javac.file.RegularFileObject");
+ }
}
void testSymbolArchive() throws IOException {
String testClassName = "java.lang.String";
- JavaFileManager fm =
- getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX);
- test("testSymbolArchive",
- fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject");
+ List<File> path = getPath(System.getProperty("sun.boot.class.path"));
+ try (JavaFileManager fm =
+ getFileManager(path, USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX)) {
+ test("testSymbolArchive",
+ fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject");
+ }
}
- void testZipArchive() throws IOException {
+ void testZipArchive(File testJar) throws IOException {
String testClassName = "java.lang.String";
- JavaFileManager fm =
- getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX);
- test("testZipArchive",
- fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject");
+ List<File> path = Arrays.asList(testJar);
+ try (JavaFileManager fm =
+ getFileManager(path, IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX)) {
+ test("testZipArchive",
+ fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject");
+ }
}
- void testZipFileIndexArchive() throws IOException {
+ void testZipFileIndexArchive(File testJar) throws IOException {
String testClassName = "java.lang.String";
- JavaFileManager fm =
- getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
- test("testZipFileIndexArchive",
- fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
+ List<File> path = Arrays.asList(testJar);
+ try (JavaFileManager fm =
+ getFileManager(path, USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) {
+ test("testZipFileIndexArchive",
+ fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
+ }
}
- void testZipFileIndexArchive2() throws IOException {
+ void testZipFileIndexArchive2(File testJar) throws IOException {
String testClassName = "java.lang.String";
- JavaFileManager fm =
- getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
- test("testZipFileIndexArchive2",
- fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
+ List<File> path = Arrays.asList(testJar);
+ try (JavaFileManager fm =
+ getFileManager(path, IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) {
+ test("testZipFileIndexArchive2",
+ fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
+ }
}
/**
@@ -133,7 +158,7 @@
System.err.println("OK");
}
- JavaFileManager getFileManager(String classpathProperty,
+ JavaFileManager getFileManager(List<File> path,
boolean symFileKind,
boolean zipFileIndexKind)
throws IOException {
@@ -145,7 +170,6 @@
if (symFileKind == IGNORE_SYMBOL_FILE)
options.put("ignore.symbol.file", "true");
JavacFileManager fm = new JavacFileManager(ctx, false, null);
- List<File> path = getPath(System.getProperty(classpathProperty));
fm.setLocation(CLASS_PATH, path);
return fm;
}
--- a/langtools/test/tools/javac/ConditionalWithVoid.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/ConditionalWithVoid.java Mon Nov 17 12:32:27 2014 -0800
@@ -1,14 +1,16 @@
/*
* @test /nodynamiccopyright/
- * @bug 4974927
+ * @bug 4974927 8064464
* @summary The compiler was allowing void types in its parsing of conditional expressions.
* @author tball
*
* @compile/fail/ref=ConditionalWithVoid.out -XDrawDiagnostics ConditionalWithVoid.java
*/
public class ConditionalWithVoid {
- public int test(Object o) {
- // Should fail to compile since Object.wait() has a void return type.
+ public void test(Object o) {
+ // Should fail to compile since Object.wait() has a void return type. Poly case.
System.out.println(o instanceof String ? o.hashCode() : o.wait());
+ // Should fail to compile since Object.wait() has a void return type. Standalone case.
+ (o instanceof String ? o.hashCode() : o.wait()).toString();
}
}
--- a/langtools/test/tools/javac/ConditionalWithVoid.out Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/ConditionalWithVoid.out Mon Nov 17 12:32:27 2014 -0800
@@ -1,2 +1,3 @@
-ConditionalWithVoid.java:12:48: compiler.err.neither.conditional.subtype: java.lang.Integer, void
-1 error
+ConditionalWithVoid.java:12:71: compiler.err.void.not.allowed.here
+ConditionalWithVoid.java:14:30: compiler.err.neither.conditional.subtype: java.lang.Integer, void
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,950 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+import java.lang.annotation.*;
+import java.io.*;
+import java.net.URL;
+import java.util.List;
+
+import com.sun.tools.classfile.*;
+
+/**
+ * A class providing utilities for writing tests that inspect class
+ * files directly, looking for specific type annotations.
+ *
+ * Note: this framework does not currently handle repeating
+ * annotations.
+ */
+public class ClassfileInspector {
+
+ /**
+ * A group of expected annotations to be found in a given class.
+ * If the class name is null, then the template will be applied to
+ * every class.
+ */
+ public static class Expected {
+ /**
+ * The name of the class. If {@code null} this template will
+ * apply to every class; otherwise, it will only be applied to
+ * the named class.
+ */
+ public final String classname;
+
+ /**
+ * The expected class annotations. These will be checked
+ * against the class' attributes.
+ */
+ public final ExpectedTypeAnnotation[] classAnnos;
+
+ /**
+ * The expected method annotations. These will be checked
+ * against all methods in the class.
+ */
+ public final ExpectedMethodTypeAnnotation[] methodAnnos;
+
+ /**
+ * The expected field annotations. These will be checked
+ * against all fields in the class.
+ */
+ public final ExpectedFieldTypeAnnotation[] fieldAnnos;
+
+ /**
+ * Create an {@code Expected} from its components.
+ *
+ * @param classname The name of the class to match, or {@code
+ * null} for all classes.
+ * @param classAnnos The expected class annotations.
+ * @param methodAnnos The expected method annotations.
+ * @param fieldAnnos The expected field annotations.
+ */
+ public Expected(String classname,
+ ExpectedTypeAnnotation[] classAnnos,
+ ExpectedMethodTypeAnnotation[] methodAnnos,
+ ExpectedFieldTypeAnnotation[] fieldAnnos) {
+ this.classname = classname;
+ this.classAnnos = classAnnos;
+ this.methodAnnos = methodAnnos;
+ this.fieldAnnos = fieldAnnos;
+ }
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ final String newline = System.lineSeparator();
+ sb.append("Expected on class ").append(classname);
+ if (null != classAnnos) {
+ sb.append(newline).append("Class annotations:").append(newline);
+ for(ExpectedTypeAnnotation anno : classAnnos) {
+ sb.append(anno).append(newline);
+ }
+ }
+ if (null != methodAnnos) {
+ sb.append(newline).append("Method annotations:").append(newline);
+ for(ExpectedTypeAnnotation anno : methodAnnos) {
+ sb.append(anno).append(newline);
+ }
+ }
+ if (null != fieldAnnos) {
+ sb.append(newline).append("Field annotations:").append(newline);
+ for(ExpectedTypeAnnotation anno : fieldAnnos) {
+ sb.append(anno).append(newline);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * See if this template applies to a class.
+ *
+ * @param classname The classname to check.
+ * @return Whether or not this template should apply.
+ */
+ public boolean matchClassName(String classname) {
+ return this.classname == null || this.classname.equals(classname);
+ }
+
+ /**
+ * After applying the template to all classes, check to see if
+ * any of the expected annotations weren't matched.
+ *
+ * @return The number of missed matches.
+ */
+ public int check() {
+ int count = 0;
+ if (classAnnos != null) {
+ for(ExpectedTypeAnnotation expected : classAnnos) {
+ if (!expected.check()) {
+ count++;
+ }
+ }
+ }
+ if (methodAnnos != null) {
+ for(ExpectedMethodTypeAnnotation expected : methodAnnos) {
+ if (!expected.check()) {
+ count++;
+ }
+ }
+ }
+ if (fieldAnnos != null) {
+ for(ExpectedFieldTypeAnnotation expected : fieldAnnos) {
+ if (!expected.check()) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+ }
+
+ /**
+ * An expected type annotation. This is both a superclass for
+ * method and field type annotations, as well as a class for type
+ * annotations on a class.
+ */
+ public static class ExpectedTypeAnnotation {
+ private int count = 0;
+ protected final String expectedName;
+ protected final int expectedCount;
+ protected final TypeAnnotation.TargetType targetType;
+ protected final int bound_index;
+ protected final int parameter_index;
+ protected final int type_index;
+ protected final int exception_index;
+ protected final TypeAnnotation.Position.TypePathEntry[] typePath;
+ protected final boolean visibility;
+
+ /**
+ * Create an {@code ExpectedTypeAnnotation} from its
+ * components. It is usually a better idea to use a {@code
+ * Builder} to do this.
+ *
+ * @param expectedName The expected annotation name.
+ * @param visibility Whether this annotation should be runtime-visible.
+ * @param expectedCount The number of annotations that should
+ * be seen. If 0, this asserts that the
+ * described annotation is not present.
+ * @param targetType The expected target type.
+ * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
+ * @param parameter_index The expected parameter index, or
+ * {@code Integer.MIN_VALUE}.
+ * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
+ * @param exception_index The expected exception index, or
+ * {@code Integer.MIN_VALUE}.
+ * @param typePath The expected type path.
+ */
+ public ExpectedTypeAnnotation(String expectedName,
+ boolean visibility,
+ int expectedCount,
+ TypeAnnotation.TargetType targetType,
+ int bound_index,
+ int parameter_index,
+ int type_index,
+ int exception_index,
+ TypeAnnotation.Position.TypePathEntry... typePath) {
+ this.expectedName = expectedName;
+ this.visibility = visibility;
+ this.expectedCount = expectedCount;
+ this.targetType = targetType;
+ this.bound_index = bound_index;
+ this.parameter_index = parameter_index;
+ this.type_index = type_index;
+ this.exception_index = exception_index;
+ this.typePath = typePath;
+ }
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Expected ");
+ sb.append(expectedCount);
+ sb.append(" annotation ");
+ sb.append(expectedName);
+ sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
+ sb.append(targetType);
+ sb.append(", bound_index = ");
+ sb.append(bound_index);
+ sb.append(", parameter_index = ");
+ sb.append(parameter_index);
+ sb.append(", type_index = ");
+ sb.append(type_index);
+ sb.append(", exception_index = ");
+ sb.append(exception_index);
+ sb.append(", type_path = [");
+ for(int i = 0; i < typePath.length; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ sb.append(typePath[i]);
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ /**
+ * See if this template matches the given visibility.
+ *
+ * @param Whether or not the annotation is visible at runtime.
+ * @return Whether or not this template matches the visibility.
+ */
+ public boolean matchVisibility(boolean visibility) {
+ return this.visibility == visibility;
+ }
+
+ /**
+ * Attempty to match this template against an annotation. If
+ * it does match, then the match count for the template will
+ * be incremented. Otherwise, nothing will be done.
+ *
+ * @param anno The annotation to attempt to match.
+ */
+ public void matchAnnotation(TypeAnnotation anno) {
+ boolean matches = true;
+
+ try {
+ matches = anno.constant_pool.getUTF8Info(anno.annotation.type_index).value.equals("L" + expectedName + ";");
+ } catch(Exception e) {
+ matches = false;
+ }
+
+ matches = matches && anno.position.type == targetType;
+ matches = matches && anno.position.bound_index == bound_index;
+ matches = matches && anno.position.parameter_index == parameter_index;
+ matches = matches && anno.position.type_index == type_index;
+ matches = matches && anno.position.exception_index == exception_index;
+ matches = matches && anno.position.location.size() == typePath.length;
+
+ if (matches) {
+ int i = 0;
+ for(TypeAnnotation.Position.TypePathEntry entry :
+ anno.position.location) {
+ matches = matches && typePath[i++].equals(entry);
+ }
+ }
+
+ if (matches) {
+ count++;
+ }
+ }
+
+ /**
+ * After all matching, check to see if the expected number of
+ * matches equals the actual number. If not, then print a
+ * failure message and return {@code false}.
+ *
+ * @return Whether or not the expected number of matched
+ * equals the actual number.
+ */
+ public boolean check() {
+ if (count != expectedCount) {
+ System.err.println(this + ", but saw " + count);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * A builder class for creating {@code
+ * ExpectedTypeAnnotation}s in a more convenient fashion. The
+ * constructor for {@code ExpectedTypeAnnotation} takes a
+ * large number of parameters (by necessity). This class
+ * allows users to construct a {@code ExpectedTypeAnnotation}s
+ * using only the ones they need.
+ */
+ public static class Builder {
+ protected final String expectedName;
+ protected final int expectedCount;
+ protected final TypeAnnotation.TargetType targetType;
+ protected final boolean visibility;
+ protected int bound_index = Integer.MIN_VALUE;
+ protected int parameter_index = Integer.MIN_VALUE;
+ protected int type_index = Integer.MIN_VALUE;
+ protected int exception_index = Integer.MIN_VALUE;
+ protected TypeAnnotation.Position.TypePathEntry[] typePath =
+ new TypeAnnotation.Position.TypePathEntry[0];
+
+ /**
+ * Create a {@code Builder} from the mandatory parameters.
+ *
+ * @param expectedName The expected annotation name.
+ * @param targetType The expected target type.
+ * @param visibility Whether this annotation should be runtime-visible.
+ * @param expectedCount The number of annotations that should be seen.
+ */
+ public Builder(String expectedName,
+ TypeAnnotation.TargetType targetType,
+ boolean visibility,
+ int expectedCount) {
+ this.expectedName = expectedName;
+ this.visibility = visibility;
+ this.expectedCount = expectedCount;
+ this.targetType = targetType;
+ }
+
+ /**
+ * Create an {@code ExpectedTypeAnnotation} from all
+ * parameters that have been provided. The default values
+ * will be used for those that have not.
+ *
+ * @return The cretaed {@code ExpectedTypeAnnotation}.
+ */
+ public ExpectedTypeAnnotation build() {
+ return new ExpectedTypeAnnotation(expectedName, visibility,
+ expectedCount, targetType,
+ bound_index, parameter_index,
+ type_index, exception_index,
+ typePath);
+ }
+
+ /**
+ * Provide a bound index parameter.
+ *
+ * @param bound_index The bound_index value.
+ */
+ public Builder setBoundIndex(int bound_index) {
+ this.bound_index = bound_index;
+ return this;
+ }
+
+ /**
+ * Provide a parameter index parameter.
+ *
+ * @param bound_index The parameter_index value.
+ */
+ public Builder setParameterIndex(int parameter_index) {
+ this.parameter_index = parameter_index;
+ return this;
+ }
+
+ /**
+ * Provide a type index parameter.
+ *
+ * @param type_index The type_index value.
+ */
+ public Builder setTypeIndex(int type_index) {
+ this.type_index = type_index;
+ return this;
+ }
+
+ /**
+ * Provide an exception index parameter.
+ *
+ * @param exception_index The exception_index value.
+ */
+ public Builder setExceptionIndex(int exception_index) {
+ this.exception_index = exception_index;
+ return this;
+ }
+
+ /**
+ * Provide a type path parameter.
+ *
+ * @param typePath The type path value.
+ */
+ public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) {
+ this.typePath = typePath;
+ return this;
+ }
+ }
+ }
+
+ /**
+ * A type annotation found on a method.
+ */
+ public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation {
+ private final String methodname;
+
+ /**
+ * Create an {@code ExpectedMethodTypeAnnotation} from its
+ * components. It is usually a better idea to use a {@code
+ * Builder} to do this.
+ *
+ * @param methodname The expected method name.
+ * @param expectedName The expected annotation name.
+ * @param visibility Whether this annotation should be runtime-visible.
+ * @param expectedCount The number of annotations that should be seen.
+ * @param targetType The expected target type.
+ * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
+ * @param parameter_index The expected parameter index, or
+ * {@code Integer.MIN_VALUE}.
+ * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
+ * @param exception_index The expected exception index, or
+ * {@code Integer.MIN_VALUE}.
+ * @param typePath The expected type path.
+ */
+ public ExpectedMethodTypeAnnotation(String methodname,
+ String expectedName,
+ boolean visibility,
+ int expectedCount,
+ TypeAnnotation.TargetType targetType,
+ int bound_index,
+ int parameter_index,
+ int type_index,
+ int exception_index,
+ TypeAnnotation.Position.TypePathEntry... typePath) {
+ super(expectedName, visibility, expectedCount, targetType, bound_index,
+ parameter_index, type_index, exception_index, typePath);
+ this.methodname = methodname;
+ }
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Expected ");
+ sb.append(expectedCount);
+ sb.append(" annotation ");
+ sb.append(expectedName);
+ sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
+ sb.append(targetType);
+ sb.append(", bound_index = ");
+ sb.append(bound_index);
+ sb.append(", parameter_index = ");
+ sb.append(parameter_index);
+ sb.append(", type_index = ");
+ sb.append(type_index);
+ sb.append(", exception_index = ");
+ sb.append(exception_index);
+ sb.append(", type_path = [");
+ for(int i = 0; i < typePath.length; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ sb.append(typePath[i]);
+ }
+ sb.append("]");
+ sb.append(" on method ");
+ sb.append(methodname);
+ return sb.toString();
+ }
+
+ /**
+ * See if this template applies to a method.
+ *
+ * @param methodname The method name to check.
+ * @return Whether or not this template should apply.
+ */
+ public boolean matchMethodName(String methodname) {
+ return this.methodname.equals(methodname);
+ }
+
+ /**
+ * A builder class for creating {@code
+ * ExpectedMethodTypeAnnotation}s in a more convenient fashion. The
+ * constructor for {@code ExpectedMethodTypeAnnotation} takes a
+ * large number of parameters (by necessity). This class
+ * allows users to construct a {@code ExpectedMethodTypeAnnotation}s
+ * using only the ones they need.
+ */
+ public static class Builder extends ExpectedTypeAnnotation.Builder {
+ protected final String methodname;
+
+ /**
+ * Create a {@code Builder} from the mandatory parameters.
+ *
+ * @param methodname The expected method name.
+ * @param expectedName The expected annotation name.
+ * @param targetType The expected target type.
+ * @param visibility Whether this annotation should be runtime-visible.
+ * @param expectedCount The number of annotations that should be seen.
+ */
+ public Builder(String methodname,
+ String expectedName,
+ TypeAnnotation.TargetType targetType,
+ boolean visibility,
+ int expectedCount) {
+ super(expectedName, targetType, visibility, expectedCount);
+ this.methodname = methodname;
+ }
+
+ /**
+ * Create an {@code ExpectedMethodTypeAnnotation} from all
+ * parameters that have been provided. The default values
+ * will be used for those that have not.
+ *
+ * @return The cretaed {@code ExpectedMethodTypeAnnotation}.
+ */
+ public ExpectedMethodTypeAnnotation build() {
+ return new ExpectedMethodTypeAnnotation(methodname, expectedName,
+ visibility, expectedCount,
+ targetType, bound_index,
+ parameter_index, type_index,
+ exception_index, typePath);
+ }
+ }
+ }
+
+ /**
+ * A type annotation found on a field.
+ */
+ public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation {
+ private final String fieldname;
+
+ /**
+ * Create an {@code ExpectedFieldTypeAnnotation} from its
+ * components. It is usually a better idea to use a {@code
+ * Builder} to do this.
+ *
+ * @param fieldname The expected field name.
+ * @param expectedName The expected annotation name.
+ * @param visibility Whether this annotation should be runtime-visible.
+ * @param expectedCount The number of annotations that should be seen.
+ * @param targetType The expected target type.
+ * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
+ * @param parameter_index The expected parameter index, or
+ * {@code Integer.MIN_VALUE}.
+ * @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
+ * @param exception_index The expected exception index, or
+ * {@code Integer.MIN_VALUE}.
+ * @param typePath The expected type path.
+ */
+ public ExpectedFieldTypeAnnotation(String fieldname,
+ String expectedName,
+ boolean visibility,
+ int expectedCount,
+ TypeAnnotation.TargetType targetType,
+ int bound_index,
+ int parameter_index,
+ int type_index,
+ int exception_index,
+ TypeAnnotation.Position.TypePathEntry... typePath) {
+ super(expectedName, visibility, expectedCount, targetType, bound_index,
+ parameter_index, type_index, exception_index, typePath);
+ this.fieldname = fieldname;
+ }
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Expected ").append(expectedCount)
+ .append(" annotation ").append(expectedName)
+ .append(visibility ? ", runtime visibile " : ", runtime invisibile ")
+ .append(targetType)
+ .append(", bound_index = ").append(bound_index)
+ .append(", parameter_index = ").append(parameter_index)
+ .append(", type_index = ").append(type_index)
+ .append(", exception_index = ").append(exception_index)
+ .append(", type_path = [");
+
+ for(int i = 0; i < typePath.length; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ sb.append(typePath[i]);
+ }
+ sb.append("]")
+ .append(" on field ").append(fieldname);
+ return sb.toString();
+ }
+
+ /**
+ * See if this template applies to a field.
+ *
+ * @param fieldname The field name to check.
+ * @return Whether or not this template should apply.
+ */
+ public boolean matchFieldName(String fieldname) {
+ return this.fieldname.equals(fieldname);
+ }
+
+ /**
+ * A builder class for creating {@code
+ * ExpectedFieldTypeAnnotation}s in a more convenient fashion. The
+ * constructor for {@code ExpectedFieldTypeAnnotation} takes a
+ * large number of parameters (by necessity). This class
+ * allows users to construct a {@code ExpectedFieldTypeAnnotation}s
+ * using only the ones they need.
+ */
+ public static class Builder extends ExpectedTypeAnnotation.Builder {
+ protected final String fieldname;
+
+ /**
+ * Create a {@code Builder} from the mandatory parameters.
+ *
+ * @param fieldname The expected field name.
+ * @param expectedName The expected annotation name.
+ * @param targetType The expected target type.
+ * @param visibility Whether this annotation should be runtime-visible.
+ * @param expectedCount The number of annotations that should be seen.
+ */
+ public Builder(String fieldname,
+ String expectedName,
+ TypeAnnotation.TargetType targetType,
+ boolean visibility,
+ int expectedCount) {
+ super(expectedName, targetType, visibility, expectedCount);
+ this.fieldname = fieldname;
+ }
+
+ /**
+ * Create an {@code ExpectedFieldTypeAnnotation} from all
+ * parameters that have been provided. The default values
+ * will be used for those that have not.
+ *
+ * @return The cretaed {@code ExpectedFieldTypeAnnotation}.
+ */
+ public ExpectedFieldTypeAnnotation build() {
+ return new ExpectedFieldTypeAnnotation(fieldname, expectedName,
+ visibility, expectedCount,
+ targetType, bound_index,
+ parameter_index, type_index,
+ exception_index, typePath);
+ }
+ }
+ }
+
+ private void matchClassTypeAnnotation(ClassFile classfile,
+ ExpectedTypeAnnotation expected)
+ throws ConstantPoolException {
+ for(Attribute attr : classfile.attributes) {
+ attr.accept(typeAnnoMatcher, expected);
+ }
+ }
+
+ private void matchMethodTypeAnnotation(ClassFile classfile,
+ ExpectedMethodTypeAnnotation expected)
+ throws ConstantPoolException {
+ for(Method meth : classfile.methods) {
+ if (expected.matchMethodName(meth.getName(classfile.constant_pool))) {
+ for(Attribute attr : meth.attributes) {
+ attr.accept(typeAnnoMatcher, expected);
+ }
+ }
+ }
+ }
+
+ private void matchFieldTypeAnnotation(ClassFile classfile,
+ ExpectedFieldTypeAnnotation expected)
+ throws ConstantPoolException {
+ for(Field field : classfile.fields) {
+ if (expected.matchFieldName(field.getName(classfile.constant_pool))) {
+ for(Attribute attr : field.attributes) {
+ attr.accept(typeAnnoMatcher, expected);
+ }
+ }
+ }
+ }
+
+ private void matchClassTypeAnnotations(ClassFile classfile,
+ ExpectedTypeAnnotation[] expected)
+ throws ConstantPoolException {
+ for(ExpectedTypeAnnotation one : expected) {
+ matchClassTypeAnnotation(classfile, one);
+ }
+ }
+
+ private void matchMethodTypeAnnotations(ClassFile classfile,
+ ExpectedMethodTypeAnnotation[] expected)
+ throws ConstantPoolException {
+ for(ExpectedMethodTypeAnnotation one : expected) {
+ matchMethodTypeAnnotation(classfile, one);
+ }
+ }
+
+ private void matchFieldTypeAnnotations(ClassFile classfile,
+ ExpectedFieldTypeAnnotation[] expected)
+ throws ConstantPoolException {
+ for(ExpectedFieldTypeAnnotation one : expected) {
+ matchFieldTypeAnnotation(classfile, one);
+ }
+ }
+
+ /**
+ * Run a template on a single {@code ClassFile}.
+ *
+ * @param classfile The {@code ClassFile} on which to run tests.
+ * @param expected The expected annotation template.
+ */
+ public void run(ClassFile classfile,
+ Expected... expected)
+ throws ConstantPoolException {
+ run(new ClassFile[] { classfile }, expected);
+ }
+
+ /**
+ * Run a template on multiple {@code ClassFile}s.
+ *
+ * @param classfile The {@code ClassFile}s on which to run tests.
+ * @param expected The expected annotation template.
+ */
+ public void run(ClassFile[] classfiles,
+ Expected... expected)
+ throws ConstantPoolException {
+ for(ClassFile classfile : classfiles) {
+ for(Expected one : expected) {
+ if (one.matchClassName(classfile.getName())) {
+ if (one.classAnnos != null)
+ matchClassTypeAnnotations(classfile, one.classAnnos);
+ if (one.methodAnnos != null)
+ matchMethodTypeAnnotations(classfile, one.methodAnnos);
+ if (one.fieldAnnos != null)
+ matchFieldTypeAnnotations(classfile, one.fieldAnnos);
+ }
+ }
+ }
+ int count = 0;
+ for (Expected one : expected) {
+ count += one.check();
+ }
+
+ if (count != 0) {
+ throw new RuntimeException(count + " errors occurred in test");
+ }
+ }
+
+ /**
+ * Get a {@code ClassFile} from its file name.
+ *
+ * @param name The class' file name.
+ * @return The {@code ClassFile}
+ */
+ public static ClassFile getClassFile(String name)
+ throws IOException, ConstantPoolException {
+ final URL url = ClassfileInspector.class.getResource(name);
+ final InputStream in = url.openStream();
+ try {
+ return ClassFile.read(in);
+ } finally {
+ in.close();
+ }
+ }
+
+ private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher =
+ new Attribute.Visitor<Void, ExpectedTypeAnnotation>() {
+
+ @Override
+ public Void visitBootstrapMethods(BootstrapMethods_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitDefault(DefaultAttribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitAnnotationDefault(AnnotationDefault_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitCode(Code_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitCompilationID(CompilationID_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitConstantValue(ConstantValue_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitDeprecated(Deprecated_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitEnclosingMethod(EnclosingMethod_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitExceptions(Exceptions_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitInnerClasses(InnerClasses_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitLineNumberTable(LineNumberTable_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitLocalVariableTable(LocalVariableTable_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitMethodParameters(MethodParameters_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitSignature(Signature_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitSourceFile(SourceFile_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitSourceID(SourceID_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitStackMap(StackMap_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitStackMapTable(StackMapTable_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitSynthetic(Synthetic_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ return null;
+ }
+
+ @Override
+ public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ if (expected.matchVisibility(true)) {
+ for(TypeAnnotation anno : attr.annotations) {
+ expected.matchAnnotation(anno);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
+ ExpectedTypeAnnotation expected) {
+ if (expected.matchVisibility(false)) {
+ for(TypeAnnotation anno : attr.annotations) {
+ expected.matchAnnotation(anno);
+ }
+ }
+
+ return null;
+ }
+ };
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,130 @@
+/*
+ * 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 SyntheticParameters
+ * @summary Test generation of annotations on inner class parameters.
+ * @build ClassfileInspector
+ * @run main SyntheticParameters
+ */
+
+import java.io.*;
+import java.lang.annotation.*;
+
+import com.sun.tools.classfile.*;
+
+public class SyntheticParameters extends ClassfileInspector {
+
+ private static final String Inner_class = "SyntheticParameters$Inner.class";
+ private static final String Foo_class = "SyntheticParameters$Foo.class";
+ private static final Expected Inner_expected =
+ new Expected("SyntheticParameters$Inner",
+ null,
+ new ExpectedMethodTypeAnnotation[] {
+ (ExpectedMethodTypeAnnotation)
+ // Assert there is no annotation on the
+ // this$0 parameter.
+ new ExpectedMethodTypeAnnotation.Builder(
+ "<init>",
+ "A",
+ TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+ false,
+ 0).setParameterIndex(0).build(),
+ (ExpectedMethodTypeAnnotation)
+ // Assert there is an annotation on the
+ // first parameter.
+ new ExpectedMethodTypeAnnotation.Builder(
+ "<init>",
+ "A",
+ TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+ false,
+ 1).setParameterIndex(1).build(),
+ (ExpectedMethodTypeAnnotation)
+ new ExpectedMethodTypeAnnotation.Builder(
+ "foo",
+ "A",
+ TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+ false,
+ 1).setParameterIndex(0).build(),
+ (ExpectedMethodTypeAnnotation)
+ new ExpectedMethodTypeAnnotation.Builder(
+ "foo",
+ "A",
+ TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+ false,
+ 0).setParameterIndex(1).build()
+ },
+ null);
+ private static final Expected Foo_expected =
+ new Expected("SyntheticParameters$Foo",
+ null,
+ new ExpectedMethodTypeAnnotation[] {
+ (ExpectedMethodTypeAnnotation)
+ // Assert there is no annotation on the
+ // $enum$name parameter.
+ new ExpectedMethodTypeAnnotation.Builder(
+ "<init>",
+ "A",
+ TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+ false,
+ 0).setParameterIndex(0).build(),
+ (ExpectedMethodTypeAnnotation)
+ // Assert there is no annotation on the
+ // $enum$ordinal parameter.
+ new ExpectedMethodTypeAnnotation.Builder(
+ "<init>",
+ "A",
+ TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+ false,
+ 0).setParameterIndex(1).build(),
+ (ExpectedMethodTypeAnnotation)
+ // Assert there is an annotation on the
+ // first parameter.
+ new ExpectedMethodTypeAnnotation.Builder(
+ "<init>",
+ "A",
+ TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
+ false,
+ 1).setParameterIndex(2).build()
+ },
+ null);
+
+ public static void main(String... args) throws Exception {
+ new SyntheticParameters().run(
+ new ClassFile[] { getClassFile(Inner_class), getClassFile(Foo_class) },
+ new Expected[] { Inner_expected, Foo_expected });
+ }
+
+ public class Inner {
+ public Inner(@A int a) {}
+ public void foo(@A int a, int b) {}
+ }
+
+ public static enum Foo {
+ ONE(null);
+ Foo(@A Object a) {}
+ }
+}
+
+@Target({ElementType.TYPE_USE})
+@interface A {}
--- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Mon Nov 17 12:32:27 2014 -0800
@@ -43,7 +43,7 @@
@TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+ @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClass() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -56,7 +56,7 @@
@TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TC", type = METHOD_RECEIVER)
@TADescription(annotation = "TD", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+ @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClass2() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -70,7 +70,7 @@
@TADescription(annotation = "TC", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0})
@TADescription(annotation = "TE", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
- @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+ @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("Outer$Middle$Inner")
public String innerClass3() {
return "class Outer { class Middle { class Inner {" +
@@ -89,7 +89,7 @@
@TADescription(annotation = "RTAs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+ @TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClassRepeatableAnnotation() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -102,7 +102,7 @@
@TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTCs", type = METHOD_RECEIVER)
@TADescription(annotation = "RTDs", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+ @TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClassRepeatableAnnotation2() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -116,7 +116,7 @@
@TADescription(annotation = "RTCs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "RTDs", type = METHOD_RECEIVER, genericLocation = {1, 0})
@TADescription(annotation = "RTEs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
- @TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
+ @TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("Outer$Middle$Inner")
public String innerClassRepatableAnnotation3() {
return "class Outer { class Middle { class Inner {" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,537 @@
+/*
+ * 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 8042931
+ * @summary Checking EnclosingMethod attribute of anonymous/local class.
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build EnclosingMethodTest TestBase TestResult InMemoryFileManager ToolBox
+ * @run main EnclosingMethodTest
+ */
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.EnclosingMethod_attribute;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * The test checks the enclosing method attribute of anonymous/local classes.
+ * The top-level class contains the anonymous and local classes to be tested. The test examines
+ * each inner class and determine whether the class should have the EnclosingMethod attribute or not.
+ * Golden information about enclosing methods are held in annotation {@code ExpectedEnclosingMethod}.
+ *
+ * The test assumes that a class must have the EnclosingMethod attribute if the class is annotated or
+ * if its parent class is annotated in case of anonymous class. In addition, classes
+ * named {@code VariableInitializer} are introduced to test variable initializer cases. These classes
+ * must not have the enclosing method attribute, but its anonymous derived class must.
+ * After classification of classes, the test checks whether classes contain the correct enclosing
+ * method attribute in case of anonymous/local class, or checks whether classes do not contain
+ * the EnclosingMethod attribute, otherwise.
+ *
+ * Test cases:
+ * top-level class as enclosing class:
+ * 1. anonymous and local classes in static initializer;
+ * 2. anonymous and local classes in instance initializer;
+ * 3. anonymous and local classes in lambda;
+ * 4. anonymous and local classes in constructor;
+ * 5. anonymous and local classes in method;
+ * 6. static and instance variable initializer.
+ *
+ * inner class as enclosing class:
+ * 1. anonymous and local classes in static initializer;
+ * 2. anonymous and local classes in instance initializer;
+ * 3. anonymous and local classes in lambda;
+ * 4. anonymous and local classes in constructor;
+ * 5. anonymous and local classes in method;
+ * 6. static and instance variable initializer.
+ *
+ * enum as enclosing class:
+ * 1. anonymous and local classes in static initializer;
+ * 2. anonymous and local classes in instance initializer;
+ * 3. anonymous and local classes in lambda;
+ * 4. anonymous and local classes in constructor;
+ * 5. anonymous and local classes in method;
+ * 6. static and instance variable initializer.
+ *
+ * interface as enclosing class:
+ * 1. anonymous and local classes in lambda;
+ * 2. anonymous and local classes in static method;
+ * 3. anonymous and local classes in default method;
+ * 4. static variable initializer.
+ *
+ * annotation as enclosing class:
+ * 1. anonymous and local classes in lambda;
+ * 2. static variable initializer.
+ */
+public class EnclosingMethodTest extends TestResult {
+
+ private final Map<Class<?>, ExpectedEnclosingMethod> class2EnclosingMethod = new HashMap<>();
+ private final Set<Class<?>> noEnclosingMethod = new HashSet<>();
+
+ public EnclosingMethodTest() throws ClassNotFoundException {
+ Class<EnclosingMethodTest> outerClass = EnclosingMethodTest.class;
+ String outerClassName = outerClass.getSimpleName();
+ File testClasses = getClassDir();
+ FilenameFilter filter = (dir, name) -> name.matches(outerClassName + ".*\\.class");
+
+ for (File file : testClasses.listFiles(filter)) {
+ Class<?> clazz = Class.forName(file.getName().replace(".class", ""));
+ if (clazz.isAnonymousClass()) {
+ // anonymous class cannot be annotated, information is in its parent class.
+ ExpectedEnclosingMethod declaredAnnotation =
+ clazz.getSuperclass().getDeclaredAnnotation(ExpectedEnclosingMethod.class);
+ class2EnclosingMethod.put(clazz, declaredAnnotation);
+ } else {
+ ExpectedEnclosingMethod enclosingMethod = clazz.getDeclaredAnnotation(ExpectedEnclosingMethod.class);
+ // if class is annotated and it does not contain information for variable initializer cases,
+ // then it must have the enclosing method attribute.
+ if (enclosingMethod != null && !clazz.getSimpleName().contains("VariableInitializer")) {
+ class2EnclosingMethod.put(clazz, enclosingMethod);
+ } else {
+ noEnclosingMethod.add(clazz);
+ }
+ }
+ }
+ }
+
+ public void test() throws TestFailedException {
+ try {
+ testEnclosingMethodAttribute();
+ testLackOfEnclosingMethodAttribute();
+ } finally {
+ checkStatus();
+ }
+ }
+
+ private void testLackOfEnclosingMethodAttribute() {
+ for (Class<?> clazz : noEnclosingMethod) {
+ try {
+ addTestCase("Class should not have EnclosingMethod attribute : " + clazz);
+ ClassFile classFile = readClassFile(clazz);
+ checkEquals(countEnclosingMethodAttributes(classFile),
+ 0l, "number of the EnclosingMethod attribute in the class is zero : "
+ + classFile.getName());
+ } catch (Exception e) {
+ addFailure(e);
+ }
+ }
+ }
+
+ private void testEnclosingMethodAttribute() {
+ class2EnclosingMethod.forEach((clazz, enclosingMethod) -> {
+ try {
+ String info = enclosingMethod.info() + " "
+ + (clazz.isAnonymousClass() ? "anonymous" : "local");
+ addTestCase(info);
+ printf("Testing test case : %s\n", info);
+ ClassFile classFile = readClassFile(clazz);
+ String className = clazz.getName();
+ checkEquals(countEnclosingMethodAttributes(classFile), 1l,
+ "number of the EnclosingMethod attribute in the class is one : "
+ + clazz);
+ EnclosingMethod_attribute attr = (EnclosingMethod_attribute)
+ classFile.getAttribute(Attribute.EnclosingMethod);
+
+ if (!checkNotNull(attr, "the EnclosingMethod attribute is not null : " + className)) {
+ // stop checking, attr is null. test case failed
+ return;
+ }
+ checkEquals(classFile.constant_pool.getUTF8Value(attr.attribute_name_index),
+ "EnclosingMethod",
+ "attribute_name_index of EnclosingMethod attribute in the class : " + className);
+ checkEquals(attr.attribute_length, 4,
+ "attribute_length of EnclosingMethod attribute in the class : " + className);
+ String expectedClassName = enclosingMethod.enclosingClazz().getName();
+ checkEquals(classFile.constant_pool.getClassInfo(attr.class_index).getName(),
+ expectedClassName, String.format(
+ "enclosing class of EnclosingMethod attribute in the class %s is %s",
+ className, expectedClassName));
+
+ String expectedMethodName = enclosingMethod.enclosingMethod();
+ if (expectedMethodName.isEmpty()) {
+ // class does not have an enclosing method
+ checkEquals(attr.method_index, 0, String.format(
+ "enclosing method of EnclosingMethod attribute in the class %s is null", className));
+ } else {
+ String methodName = classFile.constant_pool.getNameAndTypeInfo(attr.method_index).getName();
+ checkTrue(methodName.startsWith(expectedMethodName), String.format(
+ "enclosing method of EnclosingMethod attribute in the class %s" +
+ " is method name %s" +
+ ", actual method name is %s",
+ className, expectedMethodName, methodName));
+ }
+ } catch (Exception e) {
+ addFailure(e);
+ }
+ });
+ }
+
+ private long countEnclosingMethodAttributes(ClassFile classFile) {
+ return Stream.of(classFile.attributes.attrs)
+ .filter(x -> x instanceof EnclosingMethod_attribute)
+ .count();
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface ExpectedEnclosingMethod {
+ String info();
+ Class<?> enclosingClazz();
+ String enclosingMethod() default "";
+ }
+
+ public static void main(String[] args) throws ClassNotFoundException, TestFailedException {
+ new EnclosingMethodTest().test();
+ }
+
+ // Test cases: enclosing class is a top-level class
+ static {
+ // anonymous and local classes in static initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingStaticInitialization in EnclosingMethodTest",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingStaticInitialization {
+ }
+ new EnclosingStaticInitialization() {
+ };
+ }
+
+ {
+ // anonymous and local classes in instance initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingInitialization in EnclosingMethodTest",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingInitialization {
+ }
+ new EnclosingInitialization() {
+ };
+ }
+
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in EnclosingMethodTest",
+ enclosingMethod = "lambda",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ EnclosingMethodTest(int i) {
+ // anonymous and local classes in constructor
+ @ExpectedEnclosingMethod(
+ info = "EnclosingConstructor in EnclosingMethodTest",
+ enclosingMethod = "<init>",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingConstructor {
+ }
+ new EnclosingConstructor() {
+ };
+ }
+
+ void method() {
+ // anonymous and local classes in method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in EnclosingMethodTest",
+ enclosingMethod = "method",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in EnclosingMethodTest",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ private static final VariableInitializer cvi = new VariableInitializer() {
+ };
+
+ // instance variable initializer
+ private final VariableInitializer ivi = new VariableInitializer() {
+ };
+
+ // Test cases: enclosing class is an inner class
+ public static class notEnclosing01 {
+ static {
+ // anonymous and local classes in static initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingStaticInitialization in notEnclosing01",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingStaticInitialization {
+ }
+ new EnclosingStaticInitialization() {
+ };
+ }
+
+ {
+ // anonymous and local classes in instance initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingInitialization in notEnclosing01",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingInitialization {
+ }
+ new EnclosingInitialization() {
+ };
+ }
+
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing01",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ notEnclosing01() {
+ // anonymous and local classes in constructor
+ @ExpectedEnclosingMethod(
+ info = "EnclosingConstructor in notEnclosing01",
+ enclosingMethod = "<init>",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingConstructor {
+ }
+ new EnclosingConstructor() {
+ };
+ }
+
+ void method() {
+ // anonymous and local classes in method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing01",
+ enclosingMethod = "method",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing01",
+ enclosingClazz = notEnclosing01.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ private static final VariableInitializer cvi = new VariableInitializer() {
+ };
+
+ // instance variable initializer
+ private final VariableInitializer ivi = new VariableInitializer() {
+ };
+ }
+
+ // Test cases: enclosing class is an interface
+ public interface notEnclosing02 {
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing02",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing02.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ static void staticMethod() {
+ // anonymous and local classes in static method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing02",
+ enclosingMethod = "staticMethod",
+ enclosingClazz = notEnclosing02.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ default void defaultMethod() {
+ // anonymous and local classes in default method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing02",
+ enclosingMethod = "defaultMethod",
+ enclosingClazz = notEnclosing02.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing02",
+ enclosingClazz = notEnclosing02.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ VariableInitializer cvi = new VariableInitializer() {
+ };
+ }
+
+ // Test cases: enclosing class is an enum
+ public enum notEnclosing03 {;
+
+ static {
+ // anonymous and local classes in static initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingStaticInitialization in notEnclosing03",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingStaticInitialization {
+ }
+ new EnclosingStaticInitialization() {
+ };
+ }
+
+ {
+ // anonymous and local classes in instance initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingInitialization in notEnclosing03",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingInitialization {
+ }
+ new EnclosingInitialization() {
+ };
+ }
+
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing03",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ notEnclosing03() {
+ // anonymous and local classes in constructor
+ @ExpectedEnclosingMethod(
+ info = "EnclosingConstructor in notEnclosing03",
+ enclosingMethod = "<init>",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingConstructor {
+ }
+ new EnclosingConstructor() {
+ };
+ }
+
+ void method() {
+ // anonymous and local classes in method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing03",
+ enclosingMethod = "method",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing03",
+ enclosingClazz = notEnclosing03.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ private static final VariableInitializer cvi = new VariableInitializer() {
+ };
+
+ // instance variable initializer
+ private final VariableInitializer ivi = new VariableInitializer() {
+ };
+ }
+
+ // Test cases: enclosing class is an annotation
+ public @interface notEnclosing04 {
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing04",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing04.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing04",
+ enclosingClazz = notEnclosing04.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ VariableInitializer cvi = new VariableInitializer() {
+ };
+ }
+}
--- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -74,13 +74,13 @@
addTestCase(src);
printf("Testing test case: \n%s\n", src);
try {
- ClassFile cf = ClassFile.read(compile(
+ ClassFile cf = readClassFile(compile(
new String[]{"package-info.java", package_info},
new String[]{"notDeprecated.java", src})
- .getClasses().get(CLASS_NAME).openInputStream());
+ .getClasses().get(CLASS_NAME));
Deprecated_attribute attr =
(Deprecated_attribute) cf.getAttribute(Attribute.Deprecated);
- assertNull(attr, "Class can not have deprecated attribute : " + CLASS_NAME);
+ checkNull(attr, "Class can not have deprecated attribute : " + CLASS_NAME);
} catch (Exception e) {
addFailure(e);
}
--- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -240,7 +240,7 @@
? "deprecated"
: "notDeprecated";
echo("Testing outer class : " + outerClassName);
- ClassFile cf = ClassFile.read(classes.get(outerClassName).openInputStream());
+ ClassFile cf = readClassFile(classes.get(outerClassName));
Deprecated_attribute attr = (Deprecated_attribute)
cf.getAttribute(Attribute.Deprecated);
testAttribute(outerClassName, attr, cf);
@@ -260,7 +260,7 @@
String innerClassName = cf.constant_pool.
getClassInfo(innerClass.inner_class_info_index).getName();
echo("Testing inner class : " + innerClassName);
- ClassFile innerCf = ClassFile.read(classes.get(innerClassName).openInputStream());
+ ClassFile innerCf = readClassFile(classes.get(innerClassName));
Deprecated_attribute attr = (Deprecated_attribute)
innerCf.getAttribute(Attribute.Deprecated);
String innerClassSimpleName = innerClass.getInnerName(cf.constant_pool);
@@ -298,17 +298,18 @@
if (name.contains("deprecated")) {
testDeprecatedAttribute(name, attr, cf);
} else {
- assertNull(attr, name + " should not have deprecated attribute");
+ checkNull(attr, name + " should not have deprecated attribute");
}
}
private void testDeprecatedAttribute(String name, Deprecated_attribute attr, ClassFile cf)
throws ConstantPoolException {
- assertNotNull(attr, name + " must have deprecated attribute");
- assertEquals(0, attr.attribute_length,
- "attribute_length should equal to 0");
- assertEquals("Deprecated",
- cf.constant_pool.getUTF8Value(attr.attribute_name_index),
- name + " attribute_name_index");
+ if (checkNotNull(attr, name + " must have deprecated attribute")) {
+ checkEquals(0, attr.attribute_length,
+ "attribute_length should equal to 0");
+ checkEquals("Deprecated",
+ cf.constant_pool.getUTF8Value(attr.attribute_name_index),
+ name + " attribute_name_index");
+ }
}
}
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -96,21 +96,21 @@
ClassFile cf = readClassFile(currentClassName);
InnerClasses_attribute attr = (InnerClasses_attribute)
cf.getAttribute(Attribute.InnerClasses);
- assertNotNull(attr, "Class should not contain "
+ checkNotNull(attr, "Class should not contain "
+ "inner classes attribute : " + currentClassName);
- assertTrue(innerClasses.containsKey(currentClassName),
+ checkTrue(innerClasses.containsKey(currentClassName),
"map contains class name : " + currentClassName);
Set<String> setClasses = innerClasses.get(currentClassName);
if (setClasses == null) {
continue;
}
- assertEquals(attr.number_of_classes,
+ checkEquals(attr.number_of_classes,
setClasses.size(),
"Check number of inner classes : " + setClasses);
for (Info info : attr.classes) {
String innerClassName = info
.getInnerClassInfo(cf.constant_pool).getBaseName();
- assertTrue(setClasses.contains(innerClassName),
+ checkTrue(setClasses.contains(innerClassName),
currentClassName + " contains inner class : "
+ innerClassName);
if (visitedClasses.add(innerClassName)) {
@@ -124,10 +124,10 @@
Set<String> a_b = removeAll(visitedClasses, allClasses);
Set<String> b_a = removeAll(allClasses, visitedClasses);
- assertEquals(visitedClasses, allClasses,
+ checkEquals(visitedClasses, allClasses,
"All classes are found\n"
- + "visited - all classes : " + a_b
- + "\nall classes - visited : " + b_a);
+ + "visited - all classes : " + a_b
+ + "\nall classes - visited : " + b_a);
} catch (Exception e) {
addFailure(e);
} finally {
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -78,16 +78,16 @@
continue;
}
foundClasses.add(innerName);
- assertEquals(info.outer_class_info_index, 0,
+ checkEquals(info.outer_class_info_index, 0,
"outer_class_info_index of " + innerName);
if (innerName.matches("\\$\\d+")) {
- assertEquals(info.inner_name_index, 0,
+ checkEquals(info.inner_name_index, 0,
"inner_name_index of anonymous class");
}
}
Set<String> expectedClasses = getInnerClasses();
expectedClasses.remove("InnerClassesIndexTest$Inner");
- assertEquals(foundClasses, expectedClasses, "All classes are found");
+ checkEquals(foundClasses, expectedClasses, "All classes are found");
} catch (Exception e) {
addFailure(e);
} finally {
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Mon Nov 17 12:32:27 2014 -0800
@@ -202,44 +202,44 @@
++count;
}
}
- assertEquals(1, count, "Number of inner classes attribute");
- if (innerClasses == null) {
+ checkEquals(1, count, "Number of inner classes attribute");
+ if (!checkNotNull(innerClasses, "InnerClasses attribute should not be null")) {
return;
}
- assertEquals(cf.constant_pool.
+ checkEquals(cf.constant_pool.
getUTF8Info(innerClasses.attribute_name_index).value, "InnerClasses",
"innerClasses.attribute_name_index");
// Inner Classes attribute consists of length (2 bytes)
// and 8 bytes for each inner class's entry.
- assertEquals(innerClasses.attribute_length,
+ checkEquals(innerClasses.attribute_length,
2 + 8 * class2Flags.size(), "innerClasses.attribute_length");
- assertEquals(innerClasses.number_of_classes,
+ checkEquals(innerClasses.number_of_classes,
class2Flags.size(), "innerClasses.number_of_classes");
Set<String> visitedClasses = new HashSet<>();
for (Info e : innerClasses.classes) {
String baseName = cf.constant_pool.getClassInfo(
e.inner_class_info_index).getBaseName();
if (cf.major_version >= 51 && e.inner_name_index == 0) {
- assertEquals(e.outer_class_info_index, 0,
- "outer_class_info_index "
- + "in case of inner_name_index is zero : "
- + baseName);
+ checkEquals(e.outer_class_info_index, 0,
+ "outer_class_info_index "
+ + "in case of inner_name_index is zero : "
+ + baseName);
}
String className = baseName.replaceFirst(".*\\$", "");
- assertTrue(class2Flags.containsKey(className),
+ checkTrue(class2Flags.containsKey(className),
className);
- assertTrue(visitedClasses.add(className),
+ checkTrue(visitedClasses.add(className),
"there are no duplicates in attribute : " + className);
- assertEquals(e.inner_class_access_flags.getInnerClassFlags(),
+ checkEquals(e.inner_class_access_flags.getInnerClassFlags(),
class2Flags.get(className),
"inner_class_access_flags " + className);
if (!Arrays.asList(skipClasses).contains(className)) {
- assertEquals(
- cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(),
- classToTest + "$" + className,
- "inner_class_info_index of " + className);
+ checkEquals(
+ cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(),
+ classToTest + "$" + className,
+ "inner_class_info_index of " + className);
if (e.outer_class_info_index > 0) {
- assertEquals(
+ checkEquals(
cf.constant_pool.getClassInfo(e.outer_class_info_index).getName(),
classToTest,
"outer_class_info_index of " + className);
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Mon Nov 17 12:32:27 2014 -0800
@@ -25,10 +25,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -78,8 +75,8 @@
/**
* Compiles sources in memory.
*
- * @param sources to compile.
- * @return memory file manager which contains class files and class loader.
+ * @param sources to compile
+ * @return in-memory file manager which contains class files and class loader
*/
public InMemoryFileManager compile(String... sources)
throws IOException, CompilationException {
@@ -91,7 +88,7 @@
*
* @param options compiler options.
* @param sources sources to compile.
- * @return map where key is className, value is corresponding ClassFile.
+ * @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String... sources)
throws IOException, CompilationException {
@@ -102,7 +99,7 @@
* Compiles sources in memory.
*
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
- * @return map where key is className, value is corresponding ClassFile.
+ * @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(String[]... sources) throws IOException,
CompilationException {
@@ -114,7 +111,7 @@
*
* @param options compiler options
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
- * @return map where key is className, value is corresponding ClassFile.
+ * @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String[]... sources)
throws IOException, CompilationException {
@@ -142,7 +139,9 @@
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException {
- return readClassFile(fileObject.openInputStream());
+ try (InputStream is = fileObject.openInputStream()) {
+ return readClassFile(is);
+ }
}
/**
@@ -205,6 +204,12 @@
assertEquals(actual, false, message);
}
+ public void assertContains(Set<?> found, Set<?> expected, String message) {
+ Set<?> copy = new HashSet<>(expected);
+ copy.removeAll(found);
+ assertTrue(found.containsAll(expected), message + " : " + copy);
+ }
+
public File getSourceDir() {
return new File(System.getProperty("test.src", "."));
}
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Mon Nov 17 12:32:27 2014 -0800
@@ -24,10 +24,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
-import java.util.stream.Stream;
-
-import static java.lang.String.format;
-import static java.util.stream.Collectors.joining;
+import java.util.stream.Collectors;
/**
* This class accumulates test results. Test results can be checked with method @{code checkStatus}.
@@ -52,39 +49,46 @@
private String errorMessage() {
return testCases.stream().filter(Info::isFailed)
- .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
- .collect(joining("\n"));
+ .map(tc -> String.format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
+ .collect(Collectors.joining("\n"));
}
- @Override
- public void assertEquals(Object actual, Object expected, String message) {
- getLastTestCase().assertEquals(actual, expected, message);
+ public boolean checkEquals(Object actual, Object expected, String message) {
+ echo("Testing : " + message);
+ if (!Objects.equals(actual, expected)) {
+ getLastTestCase().addAssert(new AssertionFailedException(
+ String.format("%s%nGot: %s, Expected: %s", message, actual, expected)));
+ return false;
+ }
+ return true;
}
- @Override
- public void assertNull(Object actual, String message) {
- getLastTestCase().assertEquals(actual, null, message);
+ public boolean checkNull(Object actual, String message) {
+ return checkEquals(actual, null, message);
}
- @Override
- public void assertNotNull(Object actual, String message) {
- getLastTestCase().assertNotNull(actual, message);
- }
-
- @Override
- public void assertFalse(boolean actual, String message) {
- getLastTestCase().assertEquals(actual, false, message);
+ public boolean checkNotNull(Object actual, String message) {
+ echo("Testing : " + message);
+ if (Objects.isNull(actual)) {
+ getLastTestCase().addAssert(new AssertionFailedException(
+ message + " : Expected not null value"));
+ return false;
+ }
+ return true;
}
- @Override
- public void assertTrue(boolean actual, String message) {
- getLastTestCase().assertEquals(actual, true, message);
+ public boolean checkFalse(boolean actual, String message) {
+ return checkEquals(actual, false, message);
}
- public void assertContains(Set<?> found, Set<?> expected, String message) {
+ public boolean checkTrue(boolean actual, String message) {
+ return checkEquals(actual, true, message);
+ }
+
+ public boolean checkContains(Set<?> found, Set<?> expected, String message) {
Set<?> copy = new HashSet<>(expected);
copy.removeAll(found);
- assertTrue(found.containsAll(expected), message + " : " + copy);
+ return checkTrue(found.containsAll(expected), message + " : " + copy);
}
public void addFailure(Throwable th) {
@@ -99,10 +103,10 @@
}
/**
- * Throws {@code TestFailedException} if one of the asserts are failed
+ * Throws {@code TestFailedException} if one of the checks are failed
* or an exception occurs. Prints error message of failed test cases.
*
- * @throws TestFailedException if one of the asserts are failed
+ * @throws TestFailedException if one of the checks are failed
* or an exception occurs
*/
public void checkStatus() throws TestFailedException {
@@ -115,7 +119,7 @@
private class Info {
private final String info;
- private final List<String> asserts;
+ private final List<AssertionFailedException> asserts;
private final List<Throwable> errors;
private Info(String info) {
@@ -137,45 +141,20 @@
printf("[ERROR] : %s\n", getStackTrace(th));
}
- public void addFailure(String message) {
- String stackTrace = Stream.of(Thread.currentThread().getStackTrace())
- // just to get stack trace without TestResult and Thread
- .filter(e -> !"TestResult.java".equals(e.getFileName()) &&
- !"java.lang.Thread".equals(e.getClassName()))
- .map(e -> "\tat " + e)
- .collect(joining("\n"));
- asserts.add(format("%s\n%s", message, stackTrace));
- printf("[ASSERT] : %s\n", message);
- }
-
- public void assertEquals(Object actual, Object expected, String message) {
- echo("Testing : " + message);
- if (!Objects.equals(actual, expected)) {
- addFailure(message + ": Got: " + actual + ", " + "Expected: " + expected);
- }
- }
-
- public void assertNotNull(Object actual, String message) {
- echo("Testing : " + message);
- if (actual == null) {
- addFailure(message + " : Expected not null value");
- }
+ public void addAssert(AssertionFailedException e) {
+ asserts.add(e);
+ printf("[ASSERT] : %s\n", getStackTrace(e));
}
public String getMessage() {
- return (asserts.size() > 0 ? getAssertMessage() + "\n" : "") + getErrorMessage();
+ return (asserts.size() > 0 ? getErrorMessage("[ASSERT]", asserts) + "\n" : "")
+ + getErrorMessage("[ERROR]", errors);
}
- public String getAssertMessage() {
- return asserts.stream()
- .map(failure -> "[ASSERT] : " + failure)
- .collect(joining("\n"));
- }
-
- public String getErrorMessage() {
- return errors.stream()
- .map(throwable -> format("[ERROR] : %s", getStackTrace(throwable)))
- .collect(joining("\n"));
+ public String getErrorMessage(String header, List<? extends Throwable> list) {
+ return list.stream()
+ .map(throwable -> String.format("%s : %s", header, getStackTrace(throwable)))
+ .collect(Collectors.joining("\n"));
}
public String getStackTrace(Throwable throwable) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/conditional/8064464/T8064464.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,23 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8064464
+ * @summary regression with type inference of conditional expression
+ * @compile/fail/ref=T8064464.out -XDrawDiagnostics T8064464.java
+ */
+
+import java.util.List;
+
+class T8064464 {
+
+ String f(Object o) { return null; }
+ Integer f(int i) { return null; }
+
+ <X extends Integer> X id() { return null; }
+
+ void m(List<Integer> lx) {
+ Integer i1 = f(!lx.isEmpty() ? 0 : lx.get(0)); //ok --> f(int)
+ Integer i2 = f(!lx.isEmpty() ? lx.get(0) : 0); //ok --> f(int)
+ f(!lx.isEmpty() ? id() : 0); // ambiguous
+ f(!lx.isEmpty() ? 0 : id()); // ambiguous
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/conditional/8064464/T8064464.out Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,3 @@
+T8064464.java:20:5: compiler.err.ref.ambiguous: f, kindname.method, f(java.lang.Object), T8064464, kindname.method, f(int), T8064464
+T8064464.java:21:5: compiler.err.ref.ambiguous: f, kindname.method, f(java.lang.Object), T8064464, kindname.method, f(int), T8064464
+2 errors
--- a/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/diags/examples/NeitherConditionalSubtype.java Mon Nov 17 12:32:27 2014 -0800
@@ -24,9 +24,9 @@
// key: compiler.err.neither.conditional.subtype
class NeitherConditionalSubtype {
- public int test(Object o) {
+ public int test(boolean cond, Object o) {
// Should fail to compile since Object.wait() has a void return type.
- System.out.println(o instanceof String ? o.hashCode() : o.wait());
+ (o instanceof String ? o.hashCode() : o.wait()).toString();
return 0;
}
}
--- a/langtools/test/tools/javac/processing/model/type/BoundsTest.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/javac/processing/model/type/BoundsTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -25,7 +25,6 @@
* @test
* @bug 6499673
* @library /tools/javac/lib
- * @ignore 8062245 Test executes incorrect class
* @build JavacTestingAbstractProcessor BoundsTest
* @run main BoundsTest
* @summary Assertion check for TypeVariable.getUpperBound() fails
@@ -86,8 +85,8 @@
};
private static final String[] NoBounds_supers = {};
- private HashSet<CharSequence> expected_bounds;
- private HashSet<CharSequence> expected_supers;
+ private HashSet<String> expected_bounds;
+ private HashSet<String> expected_supers;
private static final File classesdir = new File("intersectionproperties");
private static final JavaCompiler comp =
@@ -99,8 +98,8 @@
final String[] Test_bounds, final String[] Test_supers)
throws IOException {
System.err.println("Testing " + Test_name);
- expected_bounds = new HashSet<CharSequence>(Arrays.asList(Test_bounds));
- expected_supers = new HashSet<CharSequence>(Arrays.asList(Test_supers));
+ expected_bounds = new HashSet<>(Arrays.asList(Test_bounds));
+ expected_supers = new HashSet<>(Arrays.asList(Test_supers));
final Iterable<? extends JavaFileObject> files =
fm.getJavaFileObjectsFromFiles(Collections.singleton(writeFile(classesdir, Test_name, Test_contents)));
final JavacTask ct =
@@ -130,7 +129,7 @@
}
public static void main(String... args) throws IOException {
- new IntersectionPropertiesTest().run();
+ new BoundsTest().run();
}
private static File writeFile(File dir, String path, String body)
@@ -166,18 +165,17 @@
final List<? extends TypeMirror> bounds = typeParameterElement.getBounds();
final List<? extends TypeMirror> supers = processingEnv.getTypeUtils().directSupertypes(upperBound);
- final HashSet<CharSequence> actual_bounds = new HashSet<CharSequence>();
- final HashSet<CharSequence> actual_supers = new HashSet<CharSequence>();
+ final HashSet<String> actual_bounds = new HashSet<>();
+ final HashSet<String> actual_supers = new HashSet<>();
for(TypeMirror ty : bounds) {
- actual_bounds.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName());
+ actual_bounds.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName().toString());
}
for(TypeMirror ty : supers) {
- actual_supers.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName());
+ actual_supers.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName().toString());
}
-
if (!expected_bounds.equals(actual_bounds)) {
System.err.println("Mismatched expected and actual bounds.");
System.err.println("Expected:");
@@ -190,7 +188,7 @@
}
if (!expected_supers.equals(actual_supers)) {
- System.err.println("Mismatched expected and actual bounds.");
+ System.err.println("Mismatched expected and actual supers.");
System.err.println("Expected:");
for(CharSequence tm : expected_supers)
System.err.println(" " + tm);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/scope/DupUnsharedTest.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,217 @@
+/*
+ * 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
+ * @summary WriteableScope.dupUnshared not working properly for shared Scopes.
+ */
+
+import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Scope.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.file.JavacFileManager;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Objects;
+import java.util.Set;
+
+public class DupUnsharedTest {
+ public static void main(String... args) throws Exception {
+ new DupUnsharedTest().run();
+ }
+
+ Context context;
+ Names names;
+ Symtab symtab;
+ Name a;
+ Name b;
+ int errors;
+
+ public DupUnsharedTest() {
+ context = new Context();
+ JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
+ names = Names.instance(context);
+ symtab = Symtab.instance(context);
+ a = names.fromString("a");
+ b = names.fromString("b");
+ }
+
+ void run() throws Exception {
+ runScopeContentTest();
+ runClashTest();
+
+ if (errors > 0)
+ throw new AssertionError("Errors detected (" + errors + ").");
+ }
+
+ void runScopeContentTest() throws Exception {
+ Set<Symbol> expected = Collections.newSetFromMap(new IdentityHashMap<>());
+ Set<Symbol> notExpected = Collections.newSetFromMap(new IdentityHashMap<>());
+ WriteableScope s1 = WriteableScope.create(symtab.rootPackage);
+ ClassSymbol acceptSym = symtab.arrayClass;
+ s1.enter(acceptSym);
+ expected.add(acceptSym);
+ WriteableScope s2 = s1.dup();
+ fillScope(s2, notExpected, a);
+ WriteableScope s3 = s2.dup();
+ fillScope(s3, notExpected, b);
+ WriteableScope s4 = s1.dupUnshared();
+ assertEquals(toSet(s4.getSymbols()), expected);
+ assertEquals(toSet(s4.getSymbolsByName(a)), Collections.emptySet());
+ assertEquals(toSet(s4.getSymbolsByName(b)), Collections.emptySet());
+ assertEquals(toSet(s4.getSymbolsByName(acceptSym.name)), expected);
+ for (Symbol sym : notExpected) {
+ try {
+ s4.remove(sym);
+ } catch (Exception ex) {
+ System.err.println("s4.remove(" + sym + "); crashes with exception:");
+ ex.printStackTrace();
+ errors++;
+ }
+ }
+ }
+
+ void fillScope(WriteableScope scope, Set<Symbol> notExpected, Name name) {
+ VarSymbol var1 = new VarSymbol(0, name, Type.noType, symtab.arrayClass);
+ VarSymbol var2 = new VarSymbol(0, name, Type.noType, symtab.autoCloseableClose.owner);
+ scope.enter(var1);
+ scope.enter(var2);
+ scope.remove(var1);
+ notExpected.add(var1);
+ notExpected.add(var2);
+ }
+
+ Set<Symbol> toSet(Iterable<Symbol> it) {
+ Set<Symbol> result = Collections.newSetFromMap(new IdentityHashMap<>());
+
+ for (Symbol sym : it) {
+ result.add(sym);
+ }
+
+ return result;
+ }
+
+ void assertEquals(Set<Symbol> set1, Set<Symbol> set2) {
+ if (!Objects.equals(set1, set2)) {
+ System.err.println("Sets are not equals: s1=" + set1 + "; s2=" + set2);
+ errors++;
+ }
+ }
+
+ /**
+ * This tests tests the following situation.
+ * - consider empty Scope S1
+ * - a Symbol with name 'A' is added into S1
+ * - S1 is dupped into S2
+ * - a Symbol with name 'B', clashing with 'A', is added into S2
+ * - so the table now looks like: [..., A, ..., B, ...]
+ * - S2 is doubled. As a consequence, the table is re-hashed, and looks like:
+ * [..., B, ..., A, ...] (note that re-hashing goes from the end, hence the original order).
+ * - B has been chosen so that it clashes in the doubled scope as well. So when looking up 'A',
+ * B is found (and rejected) first, and only then the A's bucket is tested.
+ * - S2 is dupUshared - the resulting table needs to look like: [..., /sentinel/, ..., A, ...], not
+ * [..., null, ..., A, ...], as in the latter case lookups would see 'null' while looking for
+ * 'A' and would stop the search prematurely.
+ */
+ void runClashTest() throws Exception {
+ WriteableScope emptyScope = WriteableScope.create(symtab.unnamedPackage);
+ Field tableField = emptyScope.getClass().getDeclaredField("table");
+ tableField.setAccessible(true);
+ Method dble = emptyScope.getClass().getDeclaredMethod("dble");
+ dble.setAccessible(true);
+ Method getIndex = emptyScope.getClass().getDeclaredMethod("getIndex", Name.class);
+ getIndex.setAccessible(true);
+
+ int tries = 0;
+
+ //find a name that will be in the first bucket in table (so that a conflicting name
+ //will be in placed in a bucket after this one).
+ Name first = names.fromString("a");
+ while ((Integer) getIndex.invoke(emptyScope, first) != 0) {
+ if (tries++ > MAX_TRIES) {
+ System.err.println("could not find a name that would be placed in the first bucket");
+ errors++;
+ return ;
+ }
+ first = names.fromString("a" + first.toString());
+ }
+
+ System.out.println("first name: " + first);
+
+ //now, find another name, that will clash with the first one both in the empty and a doubled scope:
+ Scope doubledEmptyScope = WriteableScope.create(symtab.unnamedPackage);
+ dble.invoke(doubledEmptyScope);
+ Integer firstNameTestScopeIndex = (Integer) getIndex.invoke(emptyScope, first);
+ Integer firstNameDoubleScopeIndex = (Integer) getIndex.invoke(doubledEmptyScope, first);
+ Name other = names.fromString("b");
+ while (!Objects.equals(firstNameTestScopeIndex, getIndex.invoke(emptyScope, other)) ||
+ !Objects.equals(firstNameDoubleScopeIndex, getIndex.invoke(doubledEmptyScope, other))) {
+ if (tries++ > MAX_TRIES) {
+ System.err.println("could not find a name that would properly clash with the first chosen name");
+ errors++;
+ return ;
+ }
+ other = names.fromString("b" + other);
+ }
+
+ System.out.println("other name: " + other);
+
+ Symbol firstSymbol = new VarSymbol(0, first, Type.noType, null);
+ Symbol otherSymbol = new VarSymbol(0, other, Type.noType, null);
+
+ //test the situation described above:
+ WriteableScope testScope1 = WriteableScope.create(symtab.unnamedPackage);
+ testScope1.enter(firstSymbol);
+
+ WriteableScope dupped1 = testScope1.dup();
+
+ dupped1.enter(otherSymbol);
+ dble.invoke(dupped1);
+
+ if (testScope1.dupUnshared().findFirst(first) != firstSymbol) {
+ System.err.println("cannot find the Symbol in the dupUnshared scope (1)");
+ errors++;
+ }
+
+ //also check a situation where the clashing Symbol is removed from the dupped scope:
+ WriteableScope testScope2 = WriteableScope.create(symtab.unnamedPackage);
+ testScope2.enter(firstSymbol);
+
+ WriteableScope dupped2 = testScope2.dup();
+
+ dupped2.enter(otherSymbol);
+ dble.invoke(dupped2);
+ dupped2.remove(otherSymbol);
+
+ if (testScope2.dupUnshared().findFirst(first) != firstSymbol) {
+ System.err.println("cannot find the Symbol in the dupUnshared scope (2)");
+ errors++;
+ }
+ }
+
+ int MAX_TRIES = 100; // max tries to find a hash clash before giving up.
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/util/NewlineOnlyDiagnostic.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+import javax.annotation.processing.*;
+import javax.tools.Diagnostic.Kind;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+/*
+ * @test
+ * @bug 8060448
+ * @summary Test that javac doesn't throw ArrayIndexOutOfBoundsException
+ * when logging the message "\n"
+ * @library /tools/javac/lib
+ * @build JavacTestingAbstractProcessor NewlineOnlyDiagnostic
+ * @compile -processor NewlineOnlyDiagnostic NewlineOnlyDiagnostic.java
+ */
+
+public class NewlineOnlyDiagnostic extends JavacTestingAbstractProcessor {
+
+ @Override
+ public boolean process(Set<? extends TypeElement> types,RoundEnvironment rEnv) {
+ processingEnv.getMessager().printMessage(Kind.NOTE,"\n");
+ return true;
+ }
+}
--- a/langtools/test/tools/lib/ToolBox.java Fri Nov 14 17:53:46 2014 +0300
+++ b/langtools/test/tools/lib/ToolBox.java Mon Nov 17 12:32:27 2014 -0800
@@ -21,6 +21,7 @@
* questions.
*/
+import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
@@ -28,6 +29,7 @@
import java.io.File;
import java.io.FilterOutputStream;
import java.io.FilterWriter;
+import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -49,12 +51,15 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
+import java.util.EnumSet;
import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -64,18 +69,20 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
+
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.JavaFileManager.Location;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.JavacTool;
-import java.io.IOError;
/**
* Utility methods and classes for writing jtreg tests for
@@ -233,7 +240,7 @@
public void createDirectories(String... paths) throws IOException {
if (paths.length == 0)
throw new IllegalArgumentException("no directories specified");
- for (String p: paths)
+ for (String p : paths)
Files.createDirectories(Paths.get(p));
}
@@ -248,7 +255,7 @@
public void createDirectories(Path... paths) throws IOException {
if (paths.length == 0)
throw new IllegalArgumentException("no directories specified");
- for (Path p: paths)
+ for (Path p : paths)
Files.createDirectories(p);
}
@@ -262,7 +269,7 @@
public void deleteFiles(String... files) throws IOException {
if (files.length == 0)
throw new IllegalArgumentException("no files specified");
- for (String file: files)
+ for (String file : files)
Files.delete(Paths.get(file));
}
@@ -392,7 +399,7 @@
public void writeJavaFiles(Path dir, String... contents) throws IOException {
if (contents.length == 0)
throw new IllegalArgumentException("no content specified for any files");
- for (String c: contents) {
+ for (String c : contents) {
new JavaSource(c).write(dir);
}
}
@@ -1090,7 +1097,7 @@
private List<File> toFiles(String path) {
List<File> result = new ArrayList<>();
- for (String s: path.split(File.pathSeparator)) {
+ for (String s : path.split(File.pathSeparator)) {
if (!s.isEmpty())
result.add(new File(s));
}
@@ -1108,7 +1115,7 @@
if (fileObjects == null)
return filesAsFileObjects;
List<JavaFileObject> combinedList = new ArrayList<>();
- for (JavaFileObject o: filesAsFileObjects)
+ for (JavaFileObject o : filesAsFileObjects)
combinedList.add(o);
combinedList.addAll(fileObjects);
return combinedList;
@@ -1308,6 +1315,7 @@
private String mainClass;
private Path baseDir;
private List<Path> paths;
+ private Set<FileObject> fileObjects;
/**
* Creates a task to write jar files, using API mode.
@@ -1315,6 +1323,7 @@
public JarTask() {
super(Mode.API);
paths = Collections.emptyList();
+ fileObjects = new LinkedHashSet<>();
}
/**
@@ -1392,6 +1401,53 @@
}
/**
+ * Adds a set of file objects to be written into the jar file, by copying them
+ * from a Location in a JavaFileManager.
+ * The file objects to be written are specified by a series of paths;
+ * each path can be in one of the following forms:
+ * <ul>
+ * <li>The name of a class. For example, java.lang.Object.
+ * In this case, the corresponding .class file will be written to the jar file.
+ * <li>the name of a package followed by {@code .*}. For example, {@code java.lang.*}.
+ * In this case, all the class files in the specified package will be written to
+ * the jar file.
+ * <li>the name of a package followed by {@code .**}. For example, {@code java.lang.**}.
+ * In this case, all the class files in the specified package, and any subpackages
+ * will be written to the jar file.
+ * </ul>
+ *
+ * @param fm the file manager in which to find the file objects
+ * @param l the location in which to find the file objects
+ * @param paths the paths specifying the file objects to be copied
+ * @return this task object
+ * @throws IOException if errors occur while determining the set of file objects
+ */
+ public JarTask files(JavaFileManager fm, Location l, String... paths)
+ throws IOException {
+ for (String p : paths) {
+ if (p.endsWith(".**"))
+ addPackage(fm, l, p.substring(0, p.length() - 3), true);
+ else if (p.endsWith(".*"))
+ addPackage(fm, l, p.substring(0, p.length() - 2), false);
+ else
+ addFile(fm, l, p);
+ }
+ return this;
+ }
+
+ private void addPackage(JavaFileManager fm, Location l, String pkg, boolean recurse)
+ throws IOException {
+ for (JavaFileObject fo : fm.list(l, pkg, EnumSet.allOf(JavaFileObject.Kind.class), recurse)) {
+ fileObjects.add(fo);
+ }
+ }
+
+ private void addFile(JavaFileManager fm, Location l, String path) throws IOException {
+ JavaFileObject fo = fm.getJavaFileForInput(l, path, Kind.CLASS);
+ fileObjects.add(fo);
+ }
+
+ /**
* Provides limited jar command-like functionality.
* The supported commands are:
* <ul>
@@ -1464,42 +1520,19 @@
StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
- int rc;
Map<OutputKind, String> outputMap = new HashMap<>();
try (OutputStream os = Files.newOutputStream(jar);
JarOutputStream jos = openJar(os, m)) {
- Path base = (baseDir == null) ? currDir : baseDir;
- for (Path path: paths) {
- Files.walkFileTree(base.resolve(path), new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
- try {
- String p = base.relativize(file)
- .normalize()
- .toString()
- .replace(File.separatorChar, '/');
- JarEntry e = new JarEntry(p);
- jos.putNextEntry(e);
- jos.write(Files.readAllBytes(file));
- jos.closeEntry();
- return FileVisitResult.CONTINUE;
- } catch (IOException e) {
- System.err.println("Error adding " + file + " to jar file: " + e);
- return FileVisitResult.TERMINATE;
- }
- }
- });
- }
- rc = 0;
+ writeFiles(jos);
+ writeFileObjects(jos);
} catch (IOException e) {
- System.err.println("Error opening " + jar + ": " + e);
- rc = 1;
+ error("Exception while opening " + jar, e);
} finally {
outputMap.put(OutputKind.STDOUT, sysOut.close());
outputMap.put(OutputKind.STDERR, sysErr.close());
}
- return checkExit(new Result(this, rc, outputMap));
+ return checkExit(new Result(this, (errors == 0) ? 0 : 1, outputMap));
}
private JarOutputStream openJar(OutputStream os, Manifest m) throws IOException {
@@ -1512,6 +1545,79 @@
}
}
+ private void writeFiles(JarOutputStream jos) throws IOException {
+ Path base = (baseDir == null) ? currDir : baseDir;
+ for (Path path : paths) {
+ Files.walkFileTree(base.resolve(path), new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+ try {
+ String p = base.relativize(file)
+ .normalize()
+ .toString()
+ .replace(File.separatorChar, '/');
+ JarEntry e = new JarEntry(p);
+ jos.putNextEntry(e);
+ try {
+ jos.write(Files.readAllBytes(file));
+ } finally {
+ jos.closeEntry();
+ }
+ return FileVisitResult.CONTINUE;
+ } catch (IOException e) {
+ error("Exception while adding " + file + " to jar file", e);
+ return FileVisitResult.TERMINATE;
+ }
+ }
+ });
+ }
+ }
+
+ private void writeFileObjects(JarOutputStream jos) throws IOException {
+ for (FileObject fo : fileObjects) {
+ String p = guessPath(fo);
+ JarEntry e = new JarEntry(p);
+ jos.putNextEntry(e);
+ try {
+ byte[] buf = new byte[1024];
+ try (BufferedInputStream in = new BufferedInputStream(fo.openInputStream())) {
+ int n;
+ while ((n = in.read(buf)) > 0)
+ jos.write(buf, 0, n);
+ } catch (IOException ex) {
+ error("Exception while adding " + fo.getName() + " to jar file", ex);
+ }
+ } finally {
+ jos.closeEntry();
+ }
+ }
+ }
+
+ /*
+ * A jar: URL is of the form jar:URL!/entry where URL is a URL for the .jar file itself.
+ * In Symbol files (i.e. ct.sym) the underlying entry is prefixed META-INF/sym/<base>.
+ */
+ private final Pattern jarEntry = Pattern.compile(".*!/(?:META-INF/sym/[^/]+/)?(.*)");
+
+ private String guessPath(FileObject fo) {
+ URI u = fo.toUri();
+ switch (u.getScheme()) {
+ case "jar":
+ Matcher m = jarEntry.matcher(u.getSchemeSpecificPart());
+ if (m.matches()) {
+ return m.group(1);
+ }
+ break;
+ }
+ throw new IllegalArgumentException(fo.getName());
+ }
+
+ private void error(String message, Throwable t) {
+ out.println("Error: " + message + ": " + t);
+ errors++;
+ }
+
+ private int errors;
}
/**
--- a/make/CompileJavaModules.gmk Fri Nov 14 17:53:46 2014 +0300
+++ b/make/CompileJavaModules.gmk Mon Nov 17 12:32:27 2014 -0800
@@ -245,7 +245,6 @@
################################################################################
# Exclude building of IIOP transport for RMI Connector
-java.management_EXCLUDES := com/sun/jmx/remote/protocol/iiop
ifeq ($(RMICONNECTOR_IIOP), false)
java.management_EXCLUDES += com/sun/jmx/remote/protocol/iiop
@@ -264,11 +263,11 @@
java.corba_COPY := .prp
java.corba_CLEAN := .properties
-java.corba_EXCLUDES := \
+java.corba_EXCLUDES += \
com/sun/corba/se/PortableActivationIDL \
com/sun/tools/corba/se/logutil \
#
-java.corba_EXCLUDE_FILES := \
+java.corba_EXCLUDE_FILES += \
com/sun/corba/se/impl/presentation/rmi/JNDIStateFactoryImpl.java \
com/sun/corba/se/spi/presentation/rmi/StubWrapper.java \
com/sun/org/omg/CORBA/IDLTypeOperations.java \
@@ -350,12 +349,12 @@
$(JDK_TOPDIR)/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/Shutdown.java
ifeq ($(OPENJDK_TARGET_OS), macosx)
- jdk.sctp_EXCLUDE_FILES := $(SCTP_IMPL_CLASSES)
+ jdk.sctp_EXCLUDE_FILES += $(SCTP_IMPL_CLASSES)
endif
ifeq ($(OPENJDK_TARGET_OS),aix)
# These files are duplicated in AIX_SRC_DIRS
- jdk.sctp_EXCLUDE_FILES := $(SCTP_IMPL_CLASSES)
+ jdk.sctp_EXCLUDE_FILES += $(SCTP_IMPL_CLASSES)
endif
################################################################################
@@ -373,7 +372,7 @@
################################################################################
-jdk.jdi_EXCLUDES := \
+jdk.jdi_EXCLUDES += \
com/sun/tools/example/debug/bdi \
com/sun/tools/example/debug/event \
com/sun/tools/example/debug/gui \
@@ -414,7 +413,7 @@
jdk.localedata_COPY := _dict _th
# Exclude BreakIterator classes that are just used in compile process to generate
# data files and shouldn't go in the product
-jdk.localedata_EXCLUDE_FILES := sun/text/resources/th/BreakIteratorRules_th.java
+jdk.localedata_EXCLUDE_FILES += sun/text/resources/th/BreakIteratorRules_th.java
################################################################################
# Setup the compilation of each module
--- a/nashorn/.hgtags Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/.hgtags Mon Nov 17 12:32:27 2014 -0800
@@ -272,3 +272,4 @@
10fe62bc188476abb025e55f55128cbfecf24584 jdk9-b36
dd7bbdf81a537106cfa9227d1a9a57849cb26b4d jdk9-b37
365f55e7b3c45637bf912c88d31b32a127ad7429 jdk9-b38
+900508346b1c2436d7059fe46a621e6ec3ffdaad jdk9-b39
--- a/nashorn/make/build.xml Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/make/build.xml Mon Nov 17 12:32:27 2014 -0800
@@ -156,6 +156,7 @@
<fileset dir="${src.dir}/jdk/nashorn/tools/resources/"/>
</copy>
<copy file="${src.dir}/jdk/internal/dynalink/support/messages.properties" todir="${build.classes.dir}/jdk/internal/dynalink/support"/>
+ <copy file="${src.dir}/jdk/nashorn/internal/codegen/anchor.properties" todir="${build.classes.dir}/jdk/nashorn/internal/codegen"/>
<echo message="full=${nashorn.fullversion}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/>
<echo file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true">${line.separator}</echo>
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ApplySpecialization.java Mon Nov 17 12:32:27 2014 -0800
@@ -141,6 +141,11 @@
try {
functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
+ public boolean enterFunctionNode(final FunctionNode fn) {
+ return fn == functionNode;
+ }
+
+ @Override
public boolean enterCallNode(final CallNode callNode) {
if (isApply(callNode)) {
throw HAS_APPLIES;
@@ -162,7 +167,7 @@
* scope, thus we are conservative and treat any access to arguments outside the
* apply call as a case of "we cannot apply the optimization".
*/
- private void checkValidTransform(final FunctionNode functionNode) {
+ private static void checkValidTransform(final FunctionNode functionNode) {
final Set<Expression> argumentsFound = new HashSet<>();
final Deque<Set<Expression>> stack = new ArrayDeque<>();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java Mon Nov 17 12:32:27 2014 -0800
@@ -33,6 +33,8 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -221,11 +223,37 @@
private static void reportError(final String msg, final File file, final Exception e) {
final long now = System.currentTimeMillis();
if(now - lastReportedError > ERROR_REPORT_THRESHOLD) {
- getLogger().warning(String.format("Failed to %s %s", msg, file), e);
+ reportError(String.format("Failed to %s %s", msg, file), e);
lastReportedError = now;
}
}
+ /**
+ * Logs an error message with warning severity (reasoning being that we're reporting an error that'll disable the
+ * type info cache, but it's only logged as a warning because that doesn't prevent Nashorn from running, it just
+ * disables a performance-enhancing cache).
+ * @param msg the message to log
+ * @param e the exception that represents the error.
+ */
+ private static void reportError(final String msg, final Exception e) {
+ getLogger().warning(msg, "\n", exceptionToString(e));
+ }
+
+ /**
+ * A helper that prints an exception stack trace into a string. We have to do this as if we just pass the exception
+ * to {@link DebugLogger#warning(Object...)}, it will only log the exception message and not the stack, making
+ * problems harder to diagnose.
+ * @param e the exception
+ * @return the string representation of {@link Exception#printStackTrace()} output.
+ */
+ private static String exceptionToString(final Exception e) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw, false);
+ e.printStackTrace(pw);
+ pw.flush();
+ return sw.toString();
+ }
+
private static File createBaseCacheDir() {
if(MAX_FILES == 0 || Options.getBooleanProperty("nashorn.typeInfo.disabled")) {
return null;
@@ -233,7 +261,7 @@
try {
return createBaseCacheDirPrivileged();
} catch(final Exception e) {
- getLogger().warning("Failed to create cache dir", e);
+ reportError("Failed to create cache dir", e);
return null;
}
}
@@ -267,7 +295,7 @@
try {
return createCacheDirPrivileged(baseDir);
} catch(final Exception e) {
- getLogger().warning("Failed to create cache dir", e);
+ reportError("Failed to create cache dir", e);
return null;
}
}
@@ -280,7 +308,7 @@
try {
versionDirName = getVersionDirName();
} catch(final Exception e) {
- getLogger().warning("Failed to calculate version dir name", e);
+ reportError("Failed to calculate version dir name", e);
return null;
}
final File versionDir = new File(baseDir, versionDirName);
@@ -328,7 +356,12 @@
* @throws Exception if digest could not be created
*/
public static String getVersionDirName() throws Exception {
- final URL url = OptimisticTypesPersistence.class.getResource("");
+ // NOTE: getResource("") won't work if the JAR file doesn't have directory entries (and JAR files in JDK distro
+ // don't, or at least it's a bad idea counting on it). Alternatively, we could've tried
+ // getResource("OptimisticTypesPersistence.class") but behavior of getResource with regard to its willingness
+ // to hand out URLs to .class files is also unspecified. Therefore, the most robust way to obtain an URL to our
+ // package is to have a small non-class anchor file and start out from its URL.
+ final URL url = OptimisticTypesPersistence.class.getResource("anchor.properties");
final String protocol = url.getProtocol();
if (protocol.equals("jar")) {
// Normal deployment: nashorn.jar
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/anchor.properties Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,27 @@
+#
+# 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. 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.
+#
+
+
+# This file exists only so OptimisticTypesPersistence.getVersionDirName() can take its URL.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java Mon Nov 17 12:32:27 2014 -0800
@@ -264,6 +264,10 @@
case COMMARIGHT: {
return rhs.getType(localVariableTypes);
}
+ case AND:
+ case OR:{
+ return Type.widestReturnType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes));
+ }
default:
if (isComparison()) {
return Type.BOOLEAN;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Mon Nov 17 12:32:27 2014 -0800
@@ -35,7 +35,6 @@
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
import java.lang.invoke.MethodHandle;
-import java.lang.invoke.SwitchPoint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -93,17 +92,6 @@
private static final Object CALL_CMP = new Object();
private static final Object TO_LOCALE_STRING = new Object();
- private SwitchPoint lengthMadeNotWritableSwitchPoint;
- private PushLinkLogic pushLinkLogic;
- private PopLinkLogic popLinkLogic;
- private ConcatLinkLogic concatLinkLogic;
-
- /**
- * Index for the modification SwitchPoint that triggers when length
- * becomes not writable
- */
- private static final int LENGTH_NOT_WRITABLE_SWITCHPOINT = 0;
-
/*
* Constructors.
*/
@@ -271,12 +259,83 @@
@Override
public Object getLength() {
final long length = JSType.toUint32(getArray().length());
- if(length < Integer.MAX_VALUE) {
+ if (length < Integer.MAX_VALUE) {
return (int)length;
}
return length;
}
+ private boolean defineLength(final long oldLen, final PropertyDescriptor oldLenDesc, final PropertyDescriptor desc, final boolean reject) {
+ // Step 3a
+ if (!desc.has(VALUE)) {
+ return super.defineOwnProperty("length", desc, reject);
+ }
+
+ // Step 3b
+ final PropertyDescriptor newLenDesc = desc;
+
+ // Step 3c and 3d - get new length and convert to long
+ final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
+
+ // Step 3e
+ newLenDesc.setValue(newLen);
+
+ // Step 3f
+ // increasing array length - just need to set new length value (and attributes if any) and return
+ if (newLen >= oldLen) {
+ return super.defineOwnProperty("length", newLenDesc, reject);
+ }
+
+ // Step 3g
+ if (!oldLenDesc.isWritable()) {
+ if (reject) {
+ throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
+ }
+ return false;
+ }
+
+ // Step 3h and 3i
+ final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();
+ if (!newWritable) {
+ newLenDesc.setWritable(true);
+ }
+
+ // Step 3j and 3k
+ final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject);
+ if (!succeeded) {
+ return false;
+ }
+
+ // Step 3l
+ // make sure that length is set till the point we can delete the old elements
+ long o = oldLen;
+ while (newLen < o) {
+ o--;
+ final boolean deleteSucceeded = delete(o, false);
+ if (!deleteSucceeded) {
+ newLenDesc.setValue(o + 1);
+ if (!newWritable) {
+ newLenDesc.setWritable(false);
+ }
+ super.defineOwnProperty("length", newLenDesc, false);
+ if (reject) {
+ throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
+ }
+ return false;
+ }
+ }
+
+ // Step 3m
+ if (!newWritable) {
+ // make 'length' property not writable
+ final ScriptObject newDesc = Global.newEmptyInstance();
+ newDesc.set(WRITABLE, false, 0);
+ return super.defineOwnProperty("length", newDesc, false);
+ }
+
+ return true;
+ }
+
/**
* ECMA 15.4.5.1 [[DefineOwnProperty]] ( P, Desc, Throw )
*/
@@ -290,82 +349,16 @@
// Step 2
// get old length and convert to long
- long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
+ final long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
// Step 3
if ("length".equals(key)) {
// check for length being made non-writable
+ final boolean result = defineLength(oldLen, oldLenDesc, desc, reject);
if (desc.has(WRITABLE) && !desc.isWritable()) {
setIsLengthNotWritable();
}
-
- // Step 3a
- if (!desc.has(VALUE)) {
- return super.defineOwnProperty("length", desc, reject);
- }
-
- // Step 3b
- final PropertyDescriptor newLenDesc = desc;
-
- // Step 3c and 3d - get new length and convert to long
- final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
-
- // Step 3e
- newLenDesc.setValue(newLen);
-
- // Step 3f
- // increasing array length - just need to set new length value (and attributes if any) and return
- if (newLen >= oldLen) {
- return super.defineOwnProperty("length", newLenDesc, reject);
- }
-
- // Step 3g
- if (!oldLenDesc.isWritable()) {
- if (reject) {
- throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
- }
- return false;
- }
-
- // Step 3h and 3i
- final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();
- if (!newWritable) {
- newLenDesc.setWritable(true);
- }
-
- // Step 3j and 3k
- final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject);
- if (!succeeded) {
- return false;
- }
-
- // Step 3l
- // make sure that length is set till the point we can delete the old elements
- while (newLen < oldLen) {
- oldLen--;
- final boolean deleteSucceeded = delete(oldLen, false);
- if (!deleteSucceeded) {
- newLenDesc.setValue(oldLen + 1);
- if (!newWritable) {
- newLenDesc.setWritable(false);
- }
- super.defineOwnProperty("length", newLenDesc, false);
- if (reject) {
- throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
- }
- return false;
- }
- }
-
- // Step 3m
- if (!newWritable) {
- // make 'length' property not writable
- final ScriptObject newDesc = Global.newEmptyInstance();
- newDesc.set(WRITABLE, false, 0);
- return super.defineOwnProperty("length", newDesc, false);
- }
-
- return true;
+ return result;
}
// Step 4a
@@ -441,23 +434,7 @@
@Override
public void setIsLengthNotWritable() {
super.setIsLengthNotWritable();
- /*
- * Switchpoints are created lazily. If we link any push or pop site,
- * we need to create the "length made not writable" switchpoint, if it
- * doesn't exist.
- *
- * If the switchpoint already exists, we will find it here, and invalidate
- * it, invalidating all previous callsites that use it.
- *
- * If the switchpoint doesn't exist, no push/pop has been linked so far,
- * because that would create it too. We invalidate it immediately and the
- * check link logic for all future callsites will fail immediately at link
- * time
- */
- if (lengthMadeNotWritableSwitchPoint == null) {
- lengthMadeNotWritableSwitchPoint = new SwitchPoint();
- }
- SwitchPoint.invalidateAll(new SwitchPoint[] { lengthMadeNotWritableSwitchPoint });
+ setArray(ArrayData.setIsLengthNotWritable(getArray()));
}
/**
@@ -494,7 +471,7 @@
@Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public static void length(final Object self, final Object length) {
if (isArray(self)) {
- ((ScriptObject) self).setLength(validLength(length, true));
+ ((ScriptObject)self).setLength(validLength(length, true));
}
}
@@ -1306,10 +1283,13 @@
// Get only non-missing elements. Missing elements go at the end
// of the sorted array. So, just don't copy these to sort input.
final ArrayList<Object> src = new ArrayList<>();
- for (long i = 0; i < len; i = array.nextIndex(i)) {
- if (array.has((int) i)) {
- src.add(array.getObject((int) i));
+
+ for (final Iterator<Long> iter = array.indexIterator(); iter.hasNext(); ) {
+ final long index = iter.next();
+ if (index >= len) {
+ break;
}
+ src.add(array.getObject((int)index));
}
final Object[] sorted = sort(src.toArray(), comparefn);
@@ -1767,11 +1747,11 @@
@Override
public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) {
if (clazz == PushLinkLogic.class) {
- return pushLinkLogic == null ? new PushLinkLogic(this) : pushLinkLogic;
+ return PushLinkLogic.INSTANCE;
} else if (clazz == PopLinkLogic.class) {
- return popLinkLogic == null ? new PopLinkLogic(this) : pushLinkLogic;
+ return PopLinkLogic.INSTANCE;
} else if (clazz == ConcatLinkLogic.class) {
- return concatLinkLogic == null ? new ConcatLinkLogic(this) : concatLinkLogic;
+ return ConcatLinkLogic.INSTANCE;
}
return null;
}
@@ -1787,21 +1767,7 @@
* modification switchpoint which is touched when length is written.
*/
private static abstract class ArrayLinkLogic extends SpecializedFunction.LinkLogic {
- private final NativeArray array;
-
- protected ArrayLinkLogic(final NativeArray array) {
- this.array = array;
- }
-
- private SwitchPoint getSwitchPoint() {
- return array.lengthMadeNotWritableSwitchPoint;
- }
-
- private SwitchPoint newSwitchPoint() {
- assert array.lengthMadeNotWritableSwitchPoint == null;
- final SwitchPoint sp = new SwitchPoint();
- array.lengthMadeNotWritableSwitchPoint = sp;
- return sp;
+ protected ArrayLinkLogic() {
}
protected static ContinuousArrayData getContinuousArrayData(final Object self) {
@@ -1822,68 +1788,13 @@
public Class<? extends Throwable> getRelinkException() {
return ClassCastException.class;
}
-
- @Override
- public boolean hasModificationSwitchPoints() {
- return getSwitchPoint() != null;
- }
-
- @Override
- public boolean hasModificationSwitchPoint(final int index) {
- assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
- return hasModificationSwitchPoints();
- }
-
- @Override
- public SwitchPoint getOrCreateModificationSwitchPoint(final int index) {
- assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
- SwitchPoint sp = getSwitchPoint();
- if (sp == null) {
- sp = newSwitchPoint();
- }
- return sp;
- }
-
- @Override
- public SwitchPoint[] getOrCreateModificationSwitchPoints() {
- return new SwitchPoint[] { getOrCreateModificationSwitchPoint(LENGTH_NOT_WRITABLE_SWITCHPOINT) };
- }
-
- @Override
- public void invalidateModificationSwitchPoint(final int index) {
- assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
- invalidateModificationSwitchPoints();
- }
-
- @Override
- public void invalidateModificationSwitchPoints() {
- final SwitchPoint sp = getSwitchPoint();
- assert sp != null : "trying to invalidate non-existant modified SwitchPoint";
- if (!sp.hasBeenInvalidated()) {
- SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
- }
- }
-
- @Override
- public boolean hasInvalidatedModificationSwitchPoint(final int index) {
- assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
- return hasInvalidatedModificationSwitchPoints();
- }
-
- @Override
- public boolean hasInvalidatedModificationSwitchPoints() {
- final SwitchPoint sp = getSwitchPoint();
- return sp != null && !sp.hasBeenInvalidated();
- }
}
/**
* This is linker logic for optimistic concatenations
*/
private static final class ConcatLinkLogic extends ArrayLinkLogic {
- private ConcatLinkLogic(final NativeArray array) {
- super(array);
- }
+ private static final LinkLogic INSTANCE = new ConcatLinkLogic();
@Override
public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
@@ -1915,9 +1826,7 @@
* This is linker logic for optimistic pushes
*/
private static final class PushLinkLogic extends ArrayLinkLogic {
- private PushLinkLogic(final NativeArray array) {
- super(array);
- }
+ private static final LinkLogic INSTANCE = new PushLinkLogic();
@Override
public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
@@ -1929,9 +1838,7 @@
* This is linker logic for optimistic pops
*/
private static final class PopLinkLogic extends ArrayLinkLogic {
- private PopLinkLogic(final NativeArray array) {
- super(array);
- }
+ private static final LinkLogic INSTANCE = new PopLinkLogic();
/**
* We need to check if we are dealing with a continuous non empty array data here,
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDebug.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDebug.java Mon Nov 17 12:32:27 2014 -0800
@@ -39,6 +39,7 @@
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.events.RuntimeEvent;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
@@ -66,6 +67,36 @@
}
/**
+ * Return the ArrayData class for this ScriptObject
+ * @param self self
+ * @param obj script object to check
+ * @return ArrayData class, or undefined if no ArrayData is present
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getArrayDataClass(final Object self, final Object obj) {
+ try {
+ return ((ScriptObject)obj).getArray().getClass();
+ } catch (final ClassCastException e) {
+ return ScriptRuntime.UNDEFINED;
+ }
+ }
+
+ /**
+ * Return the ArrayData for this ScriptObject
+ * @param self self
+ * @param obj script object to check
+ * @return ArrayData, ArrayDatas have toString methods, return Undefined if data missing
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static Object getArrayData(final Object self, final Object obj) {
+ try {
+ return ((ScriptObject)obj).getArray();
+ } catch (final ClassCastException e) {
+ return ScriptRuntime.UNDEFINED;
+ }
+ }
+
+ /**
* Nashorn extension: get context, context utility
*
* @param self self reference
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Mon Nov 17 12:32:27 2014 -0800
@@ -30,7 +30,6 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.invoke.MethodHandle;
-import java.lang.invoke.SwitchPoint;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.runtime.ScriptFunction;
@@ -62,10 +61,6 @@
*/
public static final LinkLogic EMPTY_INSTANCE = new Empty();
- private static final SwitchPoint[] INVALIDATED_SWITCHPOINTS = new SwitchPoint[0];
-
- private SwitchPoint[] modificationSwitchPoints; //cache
-
/** Empty link logic class - allow all linking, no guards */
private static final class Empty extends LinkLogic {
@Override
@@ -167,92 +162,6 @@
}
/**
- * Return the modification SwitchPoint of a particular index from this OptimisticBuiltins
- * If none exists, one is created and that one is return.
- *
- * The implementor must map indexes to specific SwitchPoints for specific events and keep
- * track of what they mean, for example NativeArray.LENGTH_NOT_WRITABLE_SWITCHPOINT
- * might be a useful index mapping
- *
- * @param index index for SwitchPoint to get or create
- * @return modification SwitchPoint of particular index for the receiver
- */
- public SwitchPoint getOrCreateModificationSwitchPoint(final int index) {
- return null;
- }
-
- /**
- * Return the modification SwitchPoint from this OptimisticBuiltins. If none
- * exists, one is created and that one is return.
- *
- * @return modification SwitchPoint for the receiver
- */
- public SwitchPoint[] getOrCreateModificationSwitchPoints() {
- return null;
- }
-
- /**
- * Hook to invalidate a modification SwitchPoint by index.
- *
- * @param index index for SwitchPoint to invalidate
- */
- public void invalidateModificationSwitchPoint(final int index) {
- //empty
- }
-
- /**
- * Hook to invalidate all modification SwitchPoints for a receiver
- */
- public void invalidateModificationSwitchPoints() {
- //empty
- }
-
- /**
- * Check whether the receiver has an invalidated modification SwitchPoint.
- *
- * @param index index for the modification SwitchPoint
- * @return true if the particular SwitchPoint at the index is invalidated
- */
- public boolean hasInvalidatedModificationSwitchPoint(final int index) {
- return false;
- }
-
- /**
- * Check whether at least one of the modification SwitchPoints has been
- * invalidated
- * @return true if one of the SwitchPoints has been invalidated
- */
- public boolean hasInvalidatedModificationSwitchPoints() {
- return false;
- }
-
- /**
- * Check whether this OptimisticBuiltins has a SwitchPoints of particular
- * index.
- *
- * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of,
- * e.g. in the constructor of every subclass.
- *
- * @param index index for the modification SwitchPoint
- * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not
- */
- public boolean hasModificationSwitchPoint(final int index) {
- return false;
- }
-
- /**
- * Check whether this OptimisticBuiltins has SwitchPoints.
- *
- * As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of,
- * e.g. in the constructor of every subclass.
- *
- * @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not
- */
- public boolean hasModificationSwitchPoints() {
- return false;
- }
-
- /**
* Check, given a link request and a receiver, if this specialization
* fits This is used by the linker in {@link ScriptFunction} to figure
* out if an optimistic builtin can be linked when first discovered
@@ -265,47 +174,9 @@
* pick a non specialized target
*/
public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
- // no matter what the modification switchpoints are, if any of them are invalidated,
- // we can't link. Side effect is that if it's the first time we see this callsite,
- // we have to create the SwitchPoint(s) so future modification switchpoint invalidations
- // relink it
- final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(self);
- if (sps == INVALIDATED_SWITCHPOINTS) {
- // nope, can't do the fast link as this assumption
- // has been invalidated already, e.g. length of an
- // array set to not writable
- return false;
- }
- modificationSwitchPoints = sps; //cache
-
// check the link guard, if it says we can link, go ahead
return canLink(self, desc, request);
}
-
- private SwitchPoint[] getOrCreateModificationSwitchPoints(final Object self) {
- final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(); //ask for all my switchpoints
- if (sps != null) { //switchpoint exists, but some may be invalidated
- for (final SwitchPoint sp : sps) {
- if (sp.hasBeenInvalidated()) {
- return INVALIDATED_SWITCHPOINTS;
- }
- }
- }
- return sps;
- }
-
- /**
- * Get the cached modification switchpoints. Only possible to do after a link
- * check call has been performed, one that has answered "true", or you will get the
- * wrong information.
- *
- * Should be used only from {@link ScriptFunction#findCallMethod}
- *
- * @return cached modification switchpoints for this callsite, null if none
- */
- public SwitchPoint[] getModificationSwitchPoints() {
- return modificationSwitchPoints == null ? null : modificationSwitchPoints.clone();
- }
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java Mon Nov 17 12:32:27 2014 -0800
@@ -82,10 +82,9 @@
* Returns a new code store instance.
*
* @param context the current context
- * @return The instance
- * @throws IOException If an error occurs
+ * @return The instance, or null if code store could not be created
*/
- public static CodeStore newCodeStore(final Context context) throws IOException {
+ public static CodeStore newCodeStore(final Context context) {
final Class<CodeStore> baseClass = CodeStore.class;
try {
// security check first
@@ -103,9 +102,14 @@
} catch (final AccessControlException e) {
context.getLogger(CodeStore.class).warning("failed to load code store provider ", e);
}
- final CodeStore store = new DirectoryCodeStore(context);
- store.initLogger(context);
- return store;
+ try {
+ final CodeStore store = new DirectoryCodeStore(context);
+ store.initLogger(context);
+ return store;
+ } catch (final IOException e) {
+ context.getLogger(CodeStore.class).warning("failed to create cache directory ", e);
+ return null;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Mon Nov 17 12:32:27 2014 -0800
@@ -33,9 +33,11 @@
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
import java.lang.invoke.SwitchPoint;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Supplier;
@@ -726,34 +728,58 @@
* @param ipp
* @return string describing the ipp map
*/
- private static String toStringInvalidations(final Map<Integer, Type> ipp) {
+ private static List<String> toStringInvalidations(final Map<Integer, Type> ipp) {
if (ipp == null) {
- return "";
+ return Collections.emptyList();
}
- final StringBuilder sb = new StringBuilder();
+ final List<String> list = new ArrayList<>();
for (final Iterator<Map.Entry<Integer, Type>> iter = ipp.entrySet().iterator(); iter.hasNext(); ) {
final Map.Entry<Integer, Type> entry = iter.next();
final char bct = entry.getValue().getBytecodeStackType();
+ final String type;
+ switch (entry.getValue().getBytecodeStackType()) {
+ case 'A':
+ type = "object";
+ break;
+ case 'I':
+ type = "int";
+ break;
+ case 'J':
+ type = "long";
+ break;
+ case 'D':
+ type = "double";
+ break;
+ default:
+ type = String.valueOf(bct);
+ break;
+ }
+
+ final StringBuilder sb = new StringBuilder();
sb.append('[').
+ append("program point: ").
append(entry.getKey()).
- append("->").
- append(bct == 'A' ? 'O' : bct).
+ append(" -> ").
+ append(type).
append(']');
- if (iter.hasNext()) {
- sb.append(' ');
- }
+ list.add(sb.toString());
}
- return sb.toString();
+ return list;
}
private void logRecompile(final String reason, final FunctionNode fn, final MethodType type, final Map<Integer, Type> ipp) {
if (log.isEnabled()) {
- log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type, " ", toStringInvalidations(ipp));
+ log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type);
+ log.indent();
+ for (final String str : toStringInvalidations(ipp)) {
+ log.fine(str);
+ }
+ log.unindent();
}
}
@@ -769,7 +795,14 @@
*/
private synchronized MethodHandle handleRewriteException(final OptimismInfo oldOptInfo, final RewriteException re) {
if (log.isEnabled()) {
- log.info(new RecompilationEvent(Level.INFO, re, re.getReturnValueNonDestructive()), "RewriteException ", re.getMessageShort());
+ log.info(
+ new RecompilationEvent(
+ Level.INFO,
+ re,
+ re.getReturnValueNonDestructive()),
+ "caught RewriteException ",
+ re.getMessageShort());
+ log.indent();
}
final MethodType type = type();
@@ -799,7 +832,7 @@
logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
- log.info("Reusable IR generated");
+ log.fine("Reusable IR generated");
// compile the rest of the function, and install it
log.info("Generating and installing bytecode from reusable IR...");
@@ -815,16 +848,16 @@
compiler.persistClassInfo(cacheKey, normalFn);
}
- log.info("Done.");
-
final boolean canBeDeoptimized = normalFn.canBeDeoptimized();
if (log.isEnabled()) {
- log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? " can still be deoptimized." : " is completely deoptimized.");
+ log.unindent();
+ log.info("Done.");
+
+ log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? "can still be deoptimized." : " is completely deoptimized.");
+ log.finest("Looking up invoker...");
}
- log.info("Looking up invoker...");
-
final MethodHandle newInvoker = effectiveOptInfo.data.lookup(fn);
invoker = newInvoker.asType(type.changeReturnType(newInvoker.type().returnType()));
constructor = null; // Will be regenerated when needed
@@ -870,7 +903,6 @@
private SwitchPoint optimisticAssumptions;
private final DebugLogger log;
- @SuppressWarnings("unused")
OptimismInfo(final RecompilableScriptFunctionData data, final Map<Integer, Type> invalidatedProgramPoints) {
this.data = data;
this.log = data.getLogger();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Mon Nov 17 12:32:27 2014 -0800
@@ -509,11 +509,7 @@
}
if (env._persistent_cache) {
- try {
- codeStore = newCodeStore(this);
- } catch (final IOException e) {
- throw new RuntimeException("Error initializing code cache", e);
- }
+ codeStore = newCodeStore(this);
}
// print version info if asked.
@@ -1200,7 +1196,7 @@
FunctionNode functionNode = null;
// We only use the code store here if optimistic types are disabled. With optimistic types, initial compilation
// just creates a thin wrapper, and actual code is stored per function in RecompilableScriptFunctionData.
- final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
+ final boolean useCodeStore = codeStore != null && !env._parse_only && !env._optimistic_types;
final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
if (useCodeStore) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Mon Nov 17 12:32:27 2014 -0800
@@ -26,7 +26,6 @@
package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
-
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -620,20 +619,25 @@
return f;
}
- MethodHandle lookup(final FunctionInitializer fnInit) {
+ private void logLookup(final boolean shouldLog, final MethodType targetType) {
+ if (shouldLog && log.isEnabled()) {
+ log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType);
+ }
+ }
+
+ private MethodHandle lookup(final FunctionInitializer fnInit, final boolean shouldLog) {
final MethodType type = fnInit.getMethodType();
+ logLookup(shouldLog, type);
return lookupCodeMethod(fnInit.getCode(), type);
}
MethodHandle lookup(final FunctionNode fn) {
final MethodType type = new FunctionSignature(fn).getMethodType();
+ logLookup(true, type);
return lookupCodeMethod(fn.getCompileUnit().getCode(), type);
}
MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) {
- if (log.isEnabled()) {
- log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType);
- }
return MH.findStatic(LOOKUP, codeClass, functionName, targetType);
}
@@ -649,7 +653,7 @@
if(!code.isEmpty()) {
throw new IllegalStateException(name);
}
- addCode(lookup(initializer), null, null, initializer.getFlags());
+ addCode(lookup(initializer, true), null, null, initializer.getFlags());
}
private CompiledFunction addCode(final MethodHandle target, final Map<Integer, Type> invalidatedProgramPoints,
@@ -671,10 +675,10 @@
*/
private CompiledFunction addCode(final FunctionInitializer fnInit, final MethodType callSiteType) {
if (isVariableArity()) {
- return addCode(lookup(fnInit), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
+ return addCode(lookup(fnInit, true), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
}
- final MethodHandle handle = lookup(fnInit);
+ final MethodHandle handle = lookup(fnInit, true);
final MethodType fromType = handle.type();
MethodType toType = needsCallee(fromType) ? callSiteType.changeParameterType(0, ScriptFunction.class) : callSiteType.dropParameterTypes(0, 1);
toType = toType.changeReturnType(fromType.returnType());
@@ -699,7 +703,7 @@
toType = toType.dropParameterTypes(fromCount, toCount);
}
- return addCode(lookup(fnInit).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
+ return addCode(lookup(fnInit, false).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Mon Nov 17 12:32:27 2014 -0800
@@ -603,16 +603,6 @@
log.info("Linking optimistic builtin function: '", name, "' args=", Arrays.toString(request.getArguments()), " desc=", desc);
}
- final SwitchPoint[] msps = linkLogic.getModificationSwitchPoints();
- if (msps != null) {
- for (final SwitchPoint sp : msps) {
- if (sp != null) {
- assert !sp.hasBeenInvalidated();
- sps.add(sp);
- }
- }
- }
-
exceptionGuard = linkLogic.getRelinkException();
break;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Mon Nov 17 12:32:27 2014 -0800
@@ -510,6 +510,13 @@
}
}
+ private void invalidateGlobalConstant(final String key) {
+ final GlobalConstants globalConstants = getGlobalConstants();
+ if (globalConstants != null) {
+ globalConstants.delete(key);
+ }
+ }
+
/**
* ECMA 8.12.9 [[DefineOwnProperty]] (P, Desc, Throw)
*
@@ -525,6 +532,8 @@
final Object current = getOwnPropertyDescriptor(key);
final String name = JSType.toString(key);
+ invalidateGlobalConstant(key);
+
if (current == UNDEFINED) {
if (isExtensible()) {
// add a new own property
@@ -923,10 +932,8 @@
if (property instanceof UserAccessorProperty) {
((UserAccessorProperty)property).setAccessors(this, getMap(), null);
}
- final GlobalConstants globalConstants = getGlobalConstants();
- if (globalConstants != null) {
- globalConstants.delete(property.getKey());
- }
+
+ invalidateGlobalConstant(property.getKey());
return true;
}
}
@@ -1352,12 +1359,9 @@
final PropertyMap selfMap = this.getMap();
final ArrayData array = getArray();
- final long length = array.length();
-
- for (long i = 0; i < length; i = array.nextIndex(i)) {
- if (array.has((int)i)) {
- keys.add(JSType.toString(i));
- }
+
+ for (final Iterator<Long> iter = array.indexIterator(); iter.hasNext(); ) {
+ keys.add(JSType.toString(iter.next().longValue()));
}
for (final Property property : selfMap.getProperties()) {
@@ -1516,12 +1520,12 @@
*
* @return {@code true} if 'length' property is non-writable
*/
- public final boolean isLengthNotWritable() {
+ public boolean isLengthNotWritable() {
return (flags & IS_LENGTH_NOT_WRITABLE) != 0;
}
/**
- * Flag this object as having non-writable length property
+ * Flag this object as having non-writable length property.
*/
public void setIsLengthNotWritable() {
flags |= IS_LENGTH_NOT_WRITABLE;
@@ -3152,6 +3156,8 @@
public final void setObject(final FindProperty find, final int callSiteFlags, final String key, final Object value) {
FindProperty f = find;
+ invalidateGlobalConstant(key);
+
if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
final boolean isScope = NashornCallSiteDescriptor.isScopeFlag(callSiteFlags);
// If the start object of the find is not this object it means the property was found inside a
@@ -3177,7 +3183,6 @@
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
}
-
return;
}
@@ -3588,7 +3593,6 @@
}
return false;
}
-
return deleteObject(JSType.toObject(key), strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -30,6 +30,9 @@
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
@@ -56,6 +59,21 @@
public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData();
/**
+ * Length of the array data. Not necessarily length of the wrapped array.
+ * This is private to ensure that no one in a subclass is able to touch the length
+ * without going through {@link setLength}. This is used to implement
+ * {@link LengthNotWritableFilter}s, ensuring that there are no ways past
+ * a {@link setLength} function replaced by a nop
+ */
+ private long length;
+
+ /**
+ * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
+ * of the wrong type
+ */
+ protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
+
+ /**
* Immutable empty array to get ScriptObjects started.
* Use the same array and convert it to mutable as soon as it is modified
*/
@@ -82,7 +100,7 @@
@Override
public ContinuousArrayData copy() {
- return new UntouchedArrayData((int)length);
+ return new UntouchedArrayData((int)length());
}
@Override
@@ -113,6 +131,16 @@
}
@Override
+ public ArrayData delete(final int index) {
+ return new DeletedRangeArrayFilter(this, index, index);
+ }
+
+ @Override
+ public ArrayData delete(final long fromIndex, final long toIndex) {
+ return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
+ }
+
+ @Override
public void shiftLeft(final int by) {
//nop, always empty or we wouldn't be of this class
}
@@ -173,16 +201,6 @@
}
@Override
- public ArrayData delete(final int index) {
- return new DeletedRangeArrayFilter(this, index, index);
- }
-
- @Override
- public ArrayData delete(final long fromIndex, final long toIndex) {
- return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
- }
-
- @Override
public Object pop() {
return ScriptRuntime.UNDEFINED;
}
@@ -231,17 +249,6 @@
};
/**
- * Length of the array data. Not necessarily length of the wrapped array.
- */
- protected long length;
-
- /**
- * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
- * of the wrong type
- */
- protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
-
- /**
* Constructor
* @param length Virtual length of the array.
*/
@@ -394,6 +401,16 @@
}
/**
+ * Prevent this array from having its length reset
+ *
+ * @param underlying the underlying ArrayDAta to wrap in the non extensible filter
+ * @return new array data, filtered
+ */
+ public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) {
+ return new LengthNotWritableFilter(underlying);
+ }
+
+ /**
* Return the length of the array data. This may differ from the actual
* length of the array this wraps as length may be set or gotten as any
* other JavaScript Property
@@ -446,6 +463,22 @@
}
/**
+ * Increase length by 1
+ * @return the new length, not the old one (i.e. pre-increment)
+ */
+ protected final long increaseLength() {
+ return ++this.length;
+ }
+
+ /**
+ * Decrease length by 1.
+ * @return the new length, not the old one (i.e. pre-decrement)
+ */
+ protected final long decreaseLength() {
+ return --this.length;
+ }
+
+ /**
* Shift the array data left
*
* TODO: explore start at an index and not at zero, to make these operations
@@ -454,7 +487,7 @@
*
* @param by offset to shift
*/
- public abstract void shiftLeft(int by);
+ public abstract void shiftLeft(final int by);
/**
* Shift the array right
@@ -463,7 +496,7 @@
* @return New arraydata (or same)
*/
- public abstract ArrayData shiftRight(int by);
+ public abstract ArrayData shiftRight(final int by);
/**
* Ensure that the given index exists and won't fail subsequent
@@ -471,7 +504,7 @@
* @param safeIndex the index to ensure wont go out of bounds
* @return new array data (or same)
*/
- public abstract ArrayData ensure(long safeIndex);
+ public abstract ArrayData ensure(final long safeIndex);
/**
* Shrink the array to a new length, may or may not retain the
@@ -481,7 +514,7 @@
*
* @return new array data (or same)
*/
- public abstract ArrayData shrink(long newLength);
+ public abstract ArrayData shrink(final long newLength);
/**
* Set an object value at a given index
@@ -491,7 +524,7 @@
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, Object value, boolean strict);
+ public abstract ArrayData set(final int index, final Object value, final boolean strict);
/**
* Set an int value at a given index
@@ -501,7 +534,7 @@
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, int value, boolean strict);
+ public abstract ArrayData set(final int index, final int value, final boolean strict);
/**
* Set a long value at a given index
@@ -511,7 +544,7 @@
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, long value, boolean strict);
+ public abstract ArrayData set(final int index, final long value, final boolean strict);
/**
* Set an double value at a given index
@@ -521,7 +554,7 @@
* @param strict are we in strict mode
* @return new array data (or same)
*/
- public abstract ArrayData set(int index, double value, boolean strict);
+ public abstract ArrayData set(final int index, final double value, final boolean strict);
/**
* Set an empty value at a given index. Should only affect Object array.
@@ -552,7 +585,7 @@
* @param index the index
* @return the value
*/
- public abstract int getInt(int index);
+ public abstract int getInt(final int index);
/**
* Returns the optimistic type of this array data. Basically, when an array data object needs to throw an
@@ -581,7 +614,7 @@
* @param index the index
* @return the value
*/
- public abstract long getLong(int index);
+ public abstract long getLong(final int index);
/**
* Get optimistic long - default is that it's impossible. Overridden
@@ -601,7 +634,7 @@
* @param index the index
* @return the value
*/
- public abstract double getDouble(int index);
+ public abstract double getDouble(final int index);
/**
* Get optimistic double - default is that it's impossible. Overridden
@@ -621,14 +654,14 @@
* @param index the index
* @return the value
*/
- public abstract Object getObject(int index);
+ public abstract Object getObject(final int index);
/**
* Tests to see if an entry exists (avoids boxing.)
* @param index the index
* @return true if entry exists
*/
- public abstract boolean has(int index);
+ public abstract boolean has(final int index);
/**
* Returns if element at specific index can be deleted or not.
@@ -674,7 +707,7 @@
* @param index the index
* @return new array data (or same)
*/
- public abstract ArrayData delete(int index);
+ public abstract ArrayData delete(final int index);
/**
* Delete a given range from this array;
@@ -684,7 +717,7 @@
*
* @return new ArrayData after deletion
*/
- public abstract ArrayData delete(long fromIndex, long toIndex);
+ public abstract ArrayData delete(final long fromIndex, final long toIndex);
/**
* Convert the ArrayData to one with a different element type
@@ -694,7 +727,7 @@
* @param type new element type
* @return new array data
*/
- public abstract ArrayData convert(Class<?> type);
+ public abstract ArrayData convert(final Class<?> type);
/**
* Push an array of items to the end of the array
@@ -778,7 +811,7 @@
* @param to end index + 1
* @return new array data
*/
- public abstract ArrayData slice(long from, long to);
+ public abstract ArrayData slice(final long from, final long to);
/**
* Fast splice operation. This just modifies the array according to the number of
@@ -823,6 +856,34 @@
}
/**
+ * Return a list of keys in the array for the iterators
+ * @return iterator key list
+ */
+ protected List<Long> computeIteratorKeys() {
+ final List<Long> keys = new ArrayList<>();
+
+ final long len = length();
+ for (long i = 0L; i < len; i = nextIndex(i)) {
+ if (has((int)i)) {
+ keys.add(i);
+ }
+ }
+
+ return keys;
+ }
+
+ /**
+ * Return an iterator that goes through all indexes of elements
+ * in this array. This includes those after array.length if
+ * they exist
+ *
+ * @return iterator
+ */
+ public Iterator<Long> indexIterator() {
+ return computeIteratorKeys().iterator();
+ }
+
+ /**
* Exponential growth function for array size when in
* need of resizing.
*
@@ -841,7 +902,7 @@
*
* @return the next index
*/
- public long nextIndex(final long index) {
+ long nextIndex(final long index) {
return index + 1;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Mon Nov 17 12:32:27 2014 -0800
@@ -39,7 +39,7 @@
protected ArrayData underlying;
ArrayFilter(final ArrayData underlying) {
- super(underlying.length);
+ super(underlying.length());
this.underlying = underlying;
}
@@ -70,62 +70,55 @@
@Override
public void shiftLeft(final int by) {
underlying.shiftLeft(by);
- setLength(underlying.length);
+ setLength(underlying.length());
}
@Override
public ArrayData shiftRight(final int by) {
underlying = underlying.shiftRight(by);
- setLength(underlying.length);
-
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData ensure(final long safeIndex) {
underlying = underlying.ensure(safeIndex);
- setLength(underlying.length);
-
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData shrink(final long newLength) {
underlying = underlying.shrink(newLength);
- setLength(underlying.length);
-
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData set(final int index, final Object value, final boolean strict) {
underlying = underlying.set(index, value, strict);
- setLength(underlying.length);
-
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
underlying = underlying.set(index, value, strict);
- setLength(underlying.length);
-
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData set(final int index, final long value, final boolean strict) {
underlying = underlying.set(index, value, strict);
- setLength(underlying.length);
-
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
underlying = underlying.set(index, value, strict);
- setLength(underlying.length);
-
+ setLength(underlying.length());
return this;
}
@@ -189,29 +182,28 @@
@Override
public ArrayData delete(final int index) {
underlying = underlying.delete(index);
- setLength(underlying.length);
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData delete(final long from, final long to) {
underlying = underlying.delete(from, to);
- setLength(underlying.length);
+ setLength(underlying.length());
return this;
}
@Override
public ArrayData convert(final Class<?> type) {
underlying = underlying.convert(type);
- setLength(underlying.length);
+ setLength(underlying.length());
return this;
}
@Override
public Object pop() {
final Object value = underlying.pop();
- setLength(underlying.length);
-
+ setLength(underlying.length());
return value;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -65,7 +65,7 @@
* @return true if we don't need to do any array reallocation to fit an element at index
*/
public final boolean hasRoomFor(final int index) {
- return has(index) || (index == length && ensure(index) == this);
+ return has(index) || (index == length() && ensure(index) == this);
}
/**
@@ -73,7 +73,7 @@
* @return true if empty
*/
public boolean isEmpty() {
- return length == 0L;
+ return length() == 0L;
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Mon Nov 17 12:32:27 2014 -0800
@@ -38,8 +38,7 @@
DeletedArrayFilter(final ArrayData underlying) {
super(underlying);
-
- this.deleted = new BitVector(underlying.length);
+ this.deleted = new BitVector(underlying.length());
}
@Override
@@ -79,25 +78,24 @@
@Override
public void shiftLeft(final int by) {
super.shiftLeft(by);
- deleted.shiftLeft(by, length);
+ deleted.shiftLeft(by, length());
}
@Override
public ArrayData shiftRight(final int by) {
super.shiftRight(by);
- deleted.shiftRight(by, length);
-
+ deleted.shiftRight(by, length());
return this;
}
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
return new SparseArrayData(this, safeIndex + 1);
}
super.ensure(safeIndex);
- deleted.resize(length);
+ deleted.resize(length());
return this;
}
@@ -105,36 +103,31 @@
@Override
public ArrayData shrink(final long newLength) {
super.shrink(newLength);
- deleted.resize(length);
-
+ deleted.resize(length());
return this;
}
@Override
public ArrayData set(final int index, final Object value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
@Override
public ArrayData set(final int index, final long value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
-
return super.set(index, value, strict);
}
@@ -146,7 +139,7 @@
@Override
public ArrayData delete(final int index) {
final long longIndex = ArrayIndex.toLongIndex(index);
- assert longIndex >= 0 && longIndex < length;
+ assert longIndex >= 0 && longIndex < length();
deleted.set(longIndex);
underlying.setEmpty(index);
return this;
@@ -154,7 +147,7 @@
@Override
public ArrayData delete(final long fromIndex, final long toIndex) {
- assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length;
+ assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length();
deleted.setRange(fromIndex, toIndex + 1);
underlying.setEmpty(fromIndex, toIndex);
return this;
@@ -162,7 +155,7 @@
@Override
public Object pop() {
- final long index = length - 1;
+ final long index = length() - 1;
if (super.has((int)index)) {
final boolean isDeleted = deleted.isSet(index);
@@ -179,7 +172,7 @@
final ArrayData newArray = underlying.slice(from, to);
final DeletedArrayFilter newFilter = new DeletedArrayFilter(newArray);
newFilter.getDeleted().copy(deleted);
- newFilter.getDeleted().shiftLeft(from, newFilter.length);
+ newFilter.getDeleted().shiftLeft(from, newFilter.length());
return newFilter;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Mon Nov 17 12:32:27 2014 -0800
@@ -42,10 +42,10 @@
}
private static ArrayData maybeSparse(final ArrayData underlying, final long hi) {
- if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) {
+ if (hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) {
return underlying;
}
- return new SparseArrayData(underlying, underlying.length);
+ return new SparseArrayData(underlying, underlying.length());
}
private boolean isEmpty() {
@@ -93,7 +93,7 @@
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
return new SparseArrayData(this, safeIndex + 1);
}
@@ -110,7 +110,7 @@
@Override
public ArrayData shiftRight(final int by) {
super.shiftRight(by);
- final long len = length;
+ final long len = length();
lo = Math.min(len, lo + by);
hi = Math.min(len - 1, hi + by);
@@ -238,7 +238,7 @@
@Override
public Object pop() {
- final int index = (int)length - 1;
+ final int index = (int)length() - 1;
if (super.has(index)) {
final boolean isDeleted = isDeleted(index);
final Object value = super.pop();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java Mon Nov 17 12:32:27 2014 -0800
@@ -26,9 +26,9 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
* ArrayData after the array has been frozen by Object.freeze call.
@@ -79,4 +79,15 @@
}
return this;
}
+
+ @Override
+ public ArrayData push(final boolean strict, final Object... items) {
+ return this; //nop
+ }
+
+ @Override
+ public Object pop() {
+ final int len = (int)underlying.length();
+ return len == 0 ? ScriptRuntime.UNDEFINED : underlying.getObject(len - 1);
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -119,22 +119,24 @@
@Override
public IntArrayData copy() {
- return new IntArrayData(array.clone(), (int)length);
+ return new IntArrayData(array.clone(), (int)length());
}
@Override
public Object asArrayOfType(final Class<?> componentType) {
if (componentType == int.class) {
- return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
+ final int len = (int)length();
+ return array.length == len ? array.clone() : Arrays.copyOf(array, len);
}
return super.asArrayOfType(componentType);
}
private Object[] toObjectArray(final boolean trim) {
- assert length <= array.length : "length exceeds internal array size";
- final Object[] oarray = new Object[trim ? (int)length : array.length];
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
+ final Object[] oarray = new Object[trim ? len : array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
oarray[index] = Integer.valueOf(array[index]);
}
@@ -142,10 +144,11 @@
}
private double[] toDoubleArray() {
- assert length <= array.length : "length exceeds internal array size";
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
final double[] darray = new double[array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
darray[index] = array[index];
}
@@ -153,10 +156,11 @@
}
private long[] toLongArray() {
- assert length <= array.length : "length exceeds internal array size";
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
final long[] larray = new long[array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
larray[index] = array[index];
}
@@ -164,15 +168,15 @@
}
private LongArrayData convertToLong() {
- return new LongArrayData(toLongArray(), (int)length);
+ return new LongArrayData(toLongArray(), (int)length());
}
private NumberArrayData convertToDouble() {
- return new NumberArrayData(toDoubleArray(), (int)length);
+ return new NumberArrayData(toDoubleArray(), (int)length());
}
private ObjectArrayData convertToObject() {
- return new ObjectArrayData(toObjectArray(false), (int)length);
+ return new ObjectArrayData(toObjectArray(false), (int)length());
}
@Override
@@ -196,7 +200,7 @@
@Override
public ArrayData shiftRight(final int by) {
- final ArrayData newData = ensure(by + length - 1);
+ final ArrayData newData = ensure(by + length() - 1);
if (newData != this) {
newData.shiftRight(by);
return newData;
@@ -241,7 +245,7 @@
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@@ -250,7 +254,7 @@
public ArrayData set(final int index, final long value, final boolean strict) {
if (JSType.isRepresentableAsInt(value)) {
array[index] = JSType.toInt32(value);
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@@ -261,7 +265,7 @@
public ArrayData set(final int index, final double value, final boolean strict) {
if (JSType.isRepresentableAsInt(value)) {
array[index] = (int)(long)value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@@ -305,7 +309,7 @@
@Override
public boolean has(final int index) {
- return 0 <= index && index < length;
+ return 0 <= index && index < length();
}
@Override
@@ -320,11 +324,12 @@
@Override
public Object pop() {
- if (length == 0) {
+ final int len = (int)length();
+ if (len == 0) {
return ScriptRuntime.UNDEFINED;
}
- final int newLength = (int)length - 1;
+ final int newLength = len - 1;
final int elem = array[newLength];
array[newLength] = 0;
setLength(newLength);
@@ -334,12 +339,12 @@
@Override
public ArrayData slice(final long from, final long to) {
- return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length : from)));
+ return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length() : from)));
}
@Override
public final ArrayData push(final boolean strict, final int item) {
- final long len = length;
+ final long len = length();
final ArrayData newData = ensure(len);
if (newData == this) {
array[(int)len] = item;
@@ -350,7 +355,7 @@
@Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
- final long oldLength = length;
+ final long oldLength = length();
final long newLength = oldLength - removed + added;
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
@@ -384,21 +389,21 @@
@Override
public long fastPush(final int arg) {
- final int len = (int)length;
+ final int len = (int)length();
if (len == array.length) {
array = Arrays.copyOf(array, nextSize(len));
}
array[len] = arg;
- return ++length;
+ return increaseLength();
}
//length must not be zero
@Override
public int fastPopInt() {
- if (length == 0) {
+ if (length() == 0) {
throw new ClassCastException(); //relink
}
- final int newLength = (int)--length;
+ final int newLength = (int)decreaseLength();
final int elem = array[newLength];
array[newLength] = 0;
return elem;
@@ -421,8 +426,8 @@
@Override
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
- final int otherLength = (int)otherData.length;
- final int thisLength = (int)length;
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
assert otherLength > 0 && thisLength > 0;
final int[] otherArray = ((IntArrayData)otherData).array;
@@ -437,7 +442,7 @@
@Override
public String toString() {
- assert length <= array.length : length + " > " + array.length;
- return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
+ assert length() <= array.length : length() + " > " + array.length;
+ return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,198 @@
+package jdk.nashorn.internal.runtime.arrays;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Filter to use for ArrayData where the length is not writable.
+ * The default behavior is just to ignore {@link ArrayData#setLength}
+ */
+final class LengthNotWritableFilter extends ArrayFilter {
+ private final SortedMap<Long, Object> extraElements; //elements with index >= length
+
+ /**
+ * Constructor
+ * @param underlying array
+ */
+ LengthNotWritableFilter(final ArrayData underlying) {
+ this(underlying, new TreeMap<Long, Object>());
+ }
+
+ private LengthNotWritableFilter(final ArrayData underlying, final SortedMap<Long, Object> extraElements) {
+ super(underlying);
+ this.extraElements = extraElements;
+ }
+
+ @Override
+ public ArrayData copy() {
+ return new LengthNotWritableFilter(underlying.copy(), new TreeMap<>(extraElements));
+ }
+
+ @Override
+ public boolean has(final int index) {
+ return super.has(index) || extraElements.containsKey((long)index);
+ }
+
+ /**
+ * Set the length of the data array
+ *
+ * @param length the new length for the data array
+ */
+ @Override
+ public void setLength(final long length) {
+ //empty - setting length for a LengthNotWritableFilter is always a nop
+ }
+
+ @Override
+ public ArrayData ensure(final long index) {
+ return this;
+ }
+
+ @Override
+ public ArrayData slice(final long from, final long to) {
+ //return array[from...to), or array[from...length] if undefined, in this case not as we are an ArrayData
+ return new LengthNotWritableFilter(underlying.slice(from, to), extraElements.subMap(from, to));
+ }
+
+ private boolean checkAdd(final long index, final Object value) {
+ if (index >= length()) {
+ extraElements.put(index, value);
+ return true;
+ }
+ return false;
+ }
+
+ private Object get(final long index) {
+ final Object obj = extraElements.get(index);
+ if (obj == null) {
+ return ScriptRuntime.UNDEFINED;
+ }
+ return obj;
+ }
+
+ @Override
+ public int getInt(final int index) {
+ if (index >= length()) {
+ return JSType.toInt32(get(index));
+ }
+ return underlying.getInt(index);
+ }
+
+ @Override
+ public int getIntOptimistic(final int index, final int programPoint) {
+ if (index >= length()) {
+ return JSType.toInt32Optimistic(get(index), programPoint);
+ }
+ return underlying.getIntOptimistic(index, programPoint);
+ }
+
+ @Override
+ public long getLong(final int index) {
+ if (index >= length()) {
+ return JSType.toLong(get(index));
+ }
+ return underlying.getLong(index);
+ }
+
+ @Override
+ public long getLongOptimistic(final int index, final int programPoint) {
+ if (index >= length()) {
+ return JSType.toLongOptimistic(get(index), programPoint);
+ }
+ return underlying.getLongOptimistic(index, programPoint);
+ }
+
+ @Override
+ public double getDouble(final int index) {
+ if (index >= length()) {
+ return JSType.toNumber(get(index));
+ }
+ return underlying.getDouble(index);
+ }
+
+ @Override
+ public double getDoubleOptimistic(final int index, final int programPoint) {
+ if (index >= length()) {
+ return JSType.toNumberOptimistic(get(index), programPoint);
+ }
+ return underlying.getDoubleOptimistic(index, programPoint);
+ }
+
+ @Override
+ public Object getObject(final int index) {
+ if (index >= length()) {
+ return get(index);
+ }
+ return underlying.getObject(index);
+ }
+
+ @Override
+ public ArrayData set(final int index, final Object value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final int value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final long value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(final int index, final double value, final boolean strict) {
+ if (checkAdd(index, value)) {
+ return this;
+ }
+ underlying = underlying.set(index, value, strict);
+ return this;
+ }
+
+ @Override
+ public ArrayData delete(final int index) {
+ extraElements.remove(index);
+ underlying = underlying.delete(index);
+ return this;
+ }
+
+ @Override
+ public ArrayData delete(final long fromIndex, final long toIndex) {
+ for (final Iterator<Long> iter = extraElements.keySet().iterator(); iter.hasNext();) {
+ final long next = iter.next();
+ if (next >= fromIndex && next <= toIndex) {
+ iter.remove();
+ }
+ if (next > toIndex) { //ordering guaranteed because TreeSet
+ break;
+ }
+ }
+ underlying = underlying.delete(fromIndex, toIndex);
+ return this;
+ }
+
+ @Override
+ public Iterator<Long> indexIterator() {
+ final List<Long> keys = computeIteratorKeys();
+ keys.addAll(extraElements.keySet()); //even if they are outside length this is fine
+ return keys.iterator();
+ }
+
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -27,7 +27,6 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
-
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@@ -77,7 +76,7 @@
@Override
public LongArrayData copy() {
- return new LongArrayData(array.clone(), (int)length);
+ return new LongArrayData(array.clone(), (int)length());
}
@Override
@@ -86,10 +85,11 @@
}
private Object[] toObjectArray(final boolean trim) {
- assert length <= array.length : "length exceeds internal array size";
- final Object[] oarray = new Object[trim ? (int)length : array.length];
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
+ final Object[] oarray = new Object[trim ? len : array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
oarray[index] = Long.valueOf(array[index]);
}
@@ -99,16 +99,18 @@
@Override
public Object asArrayOfType(final Class<?> componentType) {
if (componentType == long.class) {
- return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
+ final int len = (int)length();
+ return array.length == len ? array.clone() : Arrays.copyOf(array, len);
}
return super.asArrayOfType(componentType);
}
private double[] toDoubleArray() {
- assert length <= array.length : "length exceeds internal array size";
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
final double[] darray = new double[array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
darray[index] = array[index];
}
@@ -120,7 +122,7 @@
if (type == Integer.class || type == Long.class) {
return this;
}
- final int len = (int)length;
+ final int len = (int)length();
if (type == Double.class) {
return new NumberArrayData(toDoubleArray(), len);
}
@@ -134,7 +136,7 @@
@Override
public ArrayData shiftRight(final int by) {
- final ArrayData newData = ensure(by + length - 1);
+ final ArrayData newData = ensure(by + length() - 1);
if (newData != this) {
newData.shiftRight(by);
return newData;
@@ -179,14 +181,14 @@
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@Override
public ArrayData set(final int index, final long value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@@ -194,7 +196,7 @@
public ArrayData set(final int index, final double value, final boolean strict) {
if (JSType.isRepresentableAsLong(value)) {
array[index] = (long)value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
return convert(Double.class).set(index, value, strict);
@@ -265,7 +267,7 @@
@Override
public boolean has(final int index) {
- return 0 <= index && index < length;
+ return 0 <= index && index < length();
}
@Override
@@ -280,11 +282,12 @@
@Override
public Object pop() {
- if (length == 0) {
+ final int len = (int)length();
+ if (len == 0) {
return ScriptRuntime.UNDEFINED;
}
- final int newLength = (int)length - 1;
+ final int newLength = len - 1;
final long elem = array[newLength];
array[newLength] = 0;
setLength(newLength);
@@ -294,14 +297,14 @@
@Override
public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? from + length : from;
+ final long start = from < 0 ? from + length() : from;
final long newLength = to - start;
return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
public final ArrayData push(final boolean strict, final long item) {
- final long len = length;
+ final long len = length();
final ArrayData newData = ensure(len);
if (newData == this) {
array[(int)len] = item;
@@ -312,7 +315,7 @@
@Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
- final long oldLength = length;
+ final long oldLength = length();
final long newLength = oldLength - removed + added;
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
@@ -345,20 +348,20 @@
@Override
public long fastPush(final long arg) {
- final int len = (int)length;
+ final int len = (int)length();
if (len == array.length) {
array = Arrays.copyOf(array, nextSize(len));
}
array[len] = arg;
- return ++length;
+ return increaseLength();
}
@Override
public long fastPopLong() {
- if (length == 0) {
- throw new ClassCastException();
+ if (length() == 0) {
+ throw new ClassCastException(); //undefined result
}
- final int newLength = (int)--length;
+ final int newLength = (int)decreaseLength();
final long elem = array[newLength];
array[newLength] = 0;
return elem;
@@ -376,8 +379,8 @@
@Override
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
- final int otherLength = (int)otherData.length;
- final int thisLength = (int)length;
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
assert otherLength > 0 && thisLength > 0;
final long[] otherArray = ((LongArrayData)otherData).array;
@@ -392,13 +395,14 @@
@Override
public String toString() {
- assert length <= array.length : length + " > " + array.length;
+ assert length() <= array.length : length() + " > " + array.length;
final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).
append(": [");
- for (int i = 0; i < length; i++) {
+ final int len = (int)length();
+ for (int i = 0; i < len; i++) {
sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString()
- if (i + 1 < length) {
+ if (i + 1 < len) {
sb.append(", ");
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java Mon Nov 17 12:32:27 2014 -0800
@@ -7,13 +7,13 @@
/**
* Filter class that wrap arrays that have been tagged non extensible
*/
-public class NonExtensibleArrayFilter extends ArrayFilter {
+final class NonExtensibleArrayFilter extends ArrayFilter {
/**
* Constructor
* @param underlying array
*/
- public NonExtensibleArrayFilter(final ArrayData underlying) {
+ NonExtensibleArrayFilter(final ArrayData underlying) {
super(underlying);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -28,7 +28,6 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@@ -76,7 +75,7 @@
@Override
public NumberArrayData copy() {
- return new NumberArrayData(array.clone(), (int)length);
+ return new NumberArrayData(array.clone(), (int)length());
}
@Override
@@ -85,10 +84,11 @@
}
private Object[] toObjectArray(final boolean trim) {
- assert length <= array.length : "length exceeds internal array size";
- final Object[] oarray = new Object[trim ? (int)length : array.length];
+ assert length() <= array.length : "length exceeds internal array size";
+ final int len = (int)length();
+ final Object[] oarray = new Object[trim ? len : array.length];
- for (int index = 0; index < length; index++) {
+ for (int index = 0; index < len; index++) {
oarray[index] = Double.valueOf(array[index]);
}
return oarray;
@@ -96,8 +96,9 @@
@Override
public Object asArrayOfType(final Class<?> componentType) {
- if(componentType == double.class) {
- return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
+ if (componentType == double.class) {
+ final int len = (int)length();
+ return array.length == len ? array.clone() : Arrays.copyOf(array, len);
}
return super.asArrayOfType(componentType);
}
@@ -105,7 +106,7 @@
@Override
public ContinuousArrayData convert(final Class<?> type) {
if (type != Double.class && type != Integer.class && type != Long.class) {
- final int len = (int)length;
+ final int len = (int)length();
return new ObjectArrayData(toObjectArray(false), len);
}
return this;
@@ -118,7 +119,7 @@
@Override
public ArrayData shiftRight(final int by) {
- final ArrayData newData = ensure(by + length - 1);
+ final ArrayData newData = ensure(by + length() - 1);
if (newData != this) {
newData.shiftRight(by);
return newData;
@@ -163,21 +164,21 @@
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@Override
public ArrayData set(final int index, final long value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@@ -241,7 +242,7 @@
@Override
public boolean has(final int index) {
- return 0 <= index && index < length;
+ return 0 <= index && index < length();
}
@Override
@@ -256,11 +257,12 @@
@Override
public Object pop() {
- if (length == 0) {
+ final int len = (int)length();
+ if (len == 0) {
return UNDEFINED;
}
- final int newLength = (int)length - 1;
+ final int newLength = len - 1;
final double elem = array[newLength];
array[newLength] = 0;
setLength(newLength);
@@ -269,14 +271,14 @@
@Override
public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? from + length : from;
+ final long start = from < 0 ? from + length() : from;
final long newLength = to - start;
return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
public final ArrayData push(final boolean strict, final double item) {
- final long len = length;
+ final long len = length();
final ArrayData newData = ensure(len);
if (newData == this) {
array[(int)len] = item;
@@ -287,7 +289,7 @@
@Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
- final long oldLength = length;
+ final long oldLength = length();
final long newLength = oldLength - removed + added;
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
@@ -325,21 +327,21 @@
@Override
public long fastPush(final double arg) {
- final int len = (int)length;
+ final int len = (int)length();
if (len == array.length) {
//note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory
array = Arrays.copyOf(array, nextSize(len));
}
array[len] = arg;
- return ++length;
+ return increaseLength();
}
@Override
public double fastPopDouble() {
- if (length == 0) {
+ if (length() == 0) {
throw new ClassCastException();
}
- final int newLength = (int)--length;
+ final int newLength = (int)decreaseLength();
final double elem = array[newLength];
array[newLength] = 0;
return elem;
@@ -352,8 +354,8 @@
@Override
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
- final int otherLength = (int)otherData.length;
- final int thisLength = (int)length;
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
assert otherLength > 0 && thisLength > 0;
final double[] otherArray = ((NumberArrayData)otherData).array;
@@ -368,7 +370,7 @@
@Override
public String toString() {
- assert length <= array.length : length + " > " + array.length;
- return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
+ assert length() <= array.length : length() + " > " + array.length;
+ return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -26,7 +26,6 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
-
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@@ -77,16 +76,16 @@
@Override
public ObjectArrayData copy() {
- return new ObjectArrayData(array.clone(), (int)length);
+ return new ObjectArrayData(array.clone(), (int)length());
}
@Override
public Object[] asObjectArray() {
- return array.length == length ? array.clone() : asObjectArrayCopy();
+ return array.length == length() ? array.clone() : asObjectArrayCopy();
}
private Object[] asObjectArrayCopy() {
- final long len = length;
+ final long len = length();
assert len <= Integer.MAX_VALUE;
final Object[] copy = new Object[(int)len];
System.arraycopy(array, 0, copy, 0, (int)len);
@@ -105,7 +104,7 @@
@Override
public ArrayData shiftRight(final int by) {
- final ArrayData newData = ensure(by + length - 1);
+ final ArrayData newData = ensure(by + length() - 1);
if (newData != this) {
newData.shiftRight(by);
return newData;
@@ -137,28 +136,28 @@
@Override
public ArrayData set(final int index, final Object value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@Override
public ArrayData set(final int index, final int value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@Override
public ArrayData set(final int index, final long value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@Override
public ArrayData set(final int index, final double value, final boolean strict) {
array[index] = value;
- setLength(Math.max(index + 1, length));
+ setLength(Math.max(index + 1, length()));
return this;
}
@@ -231,7 +230,7 @@
@Override
public boolean has(final int index) {
- return 0 <= index && index < length;
+ return 0 <= index && index < length();
}
@Override
@@ -263,20 +262,20 @@
@Override
public long fastPush(final Object arg) {
- final int len = (int)length;
+ final int len = (int)length();
if (len == array.length) {
array = Arrays.copyOf(array, nextSize(len));
}
array[len] = arg;
- return ++length;
+ return increaseLength();
}
@Override
public Object fastPopObject() {
- if (length == 0) {
+ if (length() == 0) {
return ScriptRuntime.UNDEFINED;
}
- final int newLength = (int)--length;
+ final int newLength = (int)decreaseLength();
final Object elem = array[newLength];
array[newLength] = ScriptRuntime.EMPTY;
return elem;
@@ -284,11 +283,11 @@
@Override
public Object pop() {
- if (length == 0) {
+ if (length() == 0) {
return ScriptRuntime.UNDEFINED;
}
- final int newLength = (int)length - 1;
+ final int newLength = (int)length() - 1;
final Object elem = array[newLength];
setEmpty(newLength);
setLength(newLength);
@@ -297,14 +296,14 @@
@Override
public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? from + length : from;
+ final long start = from < 0 ? from + length() : from;
final long newLength = to - start;
return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
public ArrayData push(final boolean strict, final Object item) {
- final long len = length;
+ final long len = length();
final ArrayData newData = ensure(len);
if (newData == this) {
array[(int)len] = item;
@@ -315,7 +314,7 @@
@Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
- final long oldLength = length;
+ final long oldLength = length();
final long newLength = oldLength - removed + added;
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
throw new UnsupportedOperationException();
@@ -343,8 +342,8 @@
@Override
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
- final int otherLength = (int)otherData.length;
- final int thisLength = (int)length;
+ final int otherLength = (int)otherData.length();
+ final int thisLength = (int)length();
assert otherLength > 0 && thisLength > 0;
final Object[] otherArray = ((ObjectArrayData)otherData).array;
@@ -359,7 +358,7 @@
@Override
public String toString() {
- assert length <= array.length : length + " > " + array.length;
- return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
+ assert length() <= array.length : length() + " > " + array.length;
+ return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -53,21 +53,21 @@
SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) {
super(length);
- assert underlying.length <= length;
+ assert underlying.length() <= length;
this.underlying = underlying;
- this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length);
+ this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length());
this.sparseMap = sparseMap;
}
@Override
public ArrayData copy() {
- return new SparseArrayData(underlying.copy(), length, new TreeMap<>(sparseMap));
+ return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap));
}
@Override
public Object[] asObjectArray() {
- final int len = (int)Math.min(length, Integer.MAX_VALUE);
- final int underlyingLength = (int)Math.min(len, underlying.length);
+ final int len = (int)Math.min(length(), Integer.MAX_VALUE);
+ final int underlyingLength = (int)Math.min(len, underlying.length());
final Object[] objArray = new Object[len];
for (int i = 0; i < underlyingLength; i++) {
@@ -104,14 +104,15 @@
}
sparseMap = newSparseMap;
- setLength(Math.max(length - by, 0));
+ setLength(Math.max(length() - by, 0));
}
@Override
public ArrayData shiftRight(final int by) {
final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
- if (underlying.length + by > maxDenseLength) {
- for (long i = maxDenseLength - by; i < underlying.length; i++) {
+ final long len = underlying.length();
+ if (len + by > maxDenseLength) {
+ for (long i = maxDenseLength - by; i < len; i++) {
if (underlying.has((int) i)) {
newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i));
}
@@ -127,23 +128,23 @@
}
sparseMap = newSparseMap;
- setLength(length + by);
+ setLength(length() + by);
return this;
}
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex < maxDenseLength && underlying.length <= safeIndex) {
+ if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) {
underlying = underlying.ensure(safeIndex);
}
- setLength(Math.max(safeIndex + 1, length));
+ setLength(Math.max(safeIndex + 1, length()));
return this;
}
@Override
public ArrayData shrink(final long newLength) {
- if (newLength < underlying.length) {
+ if (newLength < underlying.length()) {
underlying = underlying.shrink(newLength);
underlying.setLength(newLength);
sparseMap.clear();
@@ -160,11 +161,11 @@
if (index >= 0 && index < maxDenseLength) {
ensure(index);
underlying = underlying.set(index, value, strict);
- setLength(Math.max(underlying.length, length));
+ setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
- setLength(Math.max(longIndex + 1, length));
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
@@ -175,11 +176,11 @@
if (index >= 0 && index < maxDenseLength) {
ensure(index);
underlying = underlying.set(index, value, strict);
- setLength(Math.max(underlying.length, length));
+ setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
- setLength(Math.max(longIndex + 1, length));
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
}
@@ -189,11 +190,11 @@
if (index >= 0 && index < maxDenseLength) {
ensure(index);
underlying = underlying.set(index, value, strict);
- setLength(Math.max(underlying.length, length));
+ setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
- setLength(Math.max(longIndex + 1, length));
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
}
@@ -203,11 +204,11 @@
if (index >= 0 && index < maxDenseLength) {
ensure(index);
underlying = underlying.set(index, value, strict);
- setLength(Math.max(underlying.length, length));
+ setLength(Math.max(underlying.length(), length()));
} else {
final Long longIndex = indexToKey(index);
sparseMap.put(longIndex, value);
- setLength(Math.max(longIndex + 1, length));
+ setLength(Math.max(longIndex + 1, length()));
}
return this;
}
@@ -294,7 +295,7 @@
@Override
public boolean has(final int index) {
if (index >= 0 && index < maxDenseLength) {
- return index < underlying.length && underlying.has(index);
+ return index < underlying.length() && underlying.has(index);
}
return sparseMap.containsKey(indexToKey(index));
@@ -303,7 +304,7 @@
@Override
public ArrayData delete(final int index) {
if (index >= 0 && index < maxDenseLength) {
- if (index < underlying.length) {
+ if (index < underlying.length()) {
underlying = underlying.delete(index);
}
} else {
@@ -315,8 +316,8 @@
@Override
public ArrayData delete(final long fromIndex, final long toIndex) {
- if (fromIndex < maxDenseLength && fromIndex < underlying.length) {
- underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length - 1));
+ if (fromIndex < maxDenseLength && fromIndex < underlying.length()) {
+ underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length() - 1));
}
if (toIndex >= maxDenseLength) {
sparseMap.subMap(fromIndex, true, toIndex, true).clear();
@@ -336,30 +337,34 @@
@Override
public Object pop() {
- if (length == 0) {
+ final long len = length();
+ final long underlyingLen = underlying.length();
+ if (len == 0) {
return ScriptRuntime.UNDEFINED;
}
- if (length == underlying.length) {
+ if (len == underlyingLen) {
final Object result = underlying.pop();
- setLength(underlying.length);
+ setLength(underlying.length());
return result;
}
- setLength(length - 1);
- final Long key = Long.valueOf(length);
+ setLength(len - 1);
+ final Long key = Long.valueOf(len - 1);
return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED;
}
@Override
public ArrayData slice(final long from, final long to) {
- assert to <= length;
- final long start = from < 0 ? (from + length) : from;
+ assert to <= length();
+ final long start = from < 0 ? (from + length()) : from;
final long newLength = to - start;
+ final long underlyingLength = underlying.length();
+
if (start >= 0 && to <= maxDenseLength) {
- if (newLength <= underlying.length) {
+ if (newLength <= underlyingLength) {
return underlying.slice(from, to);
}
- return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length, newLength);
+ return underlying.slice(from, to).ensure(newLength - 1).delete(underlyingLength, newLength);
}
ArrayData sliced = EMPTY_ARRAY;
@@ -369,13 +374,13 @@
sliced = sliced.set((int)(i - start), getObject((int)i), false);
}
}
- assert sliced.length == newLength;
+ assert sliced.length() == newLength;
return sliced;
}
@Override
public long nextIndex(final long index) {
- if (index < underlying.length - 1) {
+ if (index < underlying.length() - 1) {
return underlying.nextIndex(index);
}
@@ -383,6 +388,7 @@
if (nextKey != null) {
return nextKey;
}
- return length;
+
+ return length();
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Mon Nov 17 12:32:27 2014 -0800
@@ -58,7 +58,7 @@
* @return element length
*/
public final int getElementLength() {
- return (int)length;
+ return (int)length();
}
/**
@@ -119,7 +119,7 @@
@Override
public final boolean has(final int index) {
- return 0 <= index && index < length;
+ return 0 <= index && index < length();
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Mon Nov 17 12:32:27 2014 -0800
@@ -39,8 +39,7 @@
UndefinedArrayFilter(final ArrayData underlying) {
super(underlying);
-
- this.undefined = new BitVector(underlying.length);
+ this.undefined = new BitVector(underlying.length());
}
@Override
@@ -80,25 +79,24 @@
@Override
public void shiftLeft(final int by) {
super.shiftLeft(by);
- undefined.shiftLeft(by, length);
+ undefined.shiftLeft(by, length());
}
@Override
public ArrayData shiftRight(final int by) {
super.shiftRight(by);
- undefined.shiftRight(by, length);
-
+ undefined.shiftRight(by, length());
return this;
}
@Override
public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
+ if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
return new SparseArrayData(this, safeIndex + 1);
}
super.ensure(safeIndex);
- undefined.resize(length);
+ undefined.resize(length());
return this;
}
@@ -106,8 +104,7 @@
@Override
public ArrayData shrink(final long newLength) {
super.shrink(newLength);
- undefined.resize(length);
-
+ undefined.resize(length());
return this;
}
@@ -216,7 +213,7 @@
@Override
public Object pop() {
- final long index = length - 1;
+ final long index = length() - 1;
if (super.has((int)index)) {
final boolean isUndefined = undefined.isSet(index);
@@ -233,7 +230,7 @@
final ArrayData newArray = underlying.slice(from, to);
final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray);
newFilter.getUndefined().copy(undefined);
- newFilter.getUndefined().shiftLeft(from, newFilter.length);
+ newFilter.getUndefined().shiftLeft(from, newFilter.length());
return newFilter;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312.js Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * JDK-8035312 push to frozen array must not increase length property
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.debug=true
+ */
+
+function printArrayDataClass(x) {
+ if (typeof Debug !== 'undefined') {
+ print(Debug.getArrayDataClass(x));
+ }
+}
+
+function gpush(x, elem) {
+ try {
+ print("Pushing " + elem + " to " + x);
+ x.push(elem);
+ } catch (e) {
+ print("caught error" + e);
+ }
+ print("\tarray is now [" + x + "] length is = " + x.length);
+ print();
+ printArrayDataClass(x);
+}
+
+function gpop(x) {
+ try {
+ print("Popping from " + x);
+ x.pop();
+ } catch (e) {
+ if (!(e instanceof TypeError)) {
+ print("e of wrong type " + e);
+ }
+ }
+ print("\tarray is now [" + x + "] length is = " + x.length);
+ print();
+ printArrayDataClass(x);
+}
+
+function checkArray(x) {
+ print();
+ print(">>> Push test");
+
+ var olen = x.length;
+ gpush(x, 0);
+
+ print("x.length === " + x.length + " (should be " + olen + ")");
+ print("x[3] === " + x[3] + " (should be 0)");
+ print("x[4] === " + x[4] + " (should be undefined)");
+
+ print();
+ print(">>> Pop test");
+ gpop(x);
+ gpop(x);
+ print("x.length === " + x.length + " (should be " + olen + ")");
+ print("x === " + x);
+
+ for (var i = 0 ; i < 5; i++) {
+ gpop(x);
+ }
+
+ print("x.length === " + x.length + " (should be " + olen + ")");
+ print("x === " + x);
+}
+
+print("*** Freezing");
+var frozen = [1,2,3];
+Object.freeze(frozen);
+checkArray(frozen);
+printArrayDataClass(frozen);
+
+//so far so good
+
+print();
+print("*** Other length not writable issues");
+var lengthNotWritable = [1,2,3];
+Object.defineProperty(lengthNotWritable, "length", { writable: false });
+checkArray(lengthNotWritable);
+printArrayDataClass(lengthNotWritable);
+
+function set(array, from, to, stride) {
+ //add three elements
+ for (var i = from; i < to; i+=stride) {
+ try {
+ print("Writing " + i);
+ array[i] = i;
+ printArrayDataClass(array);
+ } catch (e) {
+ print(e instanceof TypeError);
+ }
+ }
+}
+
+//define empty array with non writable length
+var arr = [1];
+Object.defineProperty(arr, "length", { writable: false });
+
+var olen2 = arr.length;
+
+set(arr, 0, 3, 1);
+
+if (arr.length != olen2) {
+ throw new ("error: " + arr.length + " != " + olen2);
+}
+
+print();
+print("array writing 0-3, with 1 stride, array = " + arr);
+print("length = " + arr.length + ", but elements are: " + arr[0] + " " + arr[1] + " " + arr[2]);
+print();
+
+//do the same but sparse/deleted range
+var arr2 = [1];
+Object.defineProperty(arr2, "length", { writable: false });
+
+print("initial length = " + arr2.length);
+var olen3 = arr2.length;
+
+set(arr2, 0, 30, 3);
+
+if (arr2.length != olen3) {
+ throw new ("error: " + arr2.length + " != " + olen3);
+}
+
+print();
+var larger = 20;
+print("array writing 0-" + larger + ", with 3 stride, array = " + arr2);
+print("length = " + arr2.length + ", but elements are: " + arr2[0] + " " + arr2[1] + " " + arr2[2]);
+
+for (var i = 0; i < larger; i++) {
+ if (arr2[i] === undefined) {
+ continue;
+ }
+ print(arr2[i] + " has length " + arr2.length);
+}
+
+print();
+var elem = 0x7fffffff - 10;
+printArrayDataClass(arr2);
+print("adding a new element high up in the array");
+print("length before element was added " + arr2.length);
+print("putting sparse at " + elem);
+arr2[elem] = "sparse";
+print("length after element was added " + arr2.length + " should be the same");
+printArrayDataClass(arr2);
+
+print();
+print("Printing arr2 - this will fail if length is > 28 and it is " + arr2.length);
+print("arr2 = [" + arr2 + "]");
+print("new length that should not be writable = " + arr2.length);
+print(arr2[elem] === "sparse");
+print(arr2[elem]);
+for (var i = 0; i < larger; i++) {
+ print(arr2[i]);
+}
+for (var key in arr2) {
+ print(key + ":" + arr2[key]);
+}
+
+//issues reported by sundar - generic setter doesn't go through push/pop bulkable
+
+function sundarExample2(arr, _writable) {
+ print("Checking if push works for bulkable non bulkable arrays - Setting length property not allowed");
+ arr[0] = "bar";
+ print(arr.length + " should be 1"); // should be 1
+ print(arr[0] + " should be bar");
+ print("["+ arr + "] should be [bar]");
+
+ // Object.defineProperty(arr, "length", { configurable: _writable });
+ Object.defineProperty(arr, "length", { writable: _writable });
+ arr[1] = "baz";
+
+ if (_writable) {
+ print(arr.length + " should be 2");
+ print(arr[0] + " should be bar");
+ print(arr[1] + " should be baz");
+ print("["+ arr + "] should be [bar,baz]");
+ } else {
+ print(arr.length + " should STILL be 1");
+ print(arr[0] + " should be bar");
+ print(arr[1] + " should be baz");
+ print("["+ arr + "] should be [bar]");
+ }
+}
+
+var newArr1 = [];
+sundarExample2(newArr1, false);
+print();
+try {
+ sundarExample2(newArr1, true);
+ print("should not get here");
+} catch (e) {
+ if (!(e instanceof TypeError)) {
+ print("Wrong exception");
+ }
+ print("got TypeError when redefining length, as expected")
+}
+print();
+
+sundarExample2([], true);
+print("Done");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,186 @@
+*** Freezing
+
+>>> Push test
+Pushing 0 to 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+x.length === 3 (should be 3)
+x[3] === undefined (should be 0)
+x[4] === undefined (should be undefined)
+
+>>> Pop test
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
+
+*** Other length not writable issues
+
+>>> Push test
+Pushing 0 to 1,2,3
+caught errorTypeError: "length" is not a writable property of [object Array]
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+x.length === 3 (should be 3)
+x[3] === 0 (should be 0)
+x[4] === undefined (should be undefined)
+
+>>> Pop test
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Popping from 1,2,3
+ array is now [1,2,3] length is = 3
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+x.length === 3 (should be 3)
+x === 1,2,3
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 0
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 1
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 2
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+
+array writing 0-3, with 1 stride, array = 0
+length = 1, but elements are: 0 undefined 2
+
+initial length = 1
+Writing 0
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 3
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 6
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 9
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 12
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 15
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 18
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 21
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 24
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+Writing 27
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+
+array writing 0-20, with 3 stride, array = 0
+length = 1, but elements are: 0 undefined undefined
+0 has length 1
+
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+adding a new element high up in the array
+length before element was added 1
+putting sparse at 2147483637
+length after element was added 1 should be the same
+class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
+
+Printing arr2 - this will fail if length is > 28 and it is 1
+arr2 = [0]
+new length that should not be writable = 1
+true
+sparse
+0
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+0:0
+2147483637:sparse
+Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
+1 should be 1
+bar should be bar
+[bar] should be [bar]
+1 should STILL be 1
+bar should be bar
+baz should be baz
+[bar] should be [bar]
+
+Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
+1 should be 1
+bar should be bar
+[bar] should be [bar]
+got TypeError when redefining length, as expected
+
+Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
+1 should be 1
+bar should be bar
+[bar] should be [bar]
+2 should be 2
+bar should be bar
+baz should be baz
+[bar,baz] should be [bar,baz]
+Done
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_2.js Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * JDK-8035312_2 - length setter and iterators
+ *
+ * @test
+ * @run
+ */
+
+"use strict"
+
+function printArray(a,n) {
+ print("PRINT_ARRAY CALLED: length = " + a.length);
+ print();
+
+ print("INDEXED");
+ for (var x = 0; x<n; x++) {
+ print("\t" + x + ":"+a[x]);
+ }
+ print("KEYS");
+ for (var key in a) {
+ print("\t" + key + ";" + a[key]);
+ }
+}
+
+var b = [1,2,3];
+
+Object.defineProperty(b, "length", { writable: false });
+var high = 8;
+b[high] = high;
+
+printArray(b, high + 5);
+
+var c = [1,2,3];
+c[high] = high;
+print();
+print("element[" + high + "]: " + c.length + " " + c[high]);
+print("Resetting length");
+c.length = 3;
+print("element[" + high + "]: " + c.length + " " + c[high]);
+print();
+
+printArray(c, high + 5);
+print();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_2.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,47 @@
+PRINT_ARRAY CALLED: length = 3
+
+INDEXED
+ 0:1
+ 1:2
+ 2:3
+ 3:undefined
+ 4:undefined
+ 5:undefined
+ 6:undefined
+ 7:undefined
+ 8:8
+ 9:undefined
+ 10:undefined
+ 11:undefined
+ 12:undefined
+KEYS
+ 0;1
+ 1;2
+ 2;3
+ 8;8
+
+element[8]: 9 8
+Resetting length
+element[8]: 3 undefined
+
+PRINT_ARRAY CALLED: length = 3
+
+INDEXED
+ 0:1
+ 1:2
+ 2:3
+ 3:undefined
+ 4:undefined
+ 5:undefined
+ 6:undefined
+ 7:undefined
+ 8:undefined
+ 9:undefined
+ 10:undefined
+ 11:undefined
+ 12:undefined
+KEYS
+ 0;1
+ 1;2
+ 2;3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_3.js Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * JDK-8035312_3 - sparse array, non writable length
+ *
+ * @test
+ * @run
+ */
+
+var b = [1,2,3];
+
+Object.defineProperty(b, "length", { writable: false });
+var high = 23534343;
+b[high-10] = high-10;
+
+print(b[high-10]);
+
+var c = [1,2,3];
+c[high-10] = high-10;
+c.length = 3;
+print(c);
+print(c[high-10]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_3.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,3 @@
+23534333
+1,2,3
+undefined
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_4.js Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * JDK-8035312_4 - pushes and pops for non writable length
+ *
+ * @test
+ * @run
+ */
+
+var b = [1,2,3];
+Object.defineProperty(b, "length", { writable: false });
+
+try {
+ b.push(4);
+} catch (e) {
+ print("length = " + b.length);
+ print("i caught an error");
+}
+print(b);
+print(b[3]);
+print("length = " + b.length);
+
+var c = [1,2,3];
+Object.defineProperty(c, "length", { writable: false });
+
+for (var i = 0; i < 5; i++) {
+ try {
+ c.pop();
+ } catch (e) {
+ print("length = " + c.length);
+ print("I caught an error");
+ print(c);
+ }
+}
+
+print(c);
+print(c[3]);
+print("length = " + b.length);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_4.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,23 @@
+length = 3
+i caught an error
+1,2,3
+4
+length = 3
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+length = 3
+I caught an error
+1,2,
+1,2,
+undefined
+length = 3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_5.js Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * JDK-8035312_5 - pushes and pops for frozen array
+ *
+ * @test
+ * @run
+ */
+
+var b = [1,2,3];
+Object.freeze(b);
+
+try {
+ b.push(4);
+} catch (e) {
+ print("length = " + b.length);
+ print("i caught an error");
+}
+print(b);
+print(b[3]);
+print("length = " + b.length);
+
+var c = [1,2,3];
+Object.freeze(c);
+
+for (var i = 0; i < 5; i++) {
+ try {
+ c.pop();
+ } catch (e) {
+ print("length = " + c.length);
+ print("I caught an error");
+ print(c);
+ }
+}
+
+print(c);
+print(c[3]);
+print("length = " + b.length);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8035312_5.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,6 @@
+1,2,3
+undefined
+length = 3
+1,2,3
+undefined
+length = 3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062799.js Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8062799: Binary logical expressions can have numeric types
+ *
+ * @test
+ * @run
+ */
+
+(function() {
+ var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect;
+
+ var b = true;
+ var i = 1;
+ var l = 4294967296;
+ var d = 2.1;
+ var o = "foo";
+
+ print(inspect(b || b, "b || b"));
+ print(inspect(b || i, "b || i"));
+ print(inspect(b || l, "b || l"));
+ print(inspect(b || d, "b || d"));
+ print(inspect(b || o, "b || o"));
+
+ print(inspect(i || b, "i || b"));
+ print(inspect(i || i, "i || i"));
+ print(inspect(i || l, "i || l"));
+ print(inspect(i || d, "i || d"));
+ print(inspect(i || o, "i || o"));
+
+ print(inspect(l || b, "l || b"));
+ print(inspect(l || i, "l || i"));
+ print(inspect(l || l, "l || l"));
+ print(inspect(l || d, "l || d"));
+ print(inspect(l || o, "l || o"));
+
+ print(inspect(d || b, "d || b"));
+ print(inspect(d || i, "d || i"));
+ print(inspect(d || l, "d || l"));
+ print(inspect(d || d, "d || d"));
+ print(inspect(d || o, "d || o"));
+
+ print(inspect(o || b, "o || b"));
+ print(inspect(o || i, "o || i"));
+ print(inspect(o || l, "o || l"));
+ print(inspect(o || d, "o || d"));
+ print(inspect(o || o, "o || o"));
+
+ print(inspect(b && b, "b && b"));
+ print(inspect(b && i, "b && i"));
+ print(inspect(b && l, "b && l"));
+ print(inspect(b && d, "b && d"));
+ print(inspect(b && o, "b && o"));
+
+ print(inspect(i && b, "i && b"));
+ print(inspect(i && i, "i && i"));
+ print(inspect(i && l, "i && l"));
+ print(inspect(i && d, "i && d"));
+ print(inspect(i && o, "i && o"));
+
+ print(inspect(l && b, "l && b"));
+ print(inspect(l && i, "l && i"));
+ print(inspect(l && l, "l && l"));
+ print(inspect(l && d, "l && d"));
+ print(inspect(l && o, "l && o"));
+
+ print(inspect(d && b, "d && b"));
+ print(inspect(d && i, "d && i"));
+ print(inspect(d && l, "d && l"));
+ print(inspect(d && d, "d && d"));
+ print(inspect(d && o, "d && o"));
+
+ print(inspect(o && b, "o && b"));
+ print(inspect(o && i, "o && i"));
+ print(inspect(o && l, "o && l"));
+ print(inspect(o && d, "o && d"));
+ print(inspect(o && o, "o && o"));
+})();
+
+
+
+
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062799.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,50 @@
+b || b: boolean
+b || i: boolean
+b || l: boolean
+b || d: boolean
+b || o: boolean
+i || b: int
+i || i: int
+i || l: long
+i || d: double
+i || o: int
+l || b: long
+l || i: long
+l || l: long
+l || d: double
+l || o: long
+d || b: double
+d || i: double
+d || l: double
+d || d: double
+d || o: double
+o || b: object
+o || i: object
+o || l: object
+o || d: object
+o || o: object
+b && b: boolean
+b && i: int
+b && l: long
+b && d: double
+b && o: object
+i && b: boolean
+i && i: int
+i && l: long
+i && d: double
+i && o: object
+l && b: boolean
+l && i: long
+l && l: long
+l && d: double
+l && o: object
+d && b: boolean
+d && i: double
+d && l: double
+d && d: double
+d && o: object
+o && b: boolean
+o && i: int
+o && l: long
+o && d: double
+o && o: object
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062937.js Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 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.
+ */
+
+/**
+ * JDK-8062937 - GlobalConstants produces wrong result with defineProperty and index setters
+ *
+ * @test
+ * @run
+ */
+
+var x = 1;
+for (var i = 2; i < 5; i++) {
+ print(x);
+ Object.defineProperty(this, "x", {value: i});
+}
+print(x);
+
+print();
+
+var name = "y";
+var y = 1;
+for (var i = 2; i < 5; i++) {
+ print(y);
+ this[name] = i;
+}
+print(y);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062937.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -0,0 +1,9 @@
+1
+2
+3
+4
+
+1
+2
+3
+4
--- a/nashorn/test/script/basic/fastpushpop.js.EXPECTED Fri Nov 14 17:53:46 2014 +0300
+++ b/nashorn/test/script/basic/fastpushpop.js.EXPECTED Mon Nov 17 12:32:27 2014 -0800
@@ -1,6 +1,6 @@
1,2,3,4,5,6
first: true
-1,2,3,4,5,6,7
+1,2,3,4,5,6
1,2,3,,,,4711.17,dingo!,4,5,6
second: true
-1,2,3,,,,4711.17,dingo!,4,5,6,7
+1,2,3,,,,4711.17,dingo!,4,5,6