--- a/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -349,3 +349,4 @@
086c682bd8c5f195c324f61e2c61fbcd0226d63b jdk-9+104
db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105
6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106
+1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107
--- a/.hgtags-top-repo Sat Mar 05 10:10:20 2016 +0100
+++ b/.hgtags-top-repo Sat Mar 05 20:46:44 2016 -0800
@@ -349,3 +349,4 @@
9a38f8b4ba220708db198d08d82fd2144a64777d jdk-9+104
be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105
54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106
+4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107
--- a/common/autoconf/flags.m4 Sat Mar 05 10:10:20 2016 +0100
+++ b/common/autoconf/flags.m4 Sat Mar 05 20:46:44 2016 -0800
@@ -123,12 +123,16 @@
[
# COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output
# COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler
+ # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder
+ # commands produced by the link step (currently AIX only)
if test "x$TOOLCHAIN_TYPE" = xxlc; then
COMPILER_TARGET_BITS_FLAG="-q"
COMPILER_COMMAND_FILE_FLAG="-f"
+ COMPILER_BINDCMD_FILE_FLAG="-bloadmap:"
else
COMPILER_TARGET_BITS_FLAG="-m"
COMPILER_COMMAND_FILE_FLAG="@"
+ COMPILER_BINDCMD_FILE_FLAG=""
# The solstudio linker does not support @-files.
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
@@ -152,6 +156,7 @@
fi
AC_SUBST(COMPILER_TARGET_BITS_FLAG)
AC_SUBST(COMPILER_COMMAND_FILE_FLAG)
+ AC_SUBST(COMPILER_BINDCMD_FILE_FLAG)
# FIXME: figure out if we should select AR flags depending on OS or toolchain.
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
@@ -294,10 +299,23 @@
SET_SHARED_LIBRARY_NAME='-h [$]1'
SET_SHARED_LIBRARY_MAPFILE='-M[$]1'
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- PICFLAG="-qpic=large"
+ # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only
+ # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker
+ # will have to patch this single instruction with a call to some out-of-order code which
+ # does the load from the TOC. This is of course slow. But in that case we also would have
+ # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'.
+ # With 'qpic=large' the compiler will by default generate a two-instruction sequence which
+ # can be patched directly by the linker and does not require a jump to out-of-order code.
+ # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc'
+ # instead. This creates a distinct TOC for every compilation unit (and thus requires two
+ # loads for accessing a global variable). But there are rumors that this may be seen as a
+ # 'performance feature' because of improved code locality of the symbols used in a
+ # compilation unit.
+ PICFLAG="-qpic"
+ JVM_CFLAGS="$JVM_CFLAGS $PICFLAG"
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
- SHARED_LIBRARY_FLAGS="-qmkshrobj"
+ SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry"
SET_EXECUTABLE_ORIGIN=""
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
@@ -835,7 +853,7 @@
LDFLAGS_CXX_SOLSTUDIO="-norunpath"
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok"
+ LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok"
LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC"
fi
@@ -891,6 +909,7 @@
AC_SUBST(JDKLIB_LIBS)
AC_SUBST(JDKEXE_LIBS)
AC_SUBST(LDFLAGS_CXX_JDK)
+ AC_SUBST(LDFLAGS_HASH_STYLE)
LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB"
LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE"
--- a/common/autoconf/generated-configure.sh Sat Mar 05 10:10:20 2016 +0100
+++ b/common/autoconf/generated-configure.sh Sat Mar 05 20:46:44 2016 -0800
@@ -701,6 +701,7 @@
ZERO_ARCHFLAG
LDFLAGS_TESTEXE
LDFLAGS_TESTLIB
+LDFLAGS_HASH_STYLE
LDFLAGS_CXX_JDK
JDKEXE_LIBS
JDKLIB_LIBS
@@ -743,6 +744,7 @@
CC_OUT_OPTION
STRIPFLAGS
ARFLAGS
+COMPILER_BINDCMD_FILE_FLAG
COMPILER_COMMAND_FILE_FLAG
COMPILER_TARGET_BITS_FLAG
JT_HOME
@@ -4230,7 +4232,7 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -4860,7 +4862,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1455271513
+DATE_WHEN_GENERATED=1456136781
###############################################################################
#
@@ -45391,12 +45393,16 @@
# COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output
# COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler
+ # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder
+ # commands produced by the link step (currently AIX only)
if test "x$TOOLCHAIN_TYPE" = xxlc; then
COMPILER_TARGET_BITS_FLAG="-q"
COMPILER_COMMAND_FILE_FLAG="-f"
+ COMPILER_BINDCMD_FILE_FLAG="-bloadmap:"
else
COMPILER_TARGET_BITS_FLAG="-m"
COMPILER_COMMAND_FILE_FLAG="@"
+ COMPILER_BINDCMD_FILE_FLAG=""
# The solstudio linker does not support @-files.
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
@@ -45424,6 +45430,7 @@
+
# FIXME: figure out if we should select AR flags depending on OS or toolchain.
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
ARFLAGS="-r"
@@ -46198,10 +46205,23 @@
SET_SHARED_LIBRARY_NAME='-h $1'
SET_SHARED_LIBRARY_MAPFILE='-M$1'
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- PICFLAG="-qpic=large"
+ # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only
+ # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker
+ # will have to patch this single instruction with a call to some out-of-order code which
+ # does the load from the TOC. This is of course slow. But in that case we also would have
+ # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'.
+ # With 'qpic=large' the compiler will by default generate a two-instruction sequence which
+ # can be patched directly by the linker and does not require a jump to out-of-order code.
+ # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc'
+ # instead. This creates a distinct TOC for every compilation unit (and thus requires two
+ # loads for accessing a global variable). But there are rumors that this may be seen as a
+ # 'performance feature' because of improved code locality of the symbols used in a
+ # compilation unit.
+ PICFLAG="-qpic"
+ JVM_CFLAGS="$JVM_CFLAGS $PICFLAG"
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
- SHARED_LIBRARY_FLAGS="-qmkshrobj"
+ SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry"
SET_EXECUTABLE_ORIGIN=""
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
@@ -46824,7 +46844,7 @@
LDFLAGS_CXX_SOLSTUDIO="-norunpath"
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok"
+ LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok"
LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC"
fi
@@ -46881,6 +46901,7 @@
+
LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB"
LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE"
@@ -58630,7 +58651,8 @@
# Setup libm (the maths library)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+ if test "x$OPENJDK_TARGET_OS" != "xwindows"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
$as_echo_n "checking for cos in -lm... " >&6; }
if ${ac_cv_lib_m_cos+:} false; then :
$as_echo_n "(cached) " >&6
@@ -58675,12 +58697,15 @@
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5
$as_echo "$as_me: Maths library was not found" >&6;}
fi
- LIBM=-lm
+ LIBM="-lm"
+ else
+ LIBM=""
+ fi
# Setup libdl (for dynamic library loading)
--- a/common/autoconf/libraries.m4 Sat Mar 05 10:10:20 2016 +0100
+++ b/common/autoconf/libraries.m4 Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -160,10 +160,14 @@
AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS],
[
# Setup libm (the maths library)
- AC_CHECK_LIB(m, cos, [], [
- AC_MSG_NOTICE([Maths library was not found])
- ])
- LIBM=-lm
+ if test "x$OPENJDK_TARGET_OS" != "xwindows"; then
+ AC_CHECK_LIB(m, cos, [], [
+ AC_MSG_NOTICE([Maths library was not found])
+ ])
+ LIBM="-lm"
+ else
+ LIBM=""
+ fi
AC_SUBST(LIBM)
# Setup libdl (for dynamic library loading)
--- a/common/autoconf/spec.gmk.in Sat Mar 05 10:10:20 2016 +0100
+++ b/common/autoconf/spec.gmk.in Sat Mar 05 20:46:44 2016 -0800
@@ -314,6 +314,10 @@
# Option used to pass a command file to the compiler
COMPILER_COMMAND_FILE_FLAG:=@COMPILER_COMMAND_FILE_FLAG@
+# Option for specifying a file which saves the binder commands
+# produced by the link step (for debugging, currently AIX only)
+COMPILER_BINDCMD_FILE_FLAG:=@COMPILER_BINDCMD_FILE_FLAG@
+
CC_OUT_OPTION:=@CC_OUT_OPTION@
EXE_OUT_OPTION:=@EXE_OUT_OPTION@
LD_OUT_OPTION:=@LD_OUT_OPTION@
@@ -351,6 +355,8 @@
CFLAGS_JDKEXE:=@CFLAGS_JDKEXE@
CXXFLAGS_JDKEXE:=@CXXFLAGS_JDKEXE@
+LDFLAGS_HASH_STYLE := @LDFLAGS_HASH_STYLE@
+
CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@
CPP:=@FIXPATH@ @CPP@
--- a/corba/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/corba/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -349,3 +349,4 @@
e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104
64006ae915b3aa85ac7e6fac679024d2da7fe526 jdk-9+105
8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106
+49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107
--- a/hotspot/.hgignore Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/.hgignore Sat Mar 05 20:46:44 2016 -0800
@@ -10,7 +10,6 @@
.igv.log
^.hgtip
.DS_Store
-\.class$
^\.mx.jvmci/env
^\.mx.jvmci/.*\.pyc
^\.mx.jvmci/eclipse-launches/.*
--- a/hotspot/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -509,3 +509,4 @@
534c50395957c6025fb6627e93b35756f8d48a08 jdk-9+104
266fa9bb5297bf02cb2a7b038b10a109817d2b48 jdk-9+105
7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106
+c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107
--- a/hotspot/make/bsd/makefiles/arm.make Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/make/bsd/makefiles/arm.make Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2016, 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
@@ -24,8 +24,4 @@
Obj_Files += bsd_arm.o
-ifneq ($(EXT_LIBS_PATH),)
- LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a
-endif
-
CFLAGS += -DVM_LITTLE_ENDIAN
--- a/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -54,6 +54,7 @@
define_pd_global(intx, InteriorEntryAlignment, 16);
define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
define_pd_global(intx, LoopUnrollLimit, 60);
+define_pd_global(intx, LoopPercentProfileLimit, 10);
// InitialCodeCacheSize derived from specjbb2000 run.
define_pd_global(intx, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize
define_pd_global(intx, CodeCacheExpansionSize, 64*K);
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -32,7 +32,6 @@
// Sets the default values for platform dependent flags used by the runtime system.
// (see globals.hpp)
-define_pd_global(bool, ConvertSleepToYield, true);
define_pd_global(bool, ShareVtableStubs, true);
define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this
--- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,39 +30,151 @@
#include "vmreg_aarch64.inline.hpp"
jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) {
- Unimplemented();
- return 0;
+ if (inst->is_call() || inst->is_jump() || inst->is_blr()) {
+ return pc_offset + NativeCall::instruction_size;
+ } else if (inst->is_general_jump()) {
+ return pc_offset + NativeGeneralJump::instruction_size;
+ } else {
+ JVMCI_ERROR_0("unsupported type of instruction for call site");
+ }
}
void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) {
- Unimplemented();
+ address pc = _instructions->start() + pc_offset;
+ Handle obj = HotSpotObjectConstantImpl::object(constant);
+ jobject value = JNIHandles::make_local(obj());
+ if (HotSpotObjectConstantImpl::compressed(constant)) {
+ int oop_index = _oop_recorder->find_index(value);
+ RelocationHolder rspec = oop_Relocation::spec(oop_index);
+ _instructions->relocate(pc, rspec, 1);
+ Unimplemented();
+ } else {
+ NativeMovConstReg* move = nativeMovConstReg_at(pc);
+ move->set_data((intptr_t) value);
+ int oop_index = _oop_recorder->find_index(value);
+ RelocationHolder rspec = oop_Relocation::spec(oop_index);
+ _instructions->relocate(pc, rspec);
+ }
}
void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) {
- Unimplemented();
+ address pc = _instructions->start() + pc_offset;
+ if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+ narrowKlass narrowOop = record_narrow_metadata_reference(constant, CHECK);
+ TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop);
+ Unimplemented();
+ } else {
+ NativeMovConstReg* move = nativeMovConstReg_at(pc);
+ Metadata* reference = record_metadata_reference(constant, CHECK);
+ move->set_data((intptr_t) reference);
+ TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference));
+ }
}
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
- Unimplemented();
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
+ address pc = _instructions->start() + pc_offset;
+ NativeInstruction* inst = nativeInstruction_at(pc);
+ if (inst->is_adr_aligned()) {
+ address dest = _constants->start() + data_offset;
+ _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS));
+ TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
+ } else {
+ JVMCI_ERROR("unknown load or move instruction at " PTR_FORMAT, p2i(pc));
+ }
}
void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) {
- Unimplemented();
+ address pc = (address) inst;
+ if (inst->is_call()) {
+ NativeCall* call = nativeCall_at(pc);
+ call->set_destination((address) foreign_call_destination);
+ _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+ } else if (inst->is_jump()) {
+ NativeJump* jump = nativeJump_at(pc);
+ jump->set_jump_destination((address) foreign_call_destination);
+ _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
+ } else if (inst->is_general_jump()) {
+ NativeGeneralJump* jump = nativeGeneralJump_at(pc);
+ jump->set_jump_destination((address) foreign_call_destination);
+ _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
+ } else {
+ JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc));
+ }
+ TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
}
void CodeInstaller::pd_relocate_JavaMethod(Handle hotspot_method, jint pc_offset, TRAPS) {
- Unimplemented();
+#ifdef ASSERT
+ Method* method = NULL;
+ // we need to check, this might also be an unresolved method
+ if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+ method = getMethodFromHotSpotMethod(hotspot_method());
+ }
+#endif
+ switch (_next_call_type) {
+ case INLINE_INVOKE:
+ break;
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
+ break;
+ }
+ case INVOKESTATIC: {
+ assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+ _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
+ break;
+ }
+ case INVOKESPECIAL: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
+ break;
+ }
+ default:
+ JVMCI_ERROR("invalid _next_call_type value");
+ break;
+ }
}
void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) {
- Unimplemented();
+ switch (mark) {
+ case POLL_NEAR:
+ JVMCI_ERROR("unimplemented");
+ break;
+ case POLL_FAR:
+ _instructions->relocate(pc, relocInfo::poll_type);
+ break;
+ case POLL_RETURN_NEAR:
+ JVMCI_ERROR("unimplemented");
+ break;
+ case POLL_RETURN_FAR:
+ _instructions->relocate(pc, relocInfo::poll_return_type);
+ break;
+ default:
+ JVMCI_ERROR("invalid mark value");
+ break;
+ }
}
// convert JVMCI register indices (as used in oop maps) to HotSpot registers
VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) {
- return NULL;
+ if (jvmci_reg < RegisterImpl::number_of_registers) {
+ return as_Register(jvmci_reg)->as_VMReg();
+ } else {
+ jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
+ if (floatRegisterNumber < FloatRegisterImpl::number_of_registers) {
+ return as_FloatRegister(floatRegisterNumber)->as_VMReg();
+ }
+ JVMCI_ERROR_NULL("invalid register number: %d", jvmci_reg);
+ }
}
bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
- return false;
+ return !hotspotRegister->is_FloatRegister();
}
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -136,7 +136,7 @@
MacroAssembler::pd_patch_instruction(instruction_address(), (address)x);
ICache::invalidate_range(instruction_address(), instruction_size);
}
-};
+}
void NativeMovConstReg::print() {
tty->print_cr(PTR_FORMAT ": mov reg, " INTPTR_FORMAT,
@@ -208,6 +208,32 @@
//-------------------------------------------------------------------
+address NativeGeneralJump::jump_destination() const {
+ NativeMovConstReg* move = nativeMovConstReg_at(instruction_address());
+ address dest = (address) move->data();
+
+ // We use jump to self as the unresolved address which the inline
+ // cache code (and relocs) know about
+
+ // return -1 if jump to self
+ dest = (dest == (address) this) ? (address) -1 : dest;
+ return dest;
+}
+
+void NativeGeneralJump::set_jump_destination(address dest) {
+ NativeMovConstReg* move = nativeMovConstReg_at(instruction_address());
+
+ // We use jump to self as the unresolved address which the inline
+ // cache code (and relocs) know about
+ if (dest == (address) -1) {
+ dest = instruction_address();
+ }
+
+ move->set_data((uintptr_t) dest);
+};
+
+//-------------------------------------------------------------------
+
bool NativeInstruction::is_safepoint_poll() {
// a safepoint_poll is implemented in two steps as either
//
@@ -249,6 +275,22 @@
Instruction_aarch64::extract(insn, 4, 0) == 0b11111);
}
+bool NativeInstruction::is_general_jump() {
+ if (is_movz()) {
+ NativeInstruction* inst1 = nativeInstruction_at(addr_at(instruction_size * 1));
+ if (inst1->is_movk()) {
+ NativeInstruction* inst2 = nativeInstruction_at(addr_at(instruction_size * 2));
+ if (inst2->is_movk()) {
+ NativeInstruction* inst3 = nativeInstruction_at(addr_at(instruction_size * 3));
+ if (inst3->is_blr()) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
bool NativeInstruction::is_movz() {
return Instruction_aarch64::extract(int_at(0), 30, 23) == 0b10100101;
}
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -54,11 +54,22 @@
friend class Relocation;
friend bool is_NativeCallTrampolineStub_at(address);
public:
- enum { instruction_size = 4 };
+ enum {
+ instruction_size = 4
+ };
+
+ juint encoding() const {
+ return uint_at(0);
+ }
+
+ bool is_blr() const { return (encoding() & 0xfffffc1f) == 0xd63f0000; }
+ bool is_adr_aligned() const { return (encoding() & 0xff000000) == 0x10000000; } // adr Xn, <label>, where label is aligned to 4 bytes (address of instruction).
+
inline bool is_nop();
inline bool is_illegal();
inline bool is_return();
bool is_jump();
+ bool is_general_jump();
inline bool is_jump_or_nop();
inline bool is_cond_jump();
bool is_safepoint_poll();
@@ -341,11 +352,15 @@
// An interface for accessing/manipulating native leal instruction of form:
// leal reg, [reg + offset]
-class NativeLoadAddress: public NativeMovRegMem {
- static const bool has_rex = true;
- static const int rex_size = 1;
+class NativeLoadAddress: public NativeInstruction {
+ enum AArch64_specific_constants {
+ instruction_size = 4,
+ instruction_offset = 0,
+ data_offset = 0,
+ next_instruction_offset = 4
+ };
+
public:
-
void verify();
void print ();
@@ -398,6 +413,10 @@
data_offset = 0,
next_instruction_offset = 4 * 4
};
+
+ address jump_destination() const;
+ void set_jump_destination(address dest);
+
static void insert_unconditional(address code_pos, address entry);
static void replace_mt_safe(address instr_addr, address code_buffer);
static void verify();
--- a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -54,6 +54,7 @@
define_pd_global(bool, UseTLAB, true);
define_pd_global(bool, ResizeTLAB, true);
define_pd_global(intx, LoopUnrollLimit, 60);
+define_pd_global(intx, LoopPercentProfileLimit, 10);
// Peephole and CISC spilling both break the graph, and so make the
// scheduler sick.
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -32,7 +32,6 @@
// Sets the default values for platform dependent flags used by the runtime system.
// (see globals.hpp)
-define_pd_global(bool, ConvertSleepToYield, true);
define_pd_global(bool, ShareVtableStubs, false); // Improves performance markedly for mtrt and compress.
define_pd_global(bool, NeedsDeoptSuspend, false); // Only register window machines need this.
--- a/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
Unimplemented();
}
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
Unimplemented();
}
--- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -52,6 +52,7 @@
define_pd_global(bool, UseTLAB, true);
define_pd_global(bool, ResizeTLAB, true);
define_pd_global(intx, LoopUnrollLimit, 60); // Design center runs on 1.3.1
+define_pd_global(intx, LoopPercentProfileLimit, 10);
define_pd_global(intx, MinJumpTableSize, 5);
// Peephole and CISC spilling both break the graph, and so makes the
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,6 @@
// the load of the dispatch address and hence the jmp would still go to the location
// according to the prior table. So, we let the thread continue and let it block by itself.
define_pd_global(bool, DontYieldALot, true); // yield no more than 100 times per second
-define_pd_global(bool, ConvertSleepToYield, false); // do not convert sleep(0) to yield. Helps GUI
define_pd_global(bool, ShareVtableStubs, false); // improves performance markedly for mtrt and compress
define_pd_global(bool, NeedsDeoptSuspend, true); // register window machines need this
--- a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -85,7 +85,7 @@
}
}
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
address pc = _instructions->start() + pc_offset;
NativeInstruction* inst = nativeInstruction_at(pc);
NativeInstruction* inst1 = nativeInstruction_at(pc + 4);
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -2015,23 +2015,33 @@
int vep_offset = ((intptr_t)__ pc()) - start;
#ifdef COMPILER1
- if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) {
- // Object.hashCode can pull the hashCode from the header word
- // instead of doing a full VM transition once it's been computed.
- // Since hashCode is usually polymorphic at call sites we can't do
- // this optimization at the call site without a lot of work.
+ if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
+ // Object.hashCode, System.identityHashCode can pull the hashCode from the
+ // header word instead of doing a full VM transition once it's been computed.
+ // Since hashCode is usually polymorphic at call sites we can't do this
+ // optimization at the call site without a lot of work.
Label slowCase;
- Register receiver = O0;
+ Label done;
+ Register obj_reg = O0;
Register result = O0;
Register header = G3_scratch;
Register hash = G3_scratch; // overwrite header value with hash value
Register mask = G1; // to get hash field from header
+ // Unlike for Object.hashCode, System.identityHashCode is static method and
+ // gets object as argument instead of the receiver.
+ if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) {
+ assert(method->is_static(), "method should be static");
+ // return 0 for null reference input
+ __ br_null(obj_reg, false, Assembler::pn, done);
+ __ delayed()->mov(obj_reg, hash);
+ }
+
// Read the header and build a mask to get its hash field. Give up if the object is not unlocked.
// We depend on hash_mask being at most 32 bits and avoid the use of
// hash_mask_in_place because it could be larger than 32 bits in a 64-bit
// vm: see markOop.hpp.
- __ ld_ptr(receiver, oopDesc::mark_offset_in_bytes(), header);
+ __ ld_ptr(obj_reg, oopDesc::mark_offset_in_bytes(), header);
__ sethi(markOopDesc::hash_mask, mask);
__ btst(markOopDesc::unlocked_value, header);
__ br(Assembler::zero, false, Assembler::pn, slowCase);
@@ -2054,6 +2064,7 @@
__ delayed()->nop();
// leaf return.
+ __ bind(done);
__ retl();
__ delayed()->mov(hash, result);
__ bind(slowCase);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -2361,7 +2361,7 @@
void Assembler::movdqu(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit);
simd_prefix(dst, xnoreg, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x6F);
@@ -2398,7 +2398,7 @@
void Assembler::vmovdqu(XMMRegister dst, Address src) {
assert(UseAVX > 0, "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_256bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
+ InstructionAttr attributes(AVX_256bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit);
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x6F);
@@ -2486,7 +2486,7 @@
void Assembler::evmovdqul(XMMRegister dst, Address src, int vector_len) {
assert(VM_Version::supports_evex(), "");
InstructionMark im(this);
- InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false , /* uses_vl */ true);
attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit);
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x6F);
@@ -2515,7 +2515,7 @@
void Assembler::evmovdquq(XMMRegister dst, Address src, int vector_len) {
assert(VM_Version::supports_evex(), "");
InstructionMark im(this);
- InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
attributes.set_address_attributes(/* tuple_type */ EVEX_FVM, /* input_size_in_bits */ EVEX_NObit);
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x6F);
@@ -2640,7 +2640,7 @@
void Assembler::movsd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x10);
emit_int8((unsigned char)(0xC0 | encode));
@@ -2649,7 +2649,7 @@
void Assembler::movsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x10);
@@ -2668,7 +2668,7 @@
void Assembler::movss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x10);
emit_int8((unsigned char)(0xC0 | encode));
@@ -2677,7 +2677,7 @@
void Assembler::movss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
simd_prefix(dst, xnoreg, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x10);
@@ -2782,7 +2782,7 @@
void Assembler::mulsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x59);
@@ -2791,7 +2791,7 @@
void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x59);
emit_int8((unsigned char)(0xC0 | encode));
@@ -2800,7 +2800,7 @@
void Assembler::mulss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x59);
@@ -2809,7 +2809,7 @@
void Assembler::mulss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x59);
emit_int8((unsigned char)(0xC0 | encode));
@@ -3993,7 +3993,7 @@
void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x51);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4002,7 +4002,7 @@
void Assembler::sqrtsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x51);
@@ -4011,7 +4011,7 @@
void Assembler::sqrtss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x51);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4024,7 +4024,7 @@
void Assembler::sqrtss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x51);
@@ -4078,7 +4078,7 @@
void Assembler::subsd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x5C);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4087,7 +4087,7 @@
void Assembler::subsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
simd_prefix(dst, dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x5C);
@@ -4096,7 +4096,7 @@
void Assembler::subss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false , /* uses_vl */ false);
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x5C);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4105,7 +4105,7 @@
void Assembler::subss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
simd_prefix(dst, dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x5C);
@@ -4293,7 +4293,7 @@
void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
@@ -4303,7 +4303,7 @@
void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x58);
@@ -4313,7 +4313,7 @@
void Assembler::vaddss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
@@ -4323,7 +4323,7 @@
void Assembler::vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x58);
@@ -4333,7 +4333,7 @@
void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
@@ -4343,7 +4343,7 @@
void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x5E);
@@ -4353,7 +4353,7 @@
void Assembler::vdivss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
@@ -4363,7 +4363,7 @@
void Assembler::vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x5E);
@@ -4373,7 +4373,7 @@
void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
@@ -4383,7 +4383,7 @@
void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x59);
@@ -4393,7 +4393,7 @@
void Assembler::vmulss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
@@ -4403,7 +4403,7 @@
void Assembler::vmulss(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x59);
@@ -4413,7 +4413,7 @@
void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
@@ -4423,7 +4423,7 @@
void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
emit_int8(0x5C);
@@ -4433,7 +4433,7 @@
void Assembler::vsubss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
InstructionMark im(this);
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
@@ -4443,7 +4443,7 @@
void Assembler::vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
- InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
+ InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
emit_int8(0x5C);
@@ -5901,7 +5901,7 @@
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) {
assert(VM_Version::supports_evex(), "");
- InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x78);
emit_int8((unsigned char)(0xC0 | encode));
@@ -5911,7 +5911,7 @@
assert(VM_Version::supports_evex(), "");
assert(dst != xnoreg, "sanity");
InstructionMark im(this);
- InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_8bit);
// swap src<->dst for encoding
vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
@@ -5922,7 +5922,7 @@
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastw(XMMRegister dst, XMMRegister src, int vector_len) {
assert(VM_Version::supports_evex(), "");
- InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x79);
emit_int8((unsigned char)(0xC0 | encode));
@@ -5932,7 +5932,7 @@
assert(VM_Version::supports_evex(), "");
assert(dst != xnoreg, "sanity");
InstructionMark im(this);
- InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_16bit);
// swap src<->dst for encoding
vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
@@ -6027,7 +6027,7 @@
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastb(XMMRegister dst, Register src, int vector_len) {
assert(VM_Version::supports_evex(), "");
- InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x7A);
emit_int8((unsigned char)(0xC0 | encode));
@@ -6036,7 +6036,7 @@
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastw(XMMRegister dst, Register src, int vector_len) {
assert(VM_Version::supports_evex(), "");
- InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true);
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
emit_int8(0x7B);
emit_int8((unsigned char)(0xC0 | encode));
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -2044,11 +2044,11 @@
class InstructionAttr {
public:
InstructionAttr(
- int vector_len,
- bool rex_vex_w,
- bool legacy_mode,
- bool no_reg_mask,
- bool uses_vl)
+ int vector_len, // The length of vector to be applied in encoding - for both AVX and EVEX
+ bool rex_vex_w, // Width of data: if 32-bits or less, false, else if 64-bit or specially defined, true
+ bool legacy_mode, // Details if either this instruction is conditionally encoded to AVX or earlier if true else possibly EVEX
+ bool no_reg_mask, // when true, k0 is used when EVEX encoding is chosen, else k1 is used under the same condition
+ bool uses_vl) // This instruction may have legacy constraints based on vector length for EVEX
:
_avx_vector_len(vector_len),
_rex_vex_w(rex_vex_w),
--- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -46,6 +46,7 @@
define_pd_global(intx, ConditionalMoveLimit, 3);
define_pd_global(intx, FreqInlineSize, 325);
define_pd_global(intx, MinJumpTableSize, 10);
+define_pd_global(intx, LoopPercentProfileLimit, 30);
#ifdef AMD64
define_pd_global(intx, INTPRESSURE, 13);
define_pd_global(intx, FLOATPRESSURE, 14);
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -31,7 +31,6 @@
// Sets the default values for platform dependent flags used by the runtime system.
// (see globals.hpp)
-define_pd_global(bool, ConvertSleepToYield, true);
define_pd_global(bool, ShareVtableStubs, true);
define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this
--- a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -101,7 +101,7 @@
}
}
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
address pc = _instructions->start() + pc_offset;
address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -7840,7 +7840,9 @@
Label COMPARE_WIDE_VECTORS_LOOP_FAILED; // used only _LP64 && AVX3
int stride, stride2, adr_stride, adr_stride1, adr_stride2;
int stride2x2 = 0x40;
- Address::ScaleFactor scale, scale1, scale2;
+ Address::ScaleFactor scale = Address::no_scale;
+ Address::ScaleFactor scale1 = Address::no_scale;
+ Address::ScaleFactor scale2 = Address::no_scale;
if (ae != StrIntrinsicNode::LL) {
stride2x2 = 0x20;
@@ -7894,9 +7896,9 @@
stride = 8;
}
} else {
- scale = Address::no_scale; // not used
scale1 = Address::times_1;
scale2 = Address::times_2;
+ // scale not used
stride = 8;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/macroAssembler.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_x86.inline.hpp"
+#ifdef COMPILER1
+#include "c1/c1_Runtime1.hpp"
+#endif //COMPILER1
+
+#define __ masm->
+
+#ifdef COMPILER1
+// ---------------------------------------------------------------------------
+// Object.hashCode, System.identityHashCode can pull the hashCode from the
+// header word instead of doing a full VM transition once it's been computed.
+// Since hashCode is usually polymorphic at call sites we can't do this
+// optimization at the call site without a lot of work.
+void SharedRuntime::inline_check_hashcode_from_object_header(MacroAssembler* masm,
+ methodHandle method,
+ Register obj_reg,
+ Register result) {
+ Label slowCase;
+
+ // Unlike for Object.hashCode, System.identityHashCode is static method and
+ // gets object as argument instead of the receiver.
+ if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) {
+ Label Continue;
+ // return 0 for null reference input
+ __ cmpptr(obj_reg, (int32_t)NULL_WORD);
+ __ jcc(Assembler::notEqual, Continue);
+ __ xorptr(result, result);
+ __ ret(0);
+ __ bind(Continue);
+ }
+
+ __ movptr(result, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
+
+ // check if locked
+ __ testptr(result, markOopDesc::unlocked_value);
+ __ jcc(Assembler::zero, slowCase);
+
+ if (UseBiasedLocking) {
+ // Check if biased and fall through to runtime if so
+ __ testptr(result, markOopDesc::biased_lock_bit_in_place);
+ __ jcc(Assembler::notZero, slowCase);
+ }
+
+ // get hash
+#ifdef _LP64
+ // Read the header and build a mask to get its hash field.
+ // Depend on hash_mask being at most 32 bits and avoid the use of hash_mask_in_place
+ // because it could be larger than 32 bits in a 64-bit vm. See markOop.hpp.
+ __ shrptr(result, markOopDesc::hash_shift);
+ __ andptr(result, markOopDesc::hash_mask);
+#else
+ __ andptr(result, markOopDesc::hash_mask_in_place);
+#endif //_LP64
+
+ // test if hashCode exists
+ __ jcc(Assembler::zero, slowCase);
+#ifndef _LP64
+ __ shrptr(result, markOopDesc::hash_shift);
+#endif
+ __ ret(0);
+ __ bind(slowCase);
+}
+#endif //COMPILER1
+
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1754,34 +1754,10 @@
int vep_offset = ((intptr_t)__ pc()) - start;
#ifdef COMPILER1
- if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) {
- // Object.hashCode can pull the hashCode from the header word
- // instead of doing a full VM transition once it's been computed.
- // Since hashCode is usually polymorphic at call sites we can't do
- // this optimization at the call site without a lot of work.
- Label slowCase;
- Register receiver = rcx;
- Register result = rax;
- __ movptr(result, Address(receiver, oopDesc::mark_offset_in_bytes()));
-
- // check if locked
- __ testptr(result, markOopDesc::unlocked_value);
- __ jcc (Assembler::zero, slowCase);
-
- if (UseBiasedLocking) {
- // Check if biased and fall through to runtime if so
- __ testptr(result, markOopDesc::biased_lock_bit_in_place);
- __ jcc (Assembler::notZero, slowCase);
- }
-
- // get hash
- __ andptr(result, markOopDesc::hash_mask_in_place);
- // test if hashCode exists
- __ jcc (Assembler::zero, slowCase);
- __ shrptr(result, markOopDesc::hash_shift);
- __ ret(0);
- __ bind (slowCase);
- }
+ // For Object.hashCode, System.identityHashCode try to pull hashCode from object header if available.
+ if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
+ inline_check_hashcode_from_object_header(masm, method, rcx /*obj_reg*/, rax /*result*/);
+ }
#endif // COMPILER1
// The instruction at the verified entry point must be 5 bytes or longer
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -2058,6 +2058,13 @@
int vep_offset = ((intptr_t)__ pc()) - start;
+#ifdef COMPILER1
+ // For Object.hashCode, System.identityHashCode try to pull hashCode from object header if available.
+ if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
+ inline_check_hashcode_from_object_header(masm, method, j_rarg0 /*obj_reg*/, rax /*result*/);
+ }
+#endif // COMPILER1
+
// The instruction at the verified entry point must be 5 bytes or longer
// because it can be patched on the fly by make_non_entrant. The stack bang
// instruction fits that requirement.
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -32,7 +32,6 @@
// Set the default values for platform dependent flags used by the
// runtime system. See globals.hpp for details of what they do.
-define_pd_global(bool, ConvertSleepToYield, true);
define_pd_global(bool, ShareVtableStubs, true);
define_pd_global(bool, NeedsDeoptSuspend, false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/G1HeapRegionType.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, 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.gc.shared;
+
+//These definitions should be kept in sync with the definitions in the HotSpot code.
+
+public enum G1HeapRegionType {
+ Free ("Free"),
+ Eden ("Eden"),
+ Survivor ("Survivor"),
+ StartsHumongous ("Starts Humongous"),
+ ContinuesHumongous ("Continues Humongous"),
+ Old ("Old"),
+ Archive ("Archive"),
+ G1HeapRegionTypeEndSentinel ("G1HeapRegionTypeEndSentinel");
+
+ private final String value;
+
+ G1HeapRegionType(String val) {
+ this.value = val;
+ }
+ public String value() {
+ return value;
+ }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java Sat Mar 05 20:46:44 2016 -0800
@@ -70,56 +70,64 @@
public static final Register r28 = new Register(28, 28, "r28", CPU);
public static final Register r29 = new Register(29, 29, "r29", CPU);
public static final Register r30 = new Register(30, 30, "r30", CPU);
+
+ /*
+ * r31 is not a general purpose register, but represents either the stackpointer or the
+ * zero/discard register depending on the instruction. So we represent those two uses as two
+ * different registers. The register numbers are kept in sync with register_aarch64.hpp and have
+ * to be sequential, hence we also need a general r31 register here, which is never used.
+ */
public static final Register r31 = new Register(31, 31, "r31", CPU);
+ public static final Register zr = new Register(32, 31, "zr", CPU);
+ public static final Register sp = new Register(33, 31, "sp", CPU);
public static final Register lr = r30;
- public static final Register zr = r31;
- public static final Register sp = r31;
// @formatter:off
public static final Register[] cpuRegisters = {
r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15,
r16, r17, r18, r19, r20, r21, r22, r23,
- r24, r25, r26, r27, r28, r29, r30, r31
+ r24, r25, r26, r27, r28, r29, r30, r31,
+ zr, sp
};
// @formatter:on
public static final RegisterCategory SIMD = new RegisterCategory("SIMD");
// Simd registers
- public static final Register v0 = new Register(32, 0, "v0", SIMD);
- public static final Register v1 = new Register(33, 1, "v1", SIMD);
- public static final Register v2 = new Register(34, 2, "v2", SIMD);
- public static final Register v3 = new Register(35, 3, "v3", SIMD);
- public static final Register v4 = new Register(36, 4, "v4", SIMD);
- public static final Register v5 = new Register(37, 5, "v5", SIMD);
- public static final Register v6 = new Register(38, 6, "v6", SIMD);
- public static final Register v7 = new Register(39, 7, "v7", SIMD);
- public static final Register v8 = new Register(40, 8, "v8", SIMD);
- public static final Register v9 = new Register(41, 9, "v9", SIMD);
- public static final Register v10 = new Register(42, 10, "v10", SIMD);
- public static final Register v11 = new Register(43, 11, "v11", SIMD);
- public static final Register v12 = new Register(44, 12, "v12", SIMD);
- public static final Register v13 = new Register(45, 13, "v13", SIMD);
- public static final Register v14 = new Register(46, 14, "v14", SIMD);
- public static final Register v15 = new Register(47, 15, "v15", SIMD);
- public static final Register v16 = new Register(48, 16, "v16", SIMD);
- public static final Register v17 = new Register(49, 17, "v17", SIMD);
- public static final Register v18 = new Register(50, 18, "v18", SIMD);
- public static final Register v19 = new Register(51, 19, "v19", SIMD);
- public static final Register v20 = new Register(52, 20, "v20", SIMD);
- public static final Register v21 = new Register(53, 21, "v21", SIMD);
- public static final Register v22 = new Register(54, 22, "v22", SIMD);
- public static final Register v23 = new Register(55, 23, "v23", SIMD);
- public static final Register v24 = new Register(56, 24, "v24", SIMD);
- public static final Register v25 = new Register(57, 25, "v25", SIMD);
- public static final Register v26 = new Register(58, 26, "v26", SIMD);
- public static final Register v27 = new Register(59, 27, "v27", SIMD);
- public static final Register v28 = new Register(60, 28, "v28", SIMD);
- public static final Register v29 = new Register(61, 29, "v29", SIMD);
- public static final Register v30 = new Register(62, 30, "v30", SIMD);
- public static final Register v31 = new Register(63, 31, "v31", SIMD);
+ public static final Register v0 = new Register(34, 0, "v0", SIMD);
+ public static final Register v1 = new Register(35, 1, "v1", SIMD);
+ public static final Register v2 = new Register(36, 2, "v2", SIMD);
+ public static final Register v3 = new Register(37, 3, "v3", SIMD);
+ public static final Register v4 = new Register(38, 4, "v4", SIMD);
+ public static final Register v5 = new Register(39, 5, "v5", SIMD);
+ public static final Register v6 = new Register(40, 6, "v6", SIMD);
+ public static final Register v7 = new Register(41, 7, "v7", SIMD);
+ public static final Register v8 = new Register(42, 8, "v8", SIMD);
+ public static final Register v9 = new Register(43, 9, "v9", SIMD);
+ public static final Register v10 = new Register(44, 10, "v10", SIMD);
+ public static final Register v11 = new Register(45, 11, "v11", SIMD);
+ public static final Register v12 = new Register(46, 12, "v12", SIMD);
+ public static final Register v13 = new Register(47, 13, "v13", SIMD);
+ public static final Register v14 = new Register(48, 14, "v14", SIMD);
+ public static final Register v15 = new Register(49, 15, "v15", SIMD);
+ public static final Register v16 = new Register(50, 16, "v16", SIMD);
+ public static final Register v17 = new Register(51, 17, "v17", SIMD);
+ public static final Register v18 = new Register(52, 18, "v18", SIMD);
+ public static final Register v19 = new Register(53, 19, "v19", SIMD);
+ public static final Register v20 = new Register(54, 20, "v20", SIMD);
+ public static final Register v21 = new Register(55, 21, "v21", SIMD);
+ public static final Register v22 = new Register(56, 22, "v22", SIMD);
+ public static final Register v23 = new Register(57, 23, "v23", SIMD);
+ public static final Register v24 = new Register(58, 24, "v24", SIMD);
+ public static final Register v25 = new Register(59, 25, "v25", SIMD);
+ public static final Register v26 = new Register(60, 26, "v26", SIMD);
+ public static final Register v27 = new Register(61, 27, "v27", SIMD);
+ public static final Register v28 = new Register(62, 28, "v28", SIMD);
+ public static final Register v29 = new Register(63, 29, "v29", SIMD);
+ public static final Register v30 = new Register(64, 30, "v30", SIMD);
+ public static final Register v31 = new Register(65, 31, "v31", SIMD);
// @formatter:off
public static final Register[] simdRegisters = {
@@ -136,6 +144,7 @@
r8, r9, r10, r11, r12, r13, r14, r15,
r16, r17, r18, r19, r20, r21, r22, r23,
r24, r25, r26, r27, r28, r29, r30, r31,
+ zr, sp,
v0, v1, v2, v3, v4, v5, v6, v7,
v8, v9, v10, v11, v12, v13, v14, v15,
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java Sat Mar 05 20:46:44 2016 -0800
@@ -31,6 +31,7 @@
import static jdk.vm.ci.aarch64.AArch64.r28;
import static jdk.vm.ci.aarch64.AArch64.r29;
import static jdk.vm.ci.aarch64.AArch64.r3;
+import static jdk.vm.ci.aarch64.AArch64.r31;
import static jdk.vm.ci.aarch64.AArch64.r4;
import static jdk.vm.ci.aarch64.AArch64.r5;
import static jdk.vm.ci.aarch64.AArch64.r6;
@@ -45,11 +46,13 @@
import static jdk.vm.ci.aarch64.AArch64.v5;
import static jdk.vm.ci.aarch64.AArch64.v6;
import static jdk.vm.ci.aarch64.AArch64.v7;
+import static jdk.vm.ci.aarch64.AArch64.zr;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import jdk.vm.ci.aarch64.AArch64;
@@ -130,16 +133,20 @@
public static final Register threadRegister = r28;
public static final Register fp = r29;
+ private static final Register[] reservedRegisters = {threadRegister, fp, lr, r31, zr, sp};
+
private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
Register[] allRegisters = arch.getAvailableValueRegisters();
- Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 5 : 4)];
+ Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
+ List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
int idx = 0;
for (Register reg : allRegisters) {
- if (reg.equals(threadRegister) || reg.equals(fp) || reg.equals(lr) || reg.equals(sp)) {
- // skip thread register, frame pointer, link register and stack pointer
+ if (reservedRegistersList.contains(reg)) {
+ // skip reserved registers
continue;
}
+ assert !(reg.equals(threadRegister) || reg.equals(fp) || reg.equals(lr) || reg.equals(r31) || reg.equals(zr) || reg.equals(sp));
if (reserveForHeapBase && reg.equals(heapBaseRegister)) {
// skip heap base register
continue;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java Sat Mar 05 20:46:44 2016 -0800
@@ -45,6 +45,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import jdk.vm.ci.code.Architecture;
@@ -119,14 +120,17 @@
*/
private final boolean needsNativeStackHomeSpace;
+ private static final Register[] reservedRegisters = {rsp, r15};
+
private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
Register[] allRegisters = arch.getAvailableValueRegisters();
- Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 3 : 2)];
+ Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
+ List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
int idx = 0;
for (Register reg : allRegisters) {
- if (reg.equals(rsp) || reg.equals(r15)) {
- // skip stack pointer and thread register
+ if (reservedRegistersList.contains(reg)) {
+ // skip reserved registers
continue;
}
if (reserveForHeapBase && reg.equals(r12)) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java Sat Mar 05 20:46:44 2016 -0800
@@ -68,6 +68,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CallingConvention;
@@ -140,14 +141,17 @@
i0, i1, i2, i3, i4, i5, i6, i7};
// @formatter:on
+ private static final Register[] reservedRegisters = {sp, g0, g2};
+
private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
Register[] allRegisters = arch.getAvailableValueRegisters();
- Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 4 : 3)];
+ Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
+ List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
int idx = 0;
for (Register reg : allRegisters) {
- if (reg.equals(sp) || reg.equals(g2) || reg.equals(g0)) {
- // skip g0, stack pointer and thread register
+ if (reservedRegistersList.contains(reg)) {
+ // skip reserved registers
continue;
}
if (reserveForHeapBase && reg.equals(g6)) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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 @@
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
import java.lang.reflect.Array;
+import java.util.Objects;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
@@ -70,13 +71,13 @@
} else if (x instanceof HotSpotObjectConstantImpl) {
return y instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) x).object() == ((HotSpotObjectConstantImpl) y).object();
} else {
- return x.equals(y);
+ return Objects.equals(x, y);
}
}
@Override
public Integer readArrayLength(JavaConstant array) {
- if (array.getJavaKind() != JavaKind.Object || array.isNull()) {
+ if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) {
return null;
}
@@ -133,12 +134,12 @@
@Override
public JavaConstant readArrayElement(JavaConstant array, int index) {
- if (array.getJavaKind() != JavaKind.Object || array.isNull()) {
+ if (array == null || array.getJavaKind() != JavaKind.Object || array.isNull()) {
return null;
}
Object a = ((HotSpotObjectConstantImpl) array).object();
- if (index < 0 || index >= Array.getLength(a)) {
+ if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) {
return null;
}
@@ -184,7 +185,7 @@
@Override
public JavaConstant boxPrimitive(JavaConstant source) {
- if (!source.getJavaKind().isPrimitive() || !isBoxCached(source)) {
+ if (source == null || !source.getJavaKind().isPrimitive() || !isBoxCached(source)) {
return null;
}
return HotSpotObjectConstantImpl.forObject(source.asBoxedPrimitive());
@@ -192,7 +193,7 @@
@Override
public JavaConstant unboxPrimitive(JavaConstant source) {
- if (!source.getJavaKind().isObject()) {
+ if (source == null || !source.getJavaKind().isObject()) {
return null;
}
if (source.isNull()) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java Sat Mar 05 20:46:44 2016 -0800
@@ -57,6 +57,13 @@
boolean isDontInline();
/**
+ * Returns true if this method has a {@code ReservedStackAccess} annotation.
+ *
+ * @return true if ReservedStackAccess annotation present, false otherwise
+ */
+ boolean hasReservedStackAccess();
+
+ /**
* Manually adds a DontInline annotation to this method.
*/
void setNotInlineable();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -309,6 +309,15 @@
}
/**
+ * Returns true if this method has a {@code ReservedStackAccess} annotation.
+ *
+ * @return true if ReservedStackAccess annotation present, false otherwise
+ */
+ public boolean hasReservedStackAccess() {
+ return (getFlags() & config().methodFlagsReservedStackAccess) != 0;
+ }
+
+ /**
* Manually adds a DontInline annotation to this method.
*/
public void setNotInlineable() {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Sat Mar 05 20:46:44 2016 -0800
@@ -850,6 +850,7 @@
@HotSpotVMFlag(name = "DontCompileHugeMethods") @Stable public boolean dontCompileHugeMethods;
@HotSpotVMFlag(name = "HugeMethodLimit") @Stable public int hugeMethodLimit;
@HotSpotVMFlag(name = "PrintInlining") @Stable public boolean printInlining;
+ @HotSpotVMFlag(name = "Inline") @Stable public boolean inline;
@HotSpotVMFlag(name = "JVMCIUseFastLocking") @Stable public boolean useFastLocking;
@HotSpotVMFlag(name = "ForceUnreachable") @Stable public boolean forceUnreachable;
@HotSpotVMFlag(name = "CodeCacheSegmentSize") @Stable public int codeSegmentSize;
@@ -974,6 +975,7 @@
@HotSpotVMFlag(name = "BlockZeroingLowLimit", archs = {"sparc"}) @Stable public int blockZeroingLowLimit;
@HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages;
+ @HotSpotVMFlag(name = "StackReservedPages") @Stable public int stackReservedPages;
@HotSpotVMFlag(name = "UseStackBanging") @Stable public boolean useStackBanging;
@HotSpotVMConstant(name = "STACK_BIAS") @Stable public int stackBias;
@HotSpotVMField(name = "CompilerToVM::Data::vm_page_size", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int vmPageSize;
@@ -1092,6 +1094,7 @@
@HotSpotVMField(name = "JavaThread::_satb_mark_queue", type = "SATBMarkQueue", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadSatbMarkQueueOffset;
@HotSpotVMField(name = "JavaThread::_vm_result", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset;
@HotSpotVMField(name = "JavaThread::_jvmci_counters", type = "jlong*", get = HotSpotVMField.Type.OFFSET) @Stable public int jvmciCountersThreadOffset;
+ @HotSpotVMField(name = "JavaThread::_reserved_stack_activation", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable public int javaThreadReservedStackActivationOffset;
/**
* An invalid value for {@link #rtldDefault}.
@@ -1235,6 +1238,7 @@
@HotSpotVMConstant(name = "Method::_force_inline") @Stable public int methodFlagsForceInline;
@HotSpotVMConstant(name = "Method::_dont_inline") @Stable public int methodFlagsDontInline;
@HotSpotVMConstant(name = "Method::_hidden") @Stable public int methodFlagsHidden;
+ @HotSpotVMConstant(name = "Method::_reserved_stack_access") @Stable public int methodFlagsReservedStackAccess;
@HotSpotVMConstant(name = "Method::nonvirtual_vtable_index") @Stable public int nonvirtualVtableIndex;
@HotSpotVMConstant(name = "Method::invalid_vtable_index") @Stable public int invalidVtableIndex;
@@ -1491,6 +1495,8 @@
@HotSpotVMField(name = "StubRoutines::_updateBytesCRC32", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long updateBytesCRC32Stub;
@HotSpotVMField(name = "StubRoutines::_crc_table_adr", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long crcTableAddress;
+ @HotSpotVMField(name = "StubRoutines::_throw_delayed_StackOverflowError_entry", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long throwDelayedStackOverflowErrorEntry;
+
@HotSpotVMField(name = "StubRoutines::_jbyte_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jbyteArraycopy;
@HotSpotVMField(name = "StubRoutines::_jshort_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jshortArraycopy;
@HotSpotVMField(name = "StubRoutines::_jint_arraycopy", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long jintArraycopy;
@@ -1548,6 +1554,7 @@
@HotSpotVMAddress(name = "SharedRuntime::register_finalizer") @Stable public long registerFinalizerAddress;
@HotSpotVMAddress(name = "SharedRuntime::exception_handler_for_return_address") @Stable public long exceptionHandlerForReturnAddressAddress;
@HotSpotVMAddress(name = "SharedRuntime::OSR_migration_end") @Stable public long osrMigrationEndAddress;
+ @HotSpotVMAddress(name = "SharedRuntime::enable_stack_reserved_zone") @Stable public long enableStackReservedZoneAddress;
@HotSpotVMAddress(name = "os::javaTimeMillis") @Stable public long javaTimeMillisAddress;
@HotSpotVMAddress(name = "os::javaTimeNanos") @Stable public long javaTimeNanosAddress;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.services/.checkstyle_checks.xml Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+ Checkstyle-Configuration: Checks
+ Description: none
+-->
+<module name="Checker">
+ <property name="severity" value="error"/>
+ <module name="TreeWalker">
+ <property name="tabWidth" value="4"/>
+ <module name="FileContentsHolder"/>
+ <module name="JavadocStyle">
+ <property name="checkHtml" value="false"/>
+ </module>
+ <module name="LocalFinalVariableName"/>
+ <module name="LocalVariableName"/>
+ <module name="MemberName">
+ <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+ </module>
+ <module name="MethodName"/>
+ <module name="PackageName"/>
+ <module name="ParameterName"/>
+ <module name="TypeName">
+ <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+ </module>
+ <module name="RedundantImport"/>
+ <module name="LineLength">
+ <property name="max" value="250"/>
+ </module>
+ <module name="MethodParamPad"/>
+ <module name="NoWhitespaceAfter">
+ <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+ </module>
+ <module name="AvoidStarImport">
+ <property name="allowClassImports" value="false"/>
+ <property name="allowStaticMemberImports" value="false"/>
+ </module>
+ <module name="NoWhitespaceBefore">
+ <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+ </module>
+ <module name="ParenPad"/>
+ <module name="TypecastParenPad">
+ <property name="tokens" value="RPAREN,TYPECAST"/>
+ </module>
+ <module name="WhitespaceAfter"/>
+ <module name="WhitespaceAround">
+ <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+ </module>
+ <module name="RedundantModifier"/>
+ <module name="AvoidNestedBlocks">
+ <property name="allowInSwitchCase" value="true"/>
+ </module>
+ <module name="EmptyBlock">
+ <property name="option" value="text"/>
+ <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+ </module>
+ <module name="LeftCurly"/>
+ <module name="NeedBraces"/>
+ <module name="RightCurly"/>
+ <module name="EmptyStatement"/>
+ <module name="HiddenField">
+ <property name="severity" value="ignore"/>
+ <property name="ignoreConstructorParameter" value="true"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="FinalClass"/>
+ <module name="HideUtilityClassConstructor">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ArrayTypeStyle"/>
+ <module name="UpperEll"/>
+ <module name="FallThrough"/>
+ <module name="FinalLocalVariable">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="MultipleVariableDeclarations"/>
+ <module name="StringLiteralEquality">
+ <property name="severity" value="error"/>
+ </module>
+ <module name="SuperFinalize"/>
+ <module name="UnnecessaryParentheses">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="Indentation">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="StaticVariableName">
+ <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+ </module>
+ <module name="EmptyForInitializerPad"/>
+ <module name="EmptyForIteratorPad"/>
+ <module name="ModifierOrder"/>
+ <module name="DefaultComesLast"/>
+ <module name="InnerAssignment">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ModifiedControlVariable"/>
+ <module name="MutableException">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ParameterAssignment">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
+ <property name="format" value="\s$"/>
+ <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+ <property name="ignoreComments" value="true"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
+ <property name="format" value=" ,"/>
+ <property name="message" value="illegal space before a comma"/>
+ <property name="ignoreComments" value="true"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="[^\x00-\x7F]"/>
+ <property name="message" value="Only use ASCII characters."/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
+ <property name="message" value="Don't use old synchronized collection classes"/>
+ </module>
+ </module>
+ <module name="RegexpHeader">
+ <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+ <property name="fileExtensions" value="java"/>
+ </module>
+ <module name="FileTabCharacter">
+ <property name="severity" value="error"/>
+ <property name="fileExtensions" value="java"/>
+ </module>
+ <module name="NewlineAtEndOfFile">
+ <property name="lineSeparator" value="lf"/>
+ </module>
+ <module name="Translation"/>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+ <property name="checkFormat" value="ConstantNameCheck"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+ <property name="checkFormat" value="MethodName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+ <property name="checkFormat" value="ParameterAssignment"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+ <property name="checkFormat" value="FinalLocalVariable"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop"/>
+ <property name="onCommentFormat" value="Checkstyle: resume"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+ <property name="checkFormat" value="InnerAssignment"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+ <property name="checkFormat" value="MemberName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+ </module>
+ <module name="RegexpMultiline">
+ <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
+ <property name="format" value="\r\n"/>
+ <property name="message" value="illegal Windows line ending"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+ <property name="checkFormat" value=".*Header"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
+ <property name="checkFormat" value="LineLength"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: start generated"/>
+ <property name="onCommentFormat" value="CheckStyle: stop generated"/>
+ <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
+ </module>
+</module>
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -4042,61 +4042,6 @@
// 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.
-// For specifics regarding the bug see GLIBC BUGID 261237 :
-// http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html.
-// Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future
-// will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar
-// is used. (The simple C test-case provided in the GLIBC bug report manifests the
-// hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos()
-// and monitorenter when we're using 1-0 locking. All those operations may result in
-// calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version
-// of libpthread avoids the problem, but isn't practical.
-//
-// Possible remedies:
-//
-// 1. Establish a minimum relative wait time. 50 to 100 msecs seems to work.
-// This is palliative and probabilistic, however. If the thread is preempted
-// between the call to compute_abstime() and pthread_cond_timedwait(), more
-// than the minimum period may have passed, and the abstime may be stale (in the
-// past) resultin in a hang. Using this technique reduces the odds of a hang
-// but the JVM is still vulnerable, particularly on heavily loaded systems.
-//
-// 2. Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead
-// of the usual flag-condvar-mutex idiom. The write side of the pipe is set
-// NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo)
-// reduces to poll()+read(). This works well, but consumes 2 FDs per extant
-// thread.
-//
-// 3. Embargo pthread_cond_timedwait() and implement a native "chron" thread
-// that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing
-// a timeout request to the chron thread and then blocking via pthread_cond_wait().
-// This also works well. In fact it avoids kernel-level scalability impediments
-// on certain platforms that don't handle lots of active pthread_cond_timedwait()
-// timers in a graceful fashion.
-//
-// 4. When the abstime value is in the past it appears that control returns
-// correctly from pthread_cond_timedwait(), but the condvar is left corrupt.
-// Subsequent timedwait/wait calls may hang indefinitely. Given that, we
-// can avoid the problem by reinitializing the condvar -- by cond_destroy()
-// followed by cond_init() -- after all calls to pthread_cond_timedwait().
-// It may be possible to avoid reinitialization by checking the return
-// value from pthread_cond_timedwait(). In addition to reinitializing the
-// condvar we must establish the invariant that cond_signal() is only called
-// within critical sections protected by the adjunct mutex. This prevents
-// cond_signal() from "seeing" a condvar that's in the midst of being
-// reinitialized or that is corrupt. Sadly, this invariant obviates the
-// desirable signal-after-unlock optimization that avoids futile context switching.
-//
-// I'm also concerned that some versions of NTPL might allocate an auxilliary
-// structure when a condvar is used or initialized. cond_destroy() would
-// release the helper structure. Our reinitialize-after-timedwait fix
-// put excessive stress on malloc/free and locks protecting the c-heap.
-//
-// We currently use (4). See the WorkAroundNTPLTimedWaitHang flag.
-// It may be possible to refine (4) by checking the kernel and NTPL verisons
-// and only enabling the work-around for vulnerable environments.
// utility to compute the abstime argument to timedwait:
// millis is the relative timeout time
@@ -4208,10 +4153,6 @@
while (_Event < 0) {
status = pthread_cond_timedwait(_cond, _mutex, &abst);
- if (status != 0 && WorkAroundNPTLTimedWaitHang) {
- pthread_cond_destroy(_cond);
- pthread_cond_init(_cond, NULL);
- }
assert_status(status == 0 || status == EINTR ||
status == ETIMEDOUT,
status, "cond_timedwait");
@@ -4255,10 +4196,6 @@
assert_status(status == 0, status, "mutex_lock");
int AnyWaiters = _nParked;
assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
- if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
- AnyWaiters = 0;
- pthread_cond_signal(_cond);
- }
status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock");
if (AnyWaiters != 0) {
@@ -4391,7 +4328,7 @@
if (_counter > 0) { // no wait needed
_counter = 0;
status = pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
+ assert_status(status == 0, status, "invariant");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
@@ -4414,10 +4351,6 @@
status = pthread_cond_wait(_cond, _mutex);
} else {
status = pthread_cond_timedwait(_cond, _mutex, &absTime);
- if (status != 0 && WorkAroundNPTLTimedWaitHang) {
- pthread_cond_destroy(_cond);
- pthread_cond_init(_cond, NULL);
- }
}
assert_status(status == 0 || status == EINTR ||
status == ETIMEDOUT,
@@ -4442,24 +4375,14 @@
void Parker::unpark() {
int status = pthread_mutex_lock(_mutex);
- assert(status == 0, "invariant");
+ assert_status(status == 0, status, "invariant");
const int s = _counter;
_counter = 1;
+ status = pthread_mutex_unlock(_mutex);
+ assert_status(status == 0, status, "invariant");
if (s < 1) {
- if (WorkAroundNPTLTimedWaitHang) {
- status = pthread_cond_signal(_cond);
- assert(status == 0, "invariant");
- status = pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
- } else {
- status = pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
- status = pthread_cond_signal(_cond);
- assert(status == 0, "invariant");
- }
- } else {
- pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
+ status = pthread_cond_signal(_cond);
+ assert_status(status == 0, status, "invariant");
}
}
--- a/hotspot/src/os/linux/vm/os_linux.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -4771,6 +4771,25 @@
}
}
+// older glibc versions don't have this macro (which expands to
+// an optimized bit-counting function) so we have to roll our own
+#ifndef CPU_COUNT
+
+static int _cpu_count(const cpu_set_t* cpus) {
+ int count = 0;
+ // only look up to the number of configured processors
+ for (int i = 0; i < os::processor_count(); i++) {
+ if (CPU_ISSET(i, cpus)) {
+ count++;
+ }
+ }
+ return count;
+}
+
+#define CPU_COUNT(cpus) _cpu_count(cpus)
+
+#endif // CPU_COUNT
+
// Get the current number of available processors for this process.
// This value can change at any time during a process's lifetime.
// sched_getaffinity gives an accurate answer as it accounts for cpusets.
@@ -4786,6 +4805,9 @@
int configured_cpus = processor_count(); // upper bound on available cpus
int cpu_count = 0;
+// old build platforms may not support dynamic cpu sets
+#ifdef CPU_ALLOC
+
// To enable easy testing of the dynamic path on different platforms we
// introduce a diagnostic flag: UseCpuAllocPath
if (configured_cpus >= CPU_SETSIZE || UseCpuAllocPath) {
@@ -4814,10 +4836,18 @@
log_trace(os)("active_processor_count: using static path - configured processors: %d",
configured_cpus);
}
+#else // CPU_ALLOC
+// these stubs won't be executed
+#define CPU_COUNT_S(size, cpus) -1
+#define CPU_FREE(cpus)
+
+ log_trace(os)("active_processor_count: only static path available - configured processors: %d",
+ configured_cpus);
+#endif // CPU_ALLOC
// pid 0 means the current thread - which we have to assume represents the process
if (sched_getaffinity(0, cpus_size, cpus_p) == 0) {
- if (cpus_p != &cpus) {
+ if (cpus_p != &cpus) { // can only be true when CPU_ALLOC used
cpu_count = CPU_COUNT_S(cpus_size, cpus_p);
}
else {
@@ -4831,7 +4861,7 @@
"which may exceed available processors", strerror(errno), cpu_count);
}
- if (cpus_p != &cpus) {
+ if (cpus_p != &cpus) { // can only be true when CPU_ALLOC used
CPU_FREE(cpus_p);
}
@@ -5349,61 +5379,6 @@
// 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.
-// For specifics regarding the bug see GLIBC BUGID 261237 :
-// http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html.
-// Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future
-// will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar
-// is used. (The simple C test-case provided in the GLIBC bug report manifests the
-// hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos()
-// and monitorenter when we're using 1-0 locking. All those operations may result in
-// calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version
-// of libpthread avoids the problem, but isn't practical.
-//
-// Possible remedies:
-//
-// 1. Establish a minimum relative wait time. 50 to 100 msecs seems to work.
-// This is palliative and probabilistic, however. If the thread is preempted
-// between the call to compute_abstime() and pthread_cond_timedwait(), more
-// than the minimum period may have passed, and the abstime may be stale (in the
-// past) resultin in a hang. Using this technique reduces the odds of a hang
-// but the JVM is still vulnerable, particularly on heavily loaded systems.
-//
-// 2. Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead
-// of the usual flag-condvar-mutex idiom. The write side of the pipe is set
-// NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo)
-// reduces to poll()+read(). This works well, but consumes 2 FDs per extant
-// thread.
-//
-// 3. Embargo pthread_cond_timedwait() and implement a native "chron" thread
-// that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing
-// a timeout request to the chron thread and then blocking via pthread_cond_wait().
-// This also works well. In fact it avoids kernel-level scalability impediments
-// on certain platforms that don't handle lots of active pthread_cond_timedwait()
-// timers in a graceful fashion.
-//
-// 4. When the abstime value is in the past it appears that control returns
-// correctly from pthread_cond_timedwait(), but the condvar is left corrupt.
-// Subsequent timedwait/wait calls may hang indefinitely. Given that, we
-// can avoid the problem by reinitializing the condvar -- by cond_destroy()
-// followed by cond_init() -- after all calls to pthread_cond_timedwait().
-// It may be possible to avoid reinitialization by checking the return
-// value from pthread_cond_timedwait(). In addition to reinitializing the
-// condvar we must establish the invariant that cond_signal() is only called
-// within critical sections protected by the adjunct mutex. This prevents
-// cond_signal() from "seeing" a condvar that's in the midst of being
-// reinitialized or that is corrupt. Sadly, this invariant obviates the
-// desirable signal-after-unlock optimization that avoids futile context switching.
-//
-// I'm also concerned that some versions of NTPL might allocate an auxilliary
-// structure when a condvar is used or initialized. cond_destroy() would
-// release the helper structure. Our reinitialize-after-timedwait fix
-// put excessive stress on malloc/free and locks protecting the c-heap.
-//
-// We currently use (4). See the WorkAroundNTPLTimedWaitHang flag.
-// It may be possible to refine (4) by checking the kernel and NTPL verisons
-// and only enabling the work-around for vulnerable environments.
// utility to compute the abstime argument to timedwait:
// millis is the relative timeout time
@@ -5529,10 +5504,6 @@
while (_Event < 0) {
status = pthread_cond_timedwait(_cond, _mutex, &abst);
- if (status != 0 && WorkAroundNPTLTimedWaitHang) {
- pthread_cond_destroy(_cond);
- pthread_cond_init(_cond, os::Linux::condAttr());
- }
assert_status(status == 0 || status == EINTR ||
status == ETIME || status == ETIMEDOUT,
status, "cond_timedwait");
@@ -5576,10 +5547,6 @@
assert_status(status == 0, status, "mutex_lock");
int AnyWaiters = _nParked;
assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
- if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
- AnyWaiters = 0;
- pthread_cond_signal(_cond);
- }
status = pthread_mutex_unlock(_mutex);
assert_status(status == 0, status, "mutex_unlock");
if (AnyWaiters != 0) {
@@ -5731,7 +5698,7 @@
if (_counter > 0) { // no wait needed
_counter = 0;
status = pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
+ assert_status(status == 0, status, "invariant");
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
@@ -5757,10 +5724,6 @@
} else {
_cur_index = isAbsolute ? ABS_INDEX : REL_INDEX;
status = pthread_cond_timedwait(&_cond[_cur_index], _mutex, &absTime);
- if (status != 0 && WorkAroundNPTLTimedWaitHang) {
- pthread_cond_destroy(&_cond[_cur_index]);
- pthread_cond_init(&_cond[_cur_index], isAbsolute ? NULL : os::Linux::condAttr());
- }
}
_cur_index = -1;
assert_status(status == 0 || status == EINTR ||
@@ -5786,33 +5749,17 @@
void Parker::unpark() {
int status = pthread_mutex_lock(_mutex);
- assert(status == 0, "invariant");
+ assert_status(status == 0, status, "invariant");
const int s = _counter;
_counter = 1;
- if (s < 1) {
- // thread might be parked
- if (_cur_index != -1) {
- // thread is definitely parked
- if (WorkAroundNPTLTimedWaitHang) {
- status = pthread_cond_signal(&_cond[_cur_index]);
- assert(status == 0, "invariant");
- status = pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
- } else {
- // must capture correct index before unlocking
- int index = _cur_index;
- status = pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
- status = pthread_cond_signal(&_cond[index]);
- assert(status == 0, "invariant");
- }
- } else {
- pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
- }
- } else {
- pthread_mutex_unlock(_mutex);
- assert(status == 0, "invariant");
+ // must capture correct index before unlocking
+ int index = _cur_index;
+ status = pthread_mutex_unlock(_mutex);
+ assert_status(status == 0, status, "invariant");
+ if (s < 1 && index != -1) {
+ // thread is definitely parked
+ status = pthread_cond_signal(&_cond[index]);
+ assert_status(status == 0, status, "invariant");
}
}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -246,7 +246,6 @@
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()) {
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -730,7 +730,7 @@
}
} else if (rt == objectNull &&
(l->as_NewInstance() || l->as_NewArray() ||
- (UseNewCode && l->as_Local() && l->as_Local()->is_receiver()))) {
+ (l->as_Local() && l->as_Local()->is_receiver()))) {
if (x->cond() == Instruction::eql) {
BlockBegin* sux = x->fsux();
set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
--- a/hotspot/src/share/vm/ci/ciField.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/ci/ciField.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -211,6 +211,12 @@
// so there is no hacking of finals going on with them.
if (holder->is_anonymous())
return true;
+ // Trust final fields in all boxed classes
+ if (holder->is_box_klass())
+ return true;
+ // Trust final fields in String
+ if (holder->name() == ciSymbol::java_lang_String())
+ return true;
// Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
// more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
--- a/hotspot/src/share/vm/code/codeBlob.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -291,6 +291,9 @@
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) MethodHandlesAdapterBlob(size);
+ if (blob == NULL) {
+ vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "CodeCache: no room for method handle adapter blob");
+ }
}
// Track memory usage statistic after releasing CodeCache_lock
MemoryService::track_code_cache_memory_usage();
--- a/hotspot/src/share/vm/code/nmethod.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/code/nmethod.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -33,6 +33,7 @@
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compilerDirectives.hpp"
+#include "compiler/directivesParser.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/bytecode.hpp"
#include "oops/methodData.hpp"
@@ -965,6 +966,12 @@
}
}
+void nmethod::maybe_print_nmethod(DirectiveSet* directive) {
+ bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
+ if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
+ print_nmethod(printnmethods);
+ }
+}
void nmethod::print_nmethod(bool printmethod) {
ttyLocker ttyl; // keep the following output all in one block
--- a/hotspot/src/share/vm/code/nmethod.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/code/nmethod.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -29,6 +29,8 @@
#include "code/pcDesc.hpp"
#include "oops/metadata.hpp"
+class DirectiveSet;
+
// This class is used internally by nmethods, to cache
// exception/pc/handler information.
@@ -714,6 +716,8 @@
void print_nul_chk_table() PRODUCT_RETURN;
void print_recorded_oops() PRODUCT_RETURN;
void print_recorded_metadata() PRODUCT_RETURN;
+
+ void maybe_print_nmethod(DirectiveSet* directive);
void print_nmethod(bool print_code);
// need to re-define this from CodeBlob else the overload hides it
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1919,12 +1919,9 @@
collect_statistics(thread, time, task);
- bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
- if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
- nmethod* nm = task->code();
- if (nm != NULL) {
- nm->print_nmethod(printnmethods);
- }
+ nmethod* nm = task->code();
+ if (nm != NULL) {
+ nm->maybe_print_nmethod(directive);
}
DirectivesStack::release(directive);
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -2206,13 +2206,13 @@
}
if (res == 0) {
LogHandle(gc, verify) log;
- log.info("Livelock: no rank reduction!");
- log.info(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n"
- " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n",
+ log.error("Livelock: no rank reduction!");
+ log.error(" Current: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n"
+ " Previous: addr = " PTR_FORMAT ", size = " SIZE_FORMAT ", obj = %s, live = %s \n",
p2i(addr), res, was_obj ?"true":"false", was_live ?"true":"false",
p2i(_last_addr), _last_size, _last_was_obj?"true":"false", _last_was_live?"true":"false");
ResourceMark rm;
- _sp->print_on(log.info_stream());
+ _sp->print_on(log.error_stream());
guarantee(false, "Verification failed.");
}
_last_addr = addr;
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -2224,8 +2224,8 @@
if (!_marks->isMarked(addr)) {
LogHandle(gc, verify) log;
ResourceMark rm;
- oop(addr)->print_on(log.info_stream());
- log.info(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
+ oop(addr)->print_on(log.error_stream());
+ log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
_failed = true;
}
return true;
@@ -2350,9 +2350,9 @@
verification_mark_bm()->iterate(&vcl);
if (vcl.failed()) {
LogHandle(gc, verify) log;
- log.info("Verification failed");
+ log.error("Failed marking verification after remark");
ResourceMark rm;
- gch->print_on(log.info_stream());
+ gch->print_on(log.error_stream());
fatal("CMS: failed marking verification after remark");
}
}
@@ -2923,7 +2923,7 @@
CMSTokenSyncWithLocks ts(true, bitMapLock());
GCTraceCPUTime tcpu;
- CMSPhaseAccounting pa(this, "Concrurrent Mark");
+ CMSPhaseAccounting pa(this, "Concurrent Mark");
bool res = markFromRootsWork();
if (res) {
_collectorState = Precleaning;
@@ -5880,8 +5880,8 @@
if (!_cms_bm->isMarked(addr)) {
LogHandle(gc, verify) log;
ResourceMark rm;
- oop(addr)->print_on(log.info_stream());
- log.info(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
+ oop(addr)->print_on(log.error_stream());
+ log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
fatal("... aborting");
}
}
@@ -6661,8 +6661,8 @@
if (!_cms_bm->isMarked(addr)) {
LogHandle(gc, verify) log;
ResourceMark rm;
- oop(addr)->print_on(log.info_stream());
- log.info(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
+ oop(addr)->print_on(log.error_stream());
+ log.error(" (" INTPTR_FORMAT " should have been marked)", p2i(addr));
fatal("... aborting");
}
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
#include "gc/g1/concurrentMarkThread.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
@@ -123,6 +124,7 @@
// wait until started is set.
sleepBeforeNextCycle();
if (_should_terminate) {
+ _cm->root_regions()->cancel_scan();
break;
}
@@ -132,6 +134,11 @@
HandleMark hm;
double cycle_start = os::elapsedVTime();
+ {
+ GCConcPhaseTimer(_cm, "Concurrent Clearing of Claimed Marks");
+ ClassLoaderDataGraph::clear_claimed_marks();
+ }
+
// We have to ensure that we finish scanning the root regions
// before the next GC takes place. To ensure this we have to
// make sure that we do not join the STS until the root regions
@@ -140,7 +147,7 @@
// without the root regions have been scanned which would be a
// correctness issue.
- if (!cm()->has_aborted()) {
+ {
GCConcPhaseTimer(_cm, "Concurrent Root Region Scanning");
_cm->scanRootRegions();
}
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1290,8 +1290,7 @@
ref_processor_cm()->verify_no_references_recorded();
// Abandon current iterations of concurrent marking and concurrent
- // refinement, if any are in progress. We have to do this before
- // wait_until_scan_finished() below.
+ // refinement, if any are in progress.
concurrent_mark()->abort();
// Make sure we'll choose a new allocation region afterwards.
@@ -2148,8 +2147,8 @@
virtual bool doHeapRegion(HeapRegion* hr) {
unsigned region_gc_time_stamp = hr->get_gc_time_stamp();
if (_gc_time_stamp != region_gc_time_stamp) {
- log_info(gc, verify)("Region " HR_FORMAT " has GC time stamp = %d, expected %d", HR_FORMAT_PARAMS(hr),
- region_gc_time_stamp, _gc_time_stamp);
+ log_error(gc, verify)("Region " HR_FORMAT " has GC time stamp = %d, expected %d", HR_FORMAT_PARAMS(hr),
+ region_gc_time_stamp, _gc_time_stamp);
_failures = true;
}
return false;
@@ -2848,7 +2847,7 @@
(g1_policy()->young_list_target_length() * HeapRegion::GrainBytes) - survivor_used_bytes;
VirtualSpaceSummary heap_summary = create_heap_space_summary();
- return G1HeapSummary(heap_summary, used(), eden_used_bytes, eden_capacity_bytes, survivor_used_bytes);
+ return G1HeapSummary(heap_summary, used(), eden_used_bytes, eden_capacity_bytes, survivor_used_bytes, num_regions());
}
G1EvacSummary G1CollectedHeap::create_g1_evac_summary(G1EvacStats* stats) {
@@ -5186,8 +5185,8 @@
NoYoungRegionsClosure() : _success(true) { }
bool doHeapRegion(HeapRegion* r) {
if (r->is_young()) {
- log_info(gc, verify)("Region [" PTR_FORMAT ", " PTR_FORMAT ") tagged as young",
- p2i(r->bottom()), p2i(r->end()));
+ log_error(gc, verify)("Region [" PTR_FORMAT ", " PTR_FORMAT ") tagged as young",
+ p2i(r->bottom()), p2i(r->end()));
_success = false;
}
return false;
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -293,29 +293,83 @@
_heap_alignment = MAX3(card_table_alignment, _space_alignment, page_size);
}
-void G1CollectorPolicy::initialize_flags() {
- if (G1HeapRegionSize != HeapRegion::GrainBytes) {
- FLAG_SET_ERGO(size_t, G1HeapRegionSize, HeapRegion::GrainBytes);
+G1CollectorState* G1CollectorPolicy::collector_state() const { return _g1->collector_state(); }
+
+// There are three command line options related to the young gen size:
+// NewSize, MaxNewSize and NewRatio (There is also -Xmn, but that is
+// just a short form for NewSize==MaxNewSize). G1 will use its internal
+// heuristics to calculate the actual young gen size, so these options
+// basically only limit the range within which G1 can pick a young gen
+// size. Also, these are general options taking byte sizes. G1 will
+// internally work with a number of regions instead. So, some rounding
+// will occur.
+//
+// If nothing related to the the young gen size is set on the command
+// line we should allow the young gen to be between G1NewSizePercent
+// and G1MaxNewSizePercent of the heap size. This means that every time
+// the heap size changes, the limits for the young gen size will be
+// recalculated.
+//
+// If only -XX:NewSize is set we should use the specified value as the
+// minimum size for young gen. Still using G1MaxNewSizePercent of the
+// heap as maximum.
+//
+// If only -XX:MaxNewSize is set we should use the specified value as the
+// maximum size for young gen. Still using G1NewSizePercent of the heap
+// as minimum.
+//
+// If -XX:NewSize and -XX:MaxNewSize are both specified we use these values.
+// No updates when the heap size changes. There is a special case when
+// NewSize==MaxNewSize. This is interpreted as "fixed" and will use a
+// different heuristic for calculating the collection set when we do mixed
+// collection.
+//
+// If only -XX:NewRatio is set we should use the specified ratio of the heap
+// as both min and max. This will be interpreted as "fixed" just like the
+// NewSize==MaxNewSize case above. But we will update the min and max
+// every time the heap size changes.
+//
+// NewSize and MaxNewSize override NewRatio. So, NewRatio is ignored if it is
+// combined with either NewSize or MaxNewSize. (A warning message is printed.)
+class G1YoungGenSizer : public CHeapObj<mtGC> {
+private:
+ enum SizerKind {
+ SizerDefaults,
+ SizerNewSizeOnly,
+ SizerMaxNewSizeOnly,
+ SizerMaxAndNewSize,
+ SizerNewRatio
+ };
+ SizerKind _sizer_kind;
+ uint _min_desired_young_length;
+ uint _max_desired_young_length;
+ bool _adaptive_size;
+ uint calculate_default_min_length(uint new_number_of_heap_regions);
+ uint calculate_default_max_length(uint new_number_of_heap_regions);
+
+ // Update the given values for minimum and maximum young gen length in regions
+ // given the number of heap regions depending on the kind of sizing algorithm.
+ void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length);
+
+public:
+ G1YoungGenSizer();
+ // Calculate the maximum length of the young gen given the number of regions
+ // depending on the sizing algorithm.
+ uint max_young_length(uint number_of_heap_regions);
+
+ void heap_size_changed(uint new_number_of_heap_regions);
+ uint min_desired_young_length() {
+ return _min_desired_young_length;
+ }
+ uint max_desired_young_length() {
+ return _max_desired_young_length;
}
- if (SurvivorRatio < 1) {
- vm_exit_during_initialization("Invalid survivor ratio specified");
+ bool adaptive_young_list_length() const {
+ return _adaptive_size;
}
- CollectorPolicy::initialize_flags();
- _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
-}
+};
-void G1CollectorPolicy::post_heap_initialize() {
- uintx max_regions = G1CollectedHeap::heap()->max_regions();
- size_t max_young_size = (size_t)_young_gen_sizer->max_young_length(max_regions) * HeapRegion::GrainBytes;
- if (max_young_size != MaxNewSize) {
- FLAG_SET_ERGO(size_t, MaxNewSize, max_young_size);
- }
-
- _ihop_control = create_ihop_control();
-}
-
-G1CollectorState* G1CollectorPolicy::collector_state() const { return _g1->collector_state(); }
G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true),
_min_desired_young_length(0), _max_desired_young_length(0) {
@@ -412,6 +466,29 @@
&_max_desired_young_length);
}
+void G1CollectorPolicy::post_heap_initialize() {
+ uintx max_regions = G1CollectedHeap::heap()->max_regions();
+ size_t max_young_size = (size_t)_young_gen_sizer->max_young_length(max_regions) * HeapRegion::GrainBytes;
+ if (max_young_size != MaxNewSize) {
+ FLAG_SET_ERGO(size_t, MaxNewSize, max_young_size);
+ }
+
+ _ihop_control = create_ihop_control();
+}
+
+void G1CollectorPolicy::initialize_flags() {
+ if (G1HeapRegionSize != HeapRegion::GrainBytes) {
+ FLAG_SET_ERGO(size_t, G1HeapRegionSize, HeapRegion::GrainBytes);
+ }
+
+ if (SurvivorRatio < 1) {
+ vm_exit_during_initialization("Invalid survivor ratio specified");
+ }
+ CollectorPolicy::initialize_flags();
+ _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
+}
+
+
void G1CollectorPolicy::init() {
// Set aside an initial future to_space.
_g1 = G1CollectedHeap::heap();
@@ -758,7 +835,7 @@
curr = curr->get_next_young_region()) {
SurvRateGroup* group = curr->surv_rate_group();
if (group == NULL && !curr->is_survivor()) {
- log_info(gc, verify)("## %s: encountered NULL surv_rate_group", name);
+ log_error(gc, verify)("## %s: encountered NULL surv_rate_group", name);
ret = false;
}
@@ -766,12 +843,12 @@
int age = curr->age_in_surv_rate_group();
if (age < 0) {
- log_info(gc, verify)("## %s: encountered negative age", name);
+ log_error(gc, verify)("## %s: encountered negative age", name);
ret = false;
}
if (age <= prev_age) {
- log_info(gc, verify)("## %s: region ages are not strictly increasing (%d, %d)", name, age, prev_age);
+ log_error(gc, verify)("## %s: region ages are not strictly increasing (%d, %d)", name, age, prev_age);
ret = false;
}
prev_age = age;
@@ -1601,6 +1678,10 @@
return young_list_length < young_list_max_length;
}
+bool G1CollectorPolicy::adaptive_young_list_length() const {
+ return _young_gen_sizer->adaptive_young_list_length();
+}
+
void G1CollectorPolicy::update_max_gc_locker_expansion() {
uint expansion_region_num = 0;
if (GCLockerEdenExpansionPercent > 0) {
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -43,6 +43,7 @@
class HeapRegion;
class CollectionSetChooser;
class G1IHOPControl;
+class G1YoungGenSizer;
// TraceYoungGenTime collects data on _both_ young and mixed evacuation pauses
// (the latter may contain non-young regions - i.e. regions that are
@@ -90,81 +91,6 @@
void print() const;
};
-// There are three command line options related to the young gen size:
-// NewSize, MaxNewSize and NewRatio (There is also -Xmn, but that is
-// just a short form for NewSize==MaxNewSize). G1 will use its internal
-// heuristics to calculate the actual young gen size, so these options
-// basically only limit the range within which G1 can pick a young gen
-// size. Also, these are general options taking byte sizes. G1 will
-// internally work with a number of regions instead. So, some rounding
-// will occur.
-//
-// If nothing related to the the young gen size is set on the command
-// line we should allow the young gen to be between G1NewSizePercent
-// and G1MaxNewSizePercent of the heap size. This means that every time
-// the heap size changes, the limits for the young gen size will be
-// recalculated.
-//
-// If only -XX:NewSize is set we should use the specified value as the
-// minimum size for young gen. Still using G1MaxNewSizePercent of the
-// heap as maximum.
-//
-// If only -XX:MaxNewSize is set we should use the specified value as the
-// maximum size for young gen. Still using G1NewSizePercent of the heap
-// as minimum.
-//
-// If -XX:NewSize and -XX:MaxNewSize are both specified we use these values.
-// No updates when the heap size changes. There is a special case when
-// NewSize==MaxNewSize. This is interpreted as "fixed" and will use a
-// different heuristic for calculating the collection set when we do mixed
-// collection.
-//
-// If only -XX:NewRatio is set we should use the specified ratio of the heap
-// as both min and max. This will be interpreted as "fixed" just like the
-// NewSize==MaxNewSize case above. But we will update the min and max
-// every time the heap size changes.
-//
-// NewSize and MaxNewSize override NewRatio. So, NewRatio is ignored if it is
-// combined with either NewSize or MaxNewSize. (A warning message is printed.)
-class G1YoungGenSizer : public CHeapObj<mtGC> {
-private:
- enum SizerKind {
- SizerDefaults,
- SizerNewSizeOnly,
- SizerMaxNewSizeOnly,
- SizerMaxAndNewSize,
- SizerNewRatio
- };
- SizerKind _sizer_kind;
- uint _min_desired_young_length;
- uint _max_desired_young_length;
- bool _adaptive_size;
- uint calculate_default_min_length(uint new_number_of_heap_regions);
- uint calculate_default_max_length(uint new_number_of_heap_regions);
-
- // Update the given values for minimum and maximum young gen length in regions
- // given the number of heap regions depending on the kind of sizing algorithm.
- void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length);
-
-public:
- G1YoungGenSizer();
- // Calculate the maximum length of the young gen given the number of regions
- // depending on the sizing algorithm.
- uint max_young_length(uint number_of_heap_regions);
-
- void heap_size_changed(uint new_number_of_heap_regions);
- uint min_desired_young_length() {
- return _min_desired_young_length;
- }
- uint max_desired_young_length() {
- return _max_desired_young_length;
- }
-
- bool adaptive_young_list_length() const {
- return _adaptive_size;
- }
-};
-
class G1CollectorPolicy: public CollectorPolicy {
private:
G1IHOPControl* _ihop_control;
@@ -784,9 +710,7 @@
return _young_list_max_length;
}
- bool adaptive_young_list_length() const {
- return _young_gen_sizer->adaptive_young_list_length();
- }
+ bool adaptive_young_list_length() const;
virtual bool should_process_references() const {
return true;
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -372,6 +372,16 @@
return res;
}
+void G1CMRootRegions::notify_scan_done() {
+ MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
+ _scan_in_progress = false;
+ RootRegionScan_lock->notify_all();
+}
+
+void G1CMRootRegions::cancel_scan() {
+ notify_scan_done();
+}
+
void G1CMRootRegions::scan_finished() {
assert(scan_in_progress(), "pre-condition");
@@ -381,11 +391,7 @@
}
_next_survivor = NULL;
- {
- MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag);
- _scan_in_progress = false;
- RootRegionScan_lock->notify_all();
- }
+ notify_scan_done();
}
bool G1CMRootRegions::wait_until_scan_finished() {
@@ -978,13 +984,11 @@
};
void G1ConcurrentMark::scanRootRegions() {
- // Start of concurrent marking.
- ClassLoaderDataGraph::clear_claimed_marks();
-
// scan_in_progress() will have been set to true only if there was
// at least one root region to scan. So, if it's false, we
// should not attempt to do any further work.
if (root_regions()->scan_in_progress()) {
+ assert(!has_aborted(), "Aborting before root region scanning is finished not supported.");
GCTraceConcTime(Info, gc) tt("Concurrent Root Region Scan");
_parallel_marking_threads = calc_parallel_marking_threads();
--- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -229,6 +229,8 @@
volatile bool _should_abort;
HeapRegion* volatile _next_survivor;
+ void notify_scan_done();
+
public:
G1CMRootRegions();
// We actually do most of the initialization in this method.
@@ -248,6 +250,8 @@
// all have been claimed.
HeapRegion* claim_next();
+ void cancel_scan();
+
// Flag that we're done with root region scanning and notify anyone
// who's waiting on it. If aborted is false, assume that all regions
// have been claimed.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1HeapRegionTraceType.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_G1_G1HEAPREGIONTRACETYPE_HPP
+#define SHARE_VM_GC_G1_G1HEAPREGIONTRACETYPE_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+class G1HeapRegionTraceType : AllStatic {
+ public:
+ enum Type {
+ Free,
+ Eden,
+ Survivor,
+ StartsHumongous,
+ ContinuesHumongous,
+ Old,
+ Archive,
+ G1HeapRegionTypeEndSentinel
+ };
+
+ static const char* to_string(G1HeapRegionTraceType::Type type) {
+ switch (type) {
+ case Free: return "Free";
+ case Eden: return "Eden";
+ case Survivor: return "Survivor";
+ case StartsHumongous: return "Starts Humongous";
+ case ContinuesHumongous: return "Continues Humongous";
+ case Old: return "Old";
+ case Archive: return "Archive";
+ default: ShouldNotReachHere(); return NULL;
+ }
+ }
+};
+
+#endif // SHARE_VM_GC_G1_G1HEAPREGIONTRACETYPE_HPP
--- a/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1HeapVerifier.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -63,10 +63,10 @@
LogHandle(gc, verify) log;
log.info("Root location " PTR_FORMAT " points to dead obj " PTR_FORMAT, p2i(p), p2i(obj));
if (_vo == VerifyOption_G1UseMarkWord) {
- log.info(" Mark word: " PTR_FORMAT, p2i(obj->mark()));
+ log.error(" Mark word: " PTR_FORMAT, p2i(obj->mark()));
}
ResourceMark rm;
- obj->print_on(log.info_stream());
+ obj->print_on(log.error_stream());
_failures = true;
}
}
@@ -111,10 +111,10 @@
// Verify that the strong code root list for this region
// contains the nmethod
if (!hrrs->strong_code_roots_list_contains(_nm)) {
- log_info(gc, verify)("Code root location " PTR_FORMAT " "
- "from nmethod " PTR_FORMAT " not in strong "
- "code roots for region [" PTR_FORMAT "," PTR_FORMAT ")",
- p2i(p), p2i(_nm), p2i(hr->bottom()), p2i(hr->end()));
+ log_error(gc, verify)("Code root location " PTR_FORMAT " "
+ "from nmethod " PTR_FORMAT " not in strong "
+ "code roots for region [" PTR_FORMAT "," PTR_FORMAT ")",
+ p2i(p), p2i(_nm), p2i(hr->bottom()), p2i(hr->end()));
_failures = true;
}
}
@@ -292,8 +292,8 @@
r->object_iterate(¬_dead_yet_cl);
if (_vo != VerifyOption_G1UseNextMarking) {
if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) {
- log_info(gc, verify)("[" PTR_FORMAT "," PTR_FORMAT "] max_live_bytes " SIZE_FORMAT " < calculated " SIZE_FORMAT,
- p2i(r->bottom()), p2i(r->end()), r->max_live_bytes(), not_dead_yet_cl.live_bytes());
+ log_error(gc, verify)("[" PTR_FORMAT "," PTR_FORMAT "] max_live_bytes " SIZE_FORMAT " < calculated " SIZE_FORMAT,
+ p2i(r->bottom()), p2i(r->end()), r->max_live_bytes(), not_dead_yet_cl.live_bytes());
_failures = true;
}
} else {
@@ -402,13 +402,13 @@
}
if (failures) {
- log_info(gc, verify)("Heap after failed verification:");
+ log_error(gc, verify)("Heap after failed verification:");
// It helps to have the per-region information in the output to
// help us track down what went wrong. This is why we call
// print_extended_on() instead of print_on().
LogHandle(gc, verify) log;
ResourceMark rm;
- _g1h->print_extended_on(log.info_stream());
+ _g1h->print_extended_on(log.error_stream());
}
guarantee(!failures, "there should not have been any failures");
}
@@ -597,8 +597,8 @@
"tams: " PTR_FORMAT " end: " PTR_FORMAT, p2i(tams), p2i(end));
HeapWord* result = bitmap->getNextMarkedWordAddress(tams, end);
if (result < end) {
- log_info(gc, verify)("## wrong marked address on %s bitmap: " PTR_FORMAT, bitmap_name, p2i(result));
- log_info(gc, verify)("## %s tams: " PTR_FORMAT " end: " PTR_FORMAT, bitmap_name, p2i(tams), p2i(end));
+ log_error(gc, verify)("## wrong marked address on %s bitmap: " PTR_FORMAT, bitmap_name, p2i(result));
+ log_error(gc, verify)("## %s tams: " PTR_FORMAT " end: " PTR_FORMAT, bitmap_name, p2i(tams), p2i(end));
return false;
}
return true;
@@ -623,8 +623,8 @@
res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end);
}
if (!res_p || !res_n) {
- log_info(gc, verify)("#### Bitmap verification failed for " HR_FORMAT, HR_FORMAT_PARAMS(hr));
- log_info(gc, verify)("#### Caller: %s", caller);
+ log_error(gc, verify)("#### Bitmap verification failed for " HR_FORMAT, HR_FORMAT_PARAMS(hr));
+ log_error(gc, verify)("#### Caller: %s", caller);
return false;
}
return true;
@@ -676,41 +676,41 @@
InCSetState cset_state = (InCSetState) G1CollectedHeap::heap()->_in_cset_fast_test.get_by_index(i);
if (hr->is_humongous()) {
if (hr->in_collection_set()) {
- log_info(gc, verify)("## humongous region %u in CSet", i);
+ log_error(gc, verify)("## humongous region %u in CSet", i);
_failures = true;
return true;
}
if (cset_state.is_in_cset()) {
- log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for humongous region %u", cset_state.value(), i);
+ log_error(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for humongous region %u", cset_state.value(), i);
_failures = true;
return true;
}
if (hr->is_continues_humongous() && cset_state.is_humongous()) {
- log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for continues humongous region %u", cset_state.value(), i);
+ log_error(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for continues humongous region %u", cset_state.value(), i);
_failures = true;
return true;
}
} else {
if (cset_state.is_humongous()) {
- log_info(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for non-humongous region %u", cset_state.value(), i);
+ log_error(gc, verify)("## inconsistent cset state " CSETSTATE_FORMAT " for non-humongous region %u", cset_state.value(), i);
_failures = true;
return true;
}
if (hr->in_collection_set() != cset_state.is_in_cset()) {
- log_info(gc, verify)("## in CSet %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
+ log_error(gc, verify)("## in CSet %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
hr->in_collection_set(), cset_state.value(), i);
_failures = true;
return true;
}
if (cset_state.is_in_cset()) {
if (hr->is_young() != (cset_state.is_young())) {
- log_info(gc, verify)("## is_young %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
+ log_error(gc, verify)("## is_young %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
hr->is_young(), cset_state.value(), i);
_failures = true;
return true;
}
if (hr->is_old() != (cset_state.is_old())) {
- log_info(gc, verify)("## is_old %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
+ log_error(gc, verify)("## is_old %d / cset state " CSETSTATE_FORMAT " inconsistency for region %u",
hr->is_old(), cset_state.value(), i);
_failures = true;
return true;
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -26,11 +26,13 @@
#include "code/nmethod.hpp"
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1HeapRegionTraceType.hpp"
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionBounds.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
+#include "gc/g1/heapRegionTracer.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/liveRange.hpp"
#include "gc/shared/space.inline.hpp"
@@ -212,10 +214,41 @@
_gc_efficiency = (double) reclaimable_bytes() / region_elapsed_time_ms;
}
+void HeapRegion::set_free() {
+ report_region_type_change(G1HeapRegionTraceType::Free);
+ _type.set_free();
+}
+
+void HeapRegion::set_eden() {
+ report_region_type_change(G1HeapRegionTraceType::Eden);
+ _type.set_eden();
+}
+
+void HeapRegion::set_eden_pre_gc() {
+ report_region_type_change(G1HeapRegionTraceType::Eden);
+ _type.set_eden_pre_gc();
+}
+
+void HeapRegion::set_survivor() {
+ report_region_type_change(G1HeapRegionTraceType::Survivor);
+ _type.set_survivor();
+}
+
+void HeapRegion::set_old() {
+ report_region_type_change(G1HeapRegionTraceType::Old);
+ _type.set_old();
+}
+
+void HeapRegion::set_archive() {
+ report_region_type_change(G1HeapRegionTraceType::Archive);
+ _type.set_archive();
+}
+
void HeapRegion::set_starts_humongous(HeapWord* obj_top, size_t fill_size) {
assert(!is_humongous(), "sanity / pre-condition");
assert(top() == bottom(), "should be empty");
+ report_region_type_change(G1HeapRegionTraceType::StartsHumongous);
_type.set_starts_humongous();
_humongous_start_region = this;
@@ -227,6 +260,7 @@
assert(top() == bottom(), "should be empty");
assert(first_hr->is_starts_humongous(), "pre-condition");
+ report_region_type_change(G1HeapRegionTraceType::ContinuesHumongous);
_type.set_continues_humongous();
_humongous_start_region = first_hr;
}
@@ -272,6 +306,15 @@
record_timestamp();
}
+void HeapRegion::report_region_type_change(G1HeapRegionTraceType::Type to) {
+ HeapRegionTracer::send_region_type_change(_hrm_index,
+ get_trace_type(),
+ to,
+ (uintptr_t)bottom(),
+ used(),
+ (uint)allocation_context());
+}
+
CompactibleSpace* HeapRegion::next_compaction_space() const {
return G1CollectedHeap::heap()->next_compaction_region(this);
}
@@ -479,7 +522,7 @@
// Object is in the region. Check that its less than top
if (_hr->top() <= (HeapWord*)obj) {
// Object is above top
- log_info(gc, verify)("Object " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ") is above top " PTR_FORMAT,
+ log_error(gc, verify)("Object " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ") is above top " PTR_FORMAT,
p2i(obj), p2i(_hr->bottom()), p2i(_hr->end()), p2i(_hr->top()));
_failures = true;
return;
@@ -513,19 +556,19 @@
if (nm != NULL) {
// Verify that the nemthod is live
if (!nm->is_alive()) {
- log_info(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has dead nmethod " PTR_FORMAT " in its strong code roots",
- p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
+ log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has dead nmethod " PTR_FORMAT " in its strong code roots",
+ p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
_failures = true;
} else {
VerifyStrongCodeRootOopClosure oop_cl(_hr, nm);
nm->oops_do(&oop_cl);
if (!oop_cl.has_oops_in_region()) {
- log_info(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has nmethod " PTR_FORMAT " in its strong code roots with no pointers into region",
- p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
+ log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has nmethod " PTR_FORMAT " in its strong code roots with no pointers into region",
+ p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
_failures = true;
} else if (oop_cl.failures()) {
- log_info(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has other failures for nmethod " PTR_FORMAT,
- p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
+ log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] has other failures for nmethod " PTR_FORMAT,
+ p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
_failures = true;
}
}
@@ -558,8 +601,8 @@
// on its strong code root list
if (is_empty()) {
if (strong_code_roots_length > 0) {
- log_info(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] is empty but has " SIZE_FORMAT " code root entries",
- p2i(bottom()), p2i(end()), strong_code_roots_length);
+ log_error(gc, verify)("region [" PTR_FORMAT "," PTR_FORMAT "] is empty but has " SIZE_FORMAT " code root entries",
+ p2i(bottom()), p2i(end()), strong_code_roots_length);
*failures = true;
}
return;
@@ -567,8 +610,8 @@
if (is_continues_humongous()) {
if (strong_code_roots_length > 0) {
- log_info(gc, verify)("region " HR_FORMAT " is a continuation of a humongous region but has " SIZE_FORMAT " code root entries",
- HR_FORMAT_PARAMS(this), strong_code_roots_length);
+ log_error(gc, verify)("region " HR_FORMAT " is a continuation of a humongous region but has " SIZE_FORMAT " code root entries",
+ HR_FORMAT_PARAMS(this), strong_code_roots_length);
*failures = true;
}
return;
@@ -661,26 +704,26 @@
Mutex::_no_safepoint_check_flag);
if (!_failures) {
- log.info("----------");
+ log.error("----------");
}
ResourceMark rm;
if (!_g1h->is_in_closed_subset(obj)) {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
- log.info("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
+ log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end()));
- print_object(log.info_stream(), _containing_obj);
- log.info("points to obj " PTR_FORMAT " not in the heap", p2i(obj));
+ print_object(log.error_stream(), _containing_obj);
+ log.error("points to obj " PTR_FORMAT " not in the heap", p2i(obj));
} else {
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
- log.info("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
+ log.error("Field " PTR_FORMAT " of live obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end()));
- print_object(log.info_stream(), _containing_obj);
- log.info("points to dead obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
+ print_object(log.error_stream(), _containing_obj);
+ log.error("points to dead obj " PTR_FORMAT " in region [" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(obj), p2i(to->bottom()), p2i(to->end()));
- print_object(log.info_stream(), obj);
+ print_object(log.error_stream(), obj);
}
- log.info("----------");
+ log.error("----------");
_failures = true;
failed = true;
_n_failures++;
@@ -730,17 +773,17 @@
Mutex::_no_safepoint_check_flag);
if (!_failures) {
- log.info("----------");
+ log.error("----------");
}
- log.info("Missing rem set entry:");
- log.info("Field " PTR_FORMAT " of obj " PTR_FORMAT ", in region " HR_FORMAT,
+ log.error("Missing rem set entry:");
+ log.error("Field " PTR_FORMAT " of obj " PTR_FORMAT ", in region " HR_FORMAT,
p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from));
ResourceMark rm;
- _containing_obj->print_on(log.info_stream());
- log.info("points to obj " PTR_FORMAT " in region " HR_FORMAT, p2i(obj), HR_FORMAT_PARAMS(to));
- obj->print_on(log.info_stream());
- log.info("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field);
- log.info("----------");
+ _containing_obj->print_on(log.error_stream());
+ log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT, p2i(obj), HR_FORMAT_PARAMS(to));
+ obj->print_on(log.error_stream());
+ log.error("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field);
+ log.error("----------");
_failures = true;
if (!failed) _n_failures++;
}
@@ -774,13 +817,13 @@
(vo == VerifyOption_G1UsePrevMarking &&
ClassLoaderDataGraph::unload_list_contains(klass));
if (!is_metaspace_object) {
- log_info(gc, verify)("klass " PTR_FORMAT " of object " PTR_FORMAT " "
- "not metadata", p2i(klass), p2i(obj));
+ log_error(gc, verify)("klass " PTR_FORMAT " of object " PTR_FORMAT " "
+ "not metadata", p2i(klass), p2i(obj));
*failures = true;
return;
} else if (!klass->is_klass()) {
- log_info(gc, verify)("klass " PTR_FORMAT " of object " PTR_FORMAT " "
- "not a klass", p2i(klass), p2i(obj));
+ log_error(gc, verify)("klass " PTR_FORMAT " of object " PTR_FORMAT " "
+ "not a klass", p2i(klass), p2i(obj));
*failures = true;
return;
} else {
@@ -811,7 +854,7 @@
}
}
} else {
- log_info(gc, verify)(PTR_FORMAT " not an oop", p2i(obj));
+ log_error(gc, verify)(PTR_FORMAT " not an oop", p2i(obj));
*failures = true;
return;
}
@@ -827,13 +870,15 @@
if (is_region_humongous) {
oop obj = oop(this->humongous_start_region()->bottom());
if ((HeapWord*)obj > bottom() || (HeapWord*)obj + obj->size() < bottom()) {
- log_info(gc, verify)("this humongous region is not part of its' humongous object " PTR_FORMAT, p2i(obj));
+ log_error(gc, verify)("this humongous region is not part of its' humongous object " PTR_FORMAT, p2i(obj));
+ *failures = true;
+ return;
}
}
if (!is_region_humongous && p != top()) {
- log_info(gc, verify)("end of last object " PTR_FORMAT " "
- "does not match top " PTR_FORMAT, p2i(p), p2i(top()));
+ log_error(gc, verify)("end of last object " PTR_FORMAT " "
+ "does not match top " PTR_FORMAT, p2i(p), p2i(top()));
*failures = true;
return;
}
@@ -847,9 +892,9 @@
HeapWord* addr_1 = p;
HeapWord* b_start_1 = _bot_part.block_start_const(addr_1);
if (b_start_1 != p) {
- log_info(gc, verify)("BOT look up for top: " PTR_FORMAT " "
- " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
- p2i(addr_1), p2i(b_start_1), p2i(p));
+ log_error(gc, verify)("BOT look up for top: " PTR_FORMAT " "
+ " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
+ p2i(addr_1), p2i(b_start_1), p2i(p));
*failures = true;
return;
}
@@ -859,9 +904,9 @@
if (addr_2 < the_end) {
HeapWord* b_start_2 = _bot_part.block_start_const(addr_2);
if (b_start_2 != p) {
- log_info(gc, verify)("BOT look up for top + 1: " PTR_FORMAT " "
- " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
- p2i(addr_2), p2i(b_start_2), p2i(p));
+ log_error(gc, verify)("BOT look up for top + 1: " PTR_FORMAT " "
+ " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
+ p2i(addr_2), p2i(b_start_2), p2i(p));
*failures = true;
return;
}
@@ -873,9 +918,9 @@
if (addr_3 < the_end) {
HeapWord* b_start_3 = _bot_part.block_start_const(addr_3);
if (b_start_3 != p) {
- log_info(gc, verify)("BOT look up for top + diff: " PTR_FORMAT " "
- " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
- p2i(addr_3), p2i(b_start_3), p2i(p));
+ log_error(gc, verify)("BOT look up for top + diff: " PTR_FORMAT " "
+ " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
+ p2i(addr_3), p2i(b_start_3), p2i(p));
*failures = true;
return;
}
@@ -885,9 +930,9 @@
HeapWord* addr_4 = the_end - 1;
HeapWord* b_start_4 = _bot_part.block_start_const(addr_4);
if (b_start_4 != p) {
- log_info(gc, verify)("BOT look up for end - 1: " PTR_FORMAT " "
- " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
- p2i(addr_4), p2i(b_start_4), p2i(p));
+ log_error(gc, verify)("BOT look up for end - 1: " PTR_FORMAT " "
+ " yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
+ p2i(addr_4), p2i(b_start_4), p2i(p));
*failures = true;
return;
}
@@ -924,7 +969,7 @@
return;
}
} else {
- log_info(gc, verify)(PTR_FORMAT " not an oop", p2i(obj));
+ log_error(gc, verify)(PTR_FORMAT " not an oop", p2i(obj));
*failures = true;
return;
}
--- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -27,6 +27,8 @@
#include "gc/g1/g1AllocationContext.hpp"
#include "gc/g1/g1BlockOffsetTable.hpp"
+#include "gc/g1/g1HeapRegionTraceType.hpp"
+#include "gc/g1/heapRegionTracer.hpp"
#include "gc/g1/heapRegionType.hpp"
#include "gc/g1/survRateGroup.hpp"
#include "gc/shared/ageTable.hpp"
@@ -243,6 +245,8 @@
return HeapRegion::block_size(addr); // Avoid virtual call
}
+ void report_region_type_change(G1HeapRegionTraceType::Type to);
+
protected:
// The index of this region in the heap region sequence.
uint _hrm_index;
@@ -427,6 +431,7 @@
const char* get_type_str() const { return _type.get_str(); }
const char* get_short_type_str() const { return _type.get_short_str(); }
+ G1HeapRegionTraceType::Type get_trace_type() { return _type.get_trace_type(); }
bool is_free() const { return _type.is_free(); }
@@ -637,15 +642,15 @@
}
}
- void set_free() { _type.set_free(); }
+ void set_free();
- void set_eden() { _type.set_eden(); }
- void set_eden_pre_gc() { _type.set_eden_pre_gc(); }
- void set_survivor() { _type.set_survivor(); }
+ void set_eden();
+ void set_eden_pre_gc();
+ void set_survivor();
- void set_old() { _type.set_old(); }
+ void set_old();
- void set_archive() { _type.set_archive(); }
+ void set_archive();
// Determine if an object has been allocated since the last
// mark performed by the collector. This returns true iff the object
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/heapRegionTracer.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/heapRegionTracer.hpp"
+#include "trace/tracing.hpp"
+
+void HeapRegionTracer::send_region_type_change(uint index,
+ G1HeapRegionTraceType::Type from,
+ G1HeapRegionTraceType::Type to,
+ uintptr_t start,
+ size_t used,
+ uint allocationContext) {
+ EventG1HeapRegionTypeChange e;
+ if (e.should_commit()) {
+ e.set_index(index);
+ e.set_from(from);
+ e.set_to(to);
+ e.set_start(start);
+ e.set_used(used);
+ e.set_allocContext(allocationContext);
+ e.commit();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/heapRegionTracer.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_G1_HEAPREGIONTRACER_HPP
+#define SHARE_VM_GC_G1_HEAPREGIONTRACER_HPP
+
+#include "gc/g1/g1HeapRegionTraceType.hpp"
+#include "memory/allocation.hpp"
+
+class HeapRegionTracer : AllStatic {
+ public:
+ static void send_region_type_change(uint index,
+ G1HeapRegionTraceType::Type from,
+ G1HeapRegionTraceType::Type to,
+ uintptr_t start,
+ size_t used,
+ uint allocationContext);
+};
+
+#endif // SHARE_VM_GC_G1_HEAPREGIONTRACER_HPP
--- a/hotspot/src/share/vm/gc/g1/heapRegionType.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/heapRegionType.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "gc/g1/g1HeapRegionTraceType.hpp"
#include "gc/g1/heapRegionType.hpp"
bool HeapRegionType::is_valid(Tag tag) {
@@ -70,3 +71,19 @@
// keep some compilers happy
return NULL;
}
+
+G1HeapRegionTraceType::Type HeapRegionType::get_trace_type() {
+ hrt_assert_is_valid(_tag);
+ switch (_tag) {
+ case FreeTag: return G1HeapRegionTraceType::Free;
+ case EdenTag: return G1HeapRegionTraceType::Eden;
+ case SurvTag: return G1HeapRegionTraceType::Survivor;
+ case StartsHumongousTag: return G1HeapRegionTraceType::StartsHumongous;
+ case ContinuesHumongousTag: return G1HeapRegionTraceType::ContinuesHumongous;
+ case OldTag: return G1HeapRegionTraceType::Old;
+ case ArchiveTag: return G1HeapRegionTraceType::Archive;
+ }
+ ShouldNotReachHere();
+ // keep some compilers happy
+ return G1HeapRegionTraceType::Free;
+}
--- a/hotspot/src/share/vm/gc/g1/heapRegionType.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/heapRegionType.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_G1_HEAPREGIONTYPE_HPP
#define SHARE_VM_GC_G1_HEAPREGIONTYPE_HPP
+#include "gc/g1/g1HeapRegionTraceType.hpp"
#include "memory/allocation.hpp"
#define hrt_assert_is_valid(tag) \
@@ -141,6 +142,7 @@
const char* get_str() const;
const char* get_short_str() const;
+ G1HeapRegionTraceType::Type get_trace_type();
HeapRegionType() : _tag(FreeTag) { hrt_assert_is_valid(_tag); }
};
--- a/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/satbMarkQueue.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -221,13 +221,13 @@
#ifdef ASSERT
void SATBMarkQueueSet::dump_active_states(bool expected_active) {
- log_info(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE");
- log_info(gc, verify)("Actual SATB active states:");
- log_info(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
+ log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE");
+ log_error(gc, verify)("Actual SATB active states:");
+ log_error(gc, verify)(" Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
for (JavaThread* t = Threads::first(); t; t = t->next()) {
- log_info(gc, verify)(" Thread \"%s\" queue: %s", t->name(), t->satb_mark_queue().is_active() ? "ACTIVE" : "INACTIVE");
+ log_error(gc, verify)(" Thread \"%s\" queue: %s", t->name(), t->satb_mark_queue().is_active() ? "ACTIVE" : "INACTIVE");
}
- log_info(gc, verify)(" Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
+ log_error(gc, verify)(" Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
}
void SATBMarkQueueSet::verify_active_states(bool expected_active) {
--- a/hotspot/src/share/vm/gc/g1/youngList.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/youngList.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -99,10 +99,10 @@
HeapRegion* last = NULL;
while (curr != NULL) {
if (!curr->is_young()) {
- log_info(gc, verify)("### YOUNG REGION " PTR_FORMAT "-" PTR_FORMAT " "
- "incorrectly tagged (y: %d, surv: %d)",
- p2i(curr->bottom()), p2i(curr->end()),
- curr->is_young(), curr->is_survivor());
+ log_error(gc, verify)("### YOUNG REGION " PTR_FORMAT "-" PTR_FORMAT " "
+ "incorrectly tagged (y: %d, surv: %d)",
+ p2i(curr->bottom()), p2i(curr->end()),
+ curr->is_young(), curr->is_survivor());
ret = false;
}
++length;
@@ -112,8 +112,8 @@
ret = ret && (length == _length);
if (!ret) {
- log_info(gc, verify)("### YOUNG LIST seems not well formed!");
- log_info(gc, verify)("### list has %u entries, _length is %u", length, _length);
+ log_error(gc, verify)("### YOUNG LIST seems not well formed!");
+ log_error(gc, verify)("### list has %u entries, _length is %u", length, _length);
}
return ret;
@@ -123,19 +123,19 @@
bool ret = true;
if (_length != 0) {
- log_info(gc, verify)("### YOUNG LIST should have 0 length, not %u", _length);
+ log_error(gc, verify)("### YOUNG LIST should have 0 length, not %u", _length);
ret = false;
}
if (check_sample && _last_sampled_rs_lengths != 0) {
- log_info(gc, verify)("### YOUNG LIST has non-zero last sampled RS lengths");
+ log_error(gc, verify)("### YOUNG LIST has non-zero last sampled RS lengths");
ret = false;
}
if (_head != NULL) {
- log_info(gc, verify)("### YOUNG LIST does not have a NULL head");
+ log_error(gc, verify)("### YOUNG LIST does not have a NULL head");
ret = false;
}
if (!ret) {
- log_info(gc, verify)("### YOUNG LIST does not seem empty");
+ log_error(gc, verify)("### YOUNG LIST does not seem empty");
}
return ret;
--- a/hotspot/src/share/vm/gc/shared/ageTable.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/ageTable.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/shared/ageTable.inline.hpp"
+#include "gc/shared/ageTableTracer.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/collectorPolicy.hpp"
#include "gc/shared/gcPolicyCounters.hpp"
@@ -100,17 +101,19 @@
log_debug(gc, age)("Desired survivor size " SIZE_FORMAT " bytes, new threshold " UINTX_FORMAT " (max threshold " UINTX_FORMAT ")",
desired_survivor_size*oopSize, (uintx) result, MaxTenuringThreshold);
- if (log_is_enabled(Trace, gc, age) || UsePerfData) {
+ if (log_is_enabled(Trace, gc, age) || UsePerfData || AgeTableTracer::is_tenuring_distribution_event_enabled()) {
size_t total = 0;
uint age = 1;
while (age < table_size) {
- total += sizes[age];
- if (sizes[age] > 0) {
+ size_t wordSize = sizes[age];
+ total += wordSize;
+ if (wordSize > 0) {
log_trace(gc, age)("- age %3u: " SIZE_FORMAT_W(10) " bytes, " SIZE_FORMAT_W(10) " total",
- age, sizes[age]*oopSize, total*oopSize);
+ age, wordSize*oopSize, total*oopSize);
}
+ AgeTableTracer::send_tenuring_distribution_event(age, wordSize*oopSize);
if (UsePerfData) {
- _perf_sizes[age]->set_value(sizes[age]*oopSize);
+ _perf_sizes[age]->set_value(wordSize*oopSize);
}
age++;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/ageTableTracer.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/ageTableTracer.hpp"
+#include "gc/shared/gcId.hpp"
+#include "trace/tracing.hpp"
+
+void AgeTableTracer::send_tenuring_distribution_event(uint age, size_t size) {
+ EventTenuringDistribution e;
+ if (e.should_commit()) {
+ e.set_gcId(GCId::current());
+ e.set_age(age);
+ e.set_size(size);
+ e.commit();
+ }
+}
+
+bool AgeTableTracer::is_tenuring_distribution_event_enabled() {
+ return EventTenuringDistribution::is_enabled();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/ageTableTracer.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_AGETABLETRACER_HPP
+#define SHARE_VM_GC_SHARED_AGETABLETRACER_HPP
+
+#include "memory/allocation.hpp"
+
+class AgeTableTracer : AllStatic {
+ public:
+ static void send_tenuring_distribution_event(uint age, size_t size);
+ static bool is_tenuring_distribution_event_enabled();
+};
+
+#endif // SHARE_VM_GC_SHARED_AGETABLETRACER_HPP
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -60,7 +60,7 @@
void ConcurrentGCThread::wait_for_universe_init() {
MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
while (!is_init_completed() && !_should_terminate) {
- CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200);
+ CGC_lock->wait(Mutex::_no_safepoint_check_flag, 1);
}
}
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
friend class VMStructs;
protected:
- bool _should_terminate;
+ bool volatile _should_terminate;
bool _has_terminated;
// Create and start the thread (setting it's priority high.)
--- a/hotspot/src/share/vm/gc/shared/gcHeapSummary.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/gcHeapSummary.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -131,12 +131,14 @@
size_t _edenUsed;
size_t _edenCapacity;
size_t _survivorUsed;
+ uint _numberOfRegions;
public:
- G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed) :
- GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed) { }
+ G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed, uint numberOfRegions) :
+ GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed), _numberOfRegions(numberOfRegions) { }
const size_t edenUsed() const { return _edenUsed; }
const size_t edenCapacity() const { return _edenCapacity; }
const size_t survivorUsed() const { return _survivorUsed; }
+ const uint numberOfRegions() const { return _numberOfRegions; }
virtual void accept(GCHeapSummaryVisitor* visitor) const {
visitor->visit(this);
--- a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -359,6 +359,7 @@
e.set_edenUsedSize(g1_heap_summary->edenUsed());
e.set_edenTotalSize(g1_heap_summary->edenCapacity());
e.set_survivorUsedSize(g1_heap_summary->survivorUsed());
+ e.set_numberOfRegions(g1_heap_summary->numberOfRegions());
e.commit();
}
}
--- a/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -34,7 +34,7 @@
#if INCLUDE_ALL_GCS
// Unit test
-#ifdef ASSERT
+#ifndef PRODUCT
static unsigned line_byte(const char* line, size_t i) {
return unsigned(line[i]) & 0xFF;
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1091,7 +1091,7 @@
} else if (reference->is_a(site_DataSectionReference::klass())) {
int data_offset = site_DataSectionReference::offset(reference);
if (0 <= data_offset && data_offset < _constants_size) {
- pd_patch_DataSectionReference(pc_offset, data_offset);
+ pd_patch_DataSectionReference(pc_offset, data_offset, CHECK);
} else {
JVMCI_ERROR("data offset 0x%X points outside data section (size 0x%X)", data_offset, _constants_size);
}
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -156,7 +156,7 @@
jint pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS);
void pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS);
void pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS);
- void pd_patch_DataSectionReference(int pc_offset, int data_offset);
+ void pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS);
void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS);
void pd_relocate_JavaMethod(Handle method, jint pc_offset, TRAPS);
void pd_relocate_poll(address pc, jint mark, TRAPS);
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -591,6 +591,13 @@
// JVMTI -- compiled method notification (must be done outside lock)
if (nm != NULL) {
nm->post_compiled_method_load_event();
+
+ if (env == NULL) {
+ // This compile didn't come through the CompileBroker so perform the printing here
+ DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
+ nm->maybe_print_nmethod(directive);
+ DirectivesStack::release(directive);
+ }
}
return result;
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -151,6 +151,7 @@
nonstatic_field(JavaThread, _pending_failed_speculation, oop) \
nonstatic_field(JavaThread, _pending_transfer_to_interpreter, bool) \
nonstatic_field(JavaThread, _jvmci_counters, jlong*) \
+ nonstatic_field(JavaThread, _reserved_stack_activation, address) \
\
static_field(java_lang_Class, _klass_offset, int) \
static_field(java_lang_Class, _array_klass_offset, int) \
@@ -210,6 +211,8 @@
\
static_field(StubRoutines, _verify_oop_count, jint) \
\
+ static_field(StubRoutines, _throw_delayed_StackOverflowError_entry, address) \
+ \
static_field(StubRoutines, _jbyte_arraycopy, address) \
static_field(StubRoutines, _jshort_arraycopy, address) \
static_field(StubRoutines, _jint_arraycopy, address) \
@@ -471,6 +474,7 @@
declare_constant(Method::_force_inline) \
declare_constant(Method::_dont_inline) \
declare_constant(Method::_hidden) \
+ declare_constant(Method::_reserved_stack_access) \
\
declare_constant(Method::nonvirtual_vtable_index) \
declare_constant(Method::invalid_vtable_index) \
@@ -517,6 +521,7 @@
declare_function(SharedRuntime::register_finalizer) \
declare_function(SharedRuntime::exception_handler_for_return_address) \
declare_function(SharedRuntime::OSR_migration_end) \
+ declare_function(SharedRuntime::enable_stack_reserved_zone) \
declare_function(SharedRuntime::dsin) \
declare_function(SharedRuntime::dcos) \
declare_function(SharedRuntime::dtan) \
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -182,6 +182,10 @@
"Unroll loop bodies with node count less than this") \
range(0, max_jint / 4) \
\
+ product_pd(intx, LoopPercentProfileLimit, \
+ "Unroll loop bodies with % node count of profile limit") \
+ range(10, 100) \
+ \
product(intx, LoopMaxUnroll, 16, \
"Maximum number of unrolls for main loop") \
range(0, max_jint) \
--- a/hotspot/src/share/vm/opto/callGenerator.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -825,10 +825,12 @@
input_not_const = false;
const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr();
ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
- guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove
const int vtable_index = Method::invalid_vtable_index;
- CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true);
- assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
+ CallGenerator* cg = C->call_generator(target, vtable_index,
+ false /* call_does_dispatch */,
+ jvms,
+ true /* allow_inline */,
+ PROB_ALWAYS);
return cg;
} else {
const char* msg = "receiver not constant";
@@ -899,13 +901,15 @@
target = C->optimize_virtual_call(caller, jvms->bci(), klass, klass,
target, receiver_type, is_virtual,
call_does_dispatch, vtable_index, // out-parameters
- /*check_access=*/false);
+ false /* check_access */);
// We lack profiling at this call but type speculation may
// provide us with a type
speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL;
}
- CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, /*allow_inline=*/true, PROB_ALWAYS, speculative_receiver_type, true, true);
- assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
+ CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms,
+ true /* allow_inline */,
+ PROB_ALWAYS,
+ speculative_receiver_type);
return cg;
} else {
const char* msg = "member_name not constant";
--- a/hotspot/src/share/vm/opto/castnode.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/castnode.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -37,7 +37,6 @@
Node* ConstraintCastNode::Identity(PhaseGVN* phase) {
Node* dom = dominating_cast(phase);
if (dom != NULL) {
- assert(_carry_dependency, "only for casts that carry a dependency");
return dom;
}
if (_carry_dependency) {
@@ -110,18 +109,22 @@
}
TypeNode* ConstraintCastNode::dominating_cast(PhaseTransform *phase) const {
- if (!carry_dependency()) {
- return NULL;
- }
Node* val = in(1);
Node* ctl = in(0);
int opc = Opcode();
if (ctl == NULL) {
return NULL;
}
+ // Range check CastIIs may all end up under a single range check and
+ // in that case only the narrower CastII would be kept by the code
+ // below which would be incorrect.
+ if (is_CastII() && as_CastII()->has_range_check()) {
+ return NULL;
+ }
for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) {
Node* u = val->fast_out(i);
if (u != this &&
+ u->outcnt() > 0 &&
u->Opcode() == opc &&
u->in(0) != NULL &&
u->bottom_type()->higher_equal(type())) {
@@ -300,7 +303,6 @@
Node* CheckCastPPNode::Identity(PhaseGVN* phase) {
Node* dom = dominating_cast(phase);
if (dom != NULL) {
- assert(_carry_dependency, "only for casts that carry a dependency");
return dom;
}
if (_carry_dependency) {
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -666,7 +666,8 @@
if (future_unroll_ct > LoopMaxUnroll) return false;
} else {
// obey user constraints on vector mapped loops with additional unrolling applied
- if ((future_unroll_ct / cl->slp_max_unroll()) > LoopMaxUnroll) return false;
+ int unroll_constraint = (cl->slp_max_unroll()) ? cl->slp_max_unroll() : 1;
+ if ((future_unroll_ct / unroll_constraint) > LoopMaxUnroll) return false;
}
// Check for initial stride being a small enough constant
@@ -689,7 +690,7 @@
// Progress defined as current size less than 20% larger than previous size.
if (UseSuperWord && cl->node_count_before_unroll() > 0 &&
future_unroll_ct > LoopUnrollMin &&
- (future_unroll_ct - 1) * 10.0 > cl->profile_trip_cnt() &&
+ (future_unroll_ct - 1) * (100 / LoopPercentProfileLimit) > cl->profile_trip_cnt() &&
1.2 * cl->node_count_before_unroll() < (double)_body.size()) {
return false;
}
@@ -1260,6 +1261,146 @@
loop->record_for_igvn();
}
+//------------------------------insert_vector_post_loop------------------------
+// Insert a copy of the atomic unrolled vectorized main loop as a post loop,
+// unroll_policy has already informed us that more unrolling is about to happen to
+// the main loop. The resultant post loop will serve as a vectorized drain loop.
+void PhaseIdealLoop::insert_vector_post_loop(IdealLoopTree *loop, Node_List &old_new) {
+ if (!loop->_head->is_CountedLoop()) return;
+
+ CountedLoopNode *cl = loop->_head->as_CountedLoop();
+
+ // only process vectorized main loops
+ if (!cl->is_vectorized_loop() || !cl->is_main_loop()) return;
+
+ int slp_max_unroll_factor = cl->slp_max_unroll();
+ int cur_unroll = cl->unrolled_count();
+
+ if (slp_max_unroll_factor == 0) return;
+
+ // only process atomic unroll vector loops (not super unrolled after vectorization)
+ if (cur_unroll != slp_max_unroll_factor) return;
+
+ // we only ever process this one time
+ if (cl->has_atomic_post_loop()) return;
+
+#ifndef PRODUCT
+ if (TraceLoopOpts) {
+ tty->print("PostVector ");
+ loop->dump_head();
+ }
+#endif
+ C->set_major_progress();
+
+ // Find common pieces of the loop being guarded with pre & post loops
+ CountedLoopNode *main_head = loop->_head->as_CountedLoop();
+ CountedLoopEndNode *main_end = main_head->loopexit();
+ guarantee(main_end != NULL, "no loop exit node");
+ // diagnostic to show loop end is not properly formed
+ assert(main_end->outcnt() == 2, "1 true, 1 false path only");
+ uint dd_main_head = dom_depth(main_head);
+ uint max = main_head->outcnt();
+
+ // mark this loop as processed
+ main_head->mark_has_atomic_post_loop();
+
+ Node *pre_header = main_head->in(LoopNode::EntryControl);
+ Node *init = main_head->init_trip();
+ Node *incr = main_end->incr();
+ Node *limit = main_end->limit();
+ Node *stride = main_end->stride();
+ Node *cmp = main_end->cmp_node();
+ BoolTest::mask b_test = main_end->test_trip();
+
+ //------------------------------
+ // Step A: Create a new post-Loop.
+ Node* main_exit = main_end->proj_out(false);
+ assert(main_exit->Opcode() == Op_IfFalse, "");
+ int dd_main_exit = dom_depth(main_exit);
+
+ // Step A1: Clone the loop body of main. The clone becomes the vector post-loop.
+ // The main loop pre-header illegally has 2 control users (old & new loops).
+ clone_loop(loop, old_new, dd_main_exit);
+ assert(old_new[main_end->_idx]->Opcode() == Op_CountedLoopEnd, "");
+ CountedLoopNode *post_head = old_new[main_head->_idx]->as_CountedLoop();
+ post_head->set_normal_loop();
+ post_head->set_post_loop(main_head);
+
+ // Reduce the post-loop trip count.
+ CountedLoopEndNode* post_end = old_new[main_end->_idx]->as_CountedLoopEnd();
+ post_end->_prob = PROB_FAIR;
+
+ // Build the main-loop normal exit.
+ IfFalseNode *new_main_exit = new IfFalseNode(main_end);
+ _igvn.register_new_node_with_optimizer(new_main_exit);
+ set_idom(new_main_exit, main_end, dd_main_exit);
+ set_loop(new_main_exit, loop->_parent);
+
+ // Step A2: Build a zero-trip guard for the vector post-loop. After leaving the
+ // main-loop, the vector post-loop may not execute at all. We 'opaque' the incr
+ // (the vectorized main-loop trip-counter exit value) because we will be changing
+ // the exit value (via additional unrolling) so we cannot constant-fold away the zero
+ // trip guard until all unrolling is done.
+ Node *zer_opaq = new Opaque1Node(C, incr);
+ Node *zer_cmp = new CmpINode(zer_opaq, limit);
+ Node *zer_bol = new BoolNode(zer_cmp, b_test);
+ register_new_node(zer_opaq, new_main_exit);
+ register_new_node(zer_cmp, new_main_exit);
+ register_new_node(zer_bol, new_main_exit);
+
+ // Build the IfNode
+ IfNode *zer_iff = new IfNode(new_main_exit, zer_bol, PROB_FAIR, COUNT_UNKNOWN);
+ _igvn.register_new_node_with_optimizer(zer_iff);
+ set_idom(zer_iff, new_main_exit, dd_main_exit);
+ set_loop(zer_iff, loop->_parent);
+
+ // Plug in the false-path, taken if we need to skip vector post-loop
+ _igvn.replace_input_of(main_exit, 0, zer_iff);
+ set_idom(main_exit, zer_iff, dd_main_exit);
+ set_idom(main_exit->unique_out(), zer_iff, dd_main_exit);
+ // Make the true-path, must enter the vector post loop
+ Node *zer_taken = new IfTrueNode(zer_iff);
+ _igvn.register_new_node_with_optimizer(zer_taken);
+ set_idom(zer_taken, zer_iff, dd_main_exit);
+ set_loop(zer_taken, loop->_parent);
+ // Plug in the true path
+ _igvn.hash_delete(post_head);
+ post_head->set_req(LoopNode::EntryControl, zer_taken);
+ set_idom(post_head, zer_taken, dd_main_exit);
+
+ Arena *a = Thread::current()->resource_area();
+ VectorSet visited(a);
+ Node_Stack clones(a, main_head->back_control()->outcnt());
+ // Step A3: Make the fall-in values to the vector post-loop come from the
+ // fall-out values of the main-loop.
+ for (DUIterator_Fast imax, i = main_head->fast_outs(imax); i < imax; i++) {
+ Node* main_phi = main_head->fast_out(i);
+ if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() >0) {
+ Node *cur_phi = old_new[main_phi->_idx];
+ Node *fallnew = clone_up_backedge_goo(main_head->back_control(),
+ post_head->init_control(),
+ main_phi->in(LoopNode::LoopBackControl),
+ visited, clones);
+ _igvn.hash_delete(cur_phi);
+ cur_phi->set_req(LoopNode::EntryControl, fallnew);
+ }
+ }
+
+ // CastII for the new post loop:
+ bool inserted = cast_incr_before_loop(zer_opaq->in(1), zer_taken, post_head);
+ assert(inserted, "no castII inserted");
+
+ // It's difficult to be precise about the trip-counts
+ // for post loops. They are usually very short,
+ // so guess that unit vector trips is a reasonable value.
+ post_head->set_profile_trip_cnt((float)slp_max_unroll_factor);
+
+ // Now force out all loop-invariant dominating tests. The optimizer
+ // finds some, but we _know_ they are all useless.
+ peeled_dom_test_elim(loop, old_new);
+ loop->record_for_igvn();
+}
+
//------------------------------is_invariant-----------------------------
// Return true if n is invariant
bool IdealLoopTree::is_invariant(Node* n) const {
@@ -2608,6 +2749,9 @@
// and we'd rather unroll the post-RCE'd loop SO... do not unroll if
// peeling.
if (should_unroll && !should_peel) {
+ if (SuperWordLoopUnrollAnalysis) {
+ phase->insert_vector_post_loop(this, old_new);
+ }
phase->do_unroll(this, old_new, true);
}
--- a/hotspot/src/share/vm/opto/loopnode.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -67,7 +67,9 @@
HasReductions=128,
WasSlpAnalyzed=256,
PassedSlpAnalysis=512,
- DoUnrollOnly=1024 };
+ DoUnrollOnly=1024,
+ VectorizedLoop=2048,
+ HasAtomicPostLoop=4096 };
char _unswitch_count;
enum { _unswitch_max=3 };
@@ -86,6 +88,8 @@
void mark_was_slp() { _loop_flags |= WasSlpAnalyzed; }
void mark_passed_slp() { _loop_flags |= PassedSlpAnalysis; }
void mark_do_unroll_only() { _loop_flags |= DoUnrollOnly; }
+ void mark_loop_vectorized() { _loop_flags |= VectorizedLoop; }
+ void mark_has_atomic_post_loop() { _loop_flags |= HasAtomicPostLoop; }
int unswitch_max() { return _unswitch_max; }
int unswitch_count() { return _unswitch_count; }
@@ -221,6 +225,8 @@
int has_passed_slp () const { return (_loop_flags&PassedSlpAnalysis) == PassedSlpAnalysis; }
int do_unroll_only () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; }
int is_main_no_pre_loop() const { return _loop_flags & MainHasNoPreLoop; }
+ int is_vectorized_loop () const { return (_loop_flags & VectorizedLoop) == VectorizedLoop; }
+ int has_atomic_post_loop () const { return (_loop_flags & HasAtomicPostLoop) == HasAtomicPostLoop; }
void set_main_no_pre_loop() { _loop_flags |= MainHasNoPreLoop; }
int main_idx() const { return _main_idx; }
@@ -893,6 +899,8 @@
// Add pre and post loops around the given loop. These loops are used
// during RCE, unrolling and aligning loops.
void insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only );
+ // Add a vector post loop between a vector main loop and the current post loop
+ void insert_vector_post_loop(IdealLoopTree *loop, Node_List &old_new);
// If Node n lives in the back_ctrl block, we clone a private version of n
// in preheader_ctrl block and return that, otherwise return n.
Node *clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones );
@@ -1105,6 +1113,8 @@
Node *place_near_use( Node *useblock ) const;
Node* try_move_store_before_loop(Node* n, Node *n_ctrl);
void try_move_store_after_loop(Node* n);
+ bool identical_backtoback_ifs(Node *n);
+ bool can_split_if(Node *n_ctrl);
bool _created_loop_node;
public:
--- a/hotspot/src/share/vm/opto/loopopts.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -47,6 +47,14 @@
return NULL;
}
+ // Splitting range check CastIIs through a loop induction Phi can
+ // cause new Phis to be created that are left unrelated to the loop
+ // induction Phi and prevent optimizations (vectorization)
+ if (n->Opcode() == Op_CastII && n->as_CastII()->has_range_check() &&
+ region->is_CountedLoop() && n->in(1) == region->as_CountedLoop()->phi()) {
+ return NULL;
+ }
+
int wins = 0;
assert(!n->is_CFG(), "");
assert(region->is_Region(), "");
@@ -1020,108 +1028,193 @@
}
+bool PhaseIdealLoop::identical_backtoback_ifs(Node *n) {
+ if (!n->is_If()) {
+ return false;
+ }
+ if (!n->in(0)->is_Region()) {
+ return false;
+ }
+ Node* region = n->in(0);
+ Node* dom = idom(region);
+ if (!dom->is_If() || dom->in(1) != n->in(1)) {
+ return false;
+ }
+ IfNode* dom_if = dom->as_If();
+ Node* proj_true = dom_if->proj_out(1);
+ Node* proj_false = dom_if->proj_out(0);
+
+ for (uint i = 1; i < region->req(); i++) {
+ if (is_dominator(proj_true, region->in(i))) {
+ continue;
+ }
+ if (is_dominator(proj_false, region->in(i))) {
+ continue;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool PhaseIdealLoop::can_split_if(Node *n_ctrl) {
+ if (C->live_nodes() > 35000) {
+ return false; // Method too big
+ }
+
+ // Do not do 'split-if' if irreducible loops are present.
+ if (_has_irreducible_loops) {
+ return false;
+ }
+
+ if (merge_point_too_heavy(C, n_ctrl)) {
+ return false;
+ }
+
+ // Do not do 'split-if' if some paths are dead. First do dead code
+ // elimination and then see if its still profitable.
+ for (uint i = 1; i < n_ctrl->req(); i++) {
+ if (n_ctrl->in(i) == C->top()) {
+ return false;
+ }
+ }
+
+ // If trying to do a 'Split-If' at the loop head, it is only
+ // profitable if the cmp folds up on BOTH paths. Otherwise we
+ // risk peeling a loop forever.
+
+ // CNC - Disabled for now. Requires careful handling of loop
+ // body selection for the cloned code. Also, make sure we check
+ // for any input path not being in the same loop as n_ctrl. For
+ // irreducible loops we cannot check for 'n_ctrl->is_Loop()'
+ // because the alternative loop entry points won't be converted
+ // into LoopNodes.
+ IdealLoopTree *n_loop = get_loop(n_ctrl);
+ for (uint j = 1; j < n_ctrl->req(); j++) {
+ if (get_loop(n_ctrl->in(j)) != n_loop) {
+ return false;
+ }
+ }
+
+ // Check for safety of the merge point.
+ if (!merge_point_safe(n_ctrl)) {
+ return false;
+ }
+
+ return true;
+}
+
//------------------------------split_if_with_blocks_post----------------------
// Do the real work in a non-recursive function. CFG hackery wants to be
// in the post-order, so it can dirty the I-DOM info and not use the dirtied
// info.
-void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
+void PhaseIdealLoop::split_if_with_blocks_post(Node *n) {
// Cloning Cmp through Phi's involves the split-if transform.
// FastLock is not used by an If
- if( n->is_Cmp() && !n->is_FastLock() ) {
- if( C->live_nodes() > 35000 ) return; // Method too big
-
- // Do not do 'split-if' if irreducible loops are present.
- if( _has_irreducible_loops )
- return;
-
+ if (n->is_Cmp() && !n->is_FastLock()) {
Node *n_ctrl = get_ctrl(n);
// Determine if the Node has inputs from some local Phi.
// Returns the block to clone thru.
- Node *n_blk = has_local_phi_input( n );
- if( n_blk != n_ctrl ) return;
+ Node *n_blk = has_local_phi_input(n);
+ if (n_blk != n_ctrl) {
+ return;
+ }
- if( merge_point_too_heavy(C, n_ctrl) )
+ if (!can_split_if(n_ctrl)) {
return;
+ }
- if( n->outcnt() != 1 ) return; // Multiple bool's from 1 compare?
+ if (n->outcnt() != 1) {
+ return; // Multiple bool's from 1 compare?
+ }
Node *bol = n->unique_out();
- assert( bol->is_Bool(), "expect a bool here" );
- if( bol->outcnt() != 1 ) return;// Multiple branches from 1 compare?
+ assert(bol->is_Bool(), "expect a bool here");
+ if (bol->outcnt() != 1) {
+ return;// Multiple branches from 1 compare?
+ }
Node *iff = bol->unique_out();
// Check some safety conditions
- if( iff->is_If() ) { // Classic split-if?
- if( iff->in(0) != n_ctrl ) return; // Compare must be in same blk as if
+ if (iff->is_If()) { // Classic split-if?
+ if (iff->in(0) != n_ctrl) {
+ return; // Compare must be in same blk as if
+ }
} else if (iff->is_CMove()) { // Trying to split-up a CMOVE
// Can't split CMove with different control edge.
- if (iff->in(0) != NULL && iff->in(0) != n_ctrl ) return;
- if( get_ctrl(iff->in(2)) == n_ctrl ||
- get_ctrl(iff->in(3)) == n_ctrl )
+ if (iff->in(0) != NULL && iff->in(0) != n_ctrl ) {
+ return;
+ }
+ if (get_ctrl(iff->in(2)) == n_ctrl ||
+ get_ctrl(iff->in(3)) == n_ctrl) {
return; // Inputs not yet split-up
- if ( get_loop(n_ctrl) != get_loop(get_ctrl(iff)) ) {
+ }
+ if (get_loop(n_ctrl) != get_loop(get_ctrl(iff))) {
return; // Loop-invar test gates loop-varying CMOVE
}
} else {
return; // some other kind of node, such as an Allocate
}
- // Do not do 'split-if' if some paths are dead. First do dead code
- // elimination and then see if its still profitable.
- for( uint i = 1; i < n_ctrl->req(); i++ )
- if( n_ctrl->in(i) == C->top() )
- return;
-
// When is split-if profitable? Every 'win' on means some control flow
// goes dead, so it's almost always a win.
int policy = 0;
- // If trying to do a 'Split-If' at the loop head, it is only
- // profitable if the cmp folds up on BOTH paths. Otherwise we
- // risk peeling a loop forever.
-
- // CNC - Disabled for now. Requires careful handling of loop
- // body selection for the cloned code. Also, make sure we check
- // for any input path not being in the same loop as n_ctrl. For
- // irreducible loops we cannot check for 'n_ctrl->is_Loop()'
- // because the alternative loop entry points won't be converted
- // into LoopNodes.
- IdealLoopTree *n_loop = get_loop(n_ctrl);
- for( uint j = 1; j < n_ctrl->req(); j++ )
- if( get_loop(n_ctrl->in(j)) != n_loop )
- return;
-
- // Check for safety of the merge point.
- if( !merge_point_safe(n_ctrl) ) {
+ // Split compare 'n' through the merge point if it is profitable
+ Node *phi = split_thru_phi( n, n_ctrl, policy);
+ if (!phi) {
return;
}
- // Split compare 'n' through the merge point if it is profitable
- Node *phi = split_thru_phi( n, n_ctrl, policy );
- if( !phi ) return;
-
// Found a Phi to split thru!
// Replace 'n' with the new phi
- _igvn.replace_node( n, phi );
+ _igvn.replace_node(n, phi);
// Now split the bool up thru the phi
- Node *bolphi = split_thru_phi( bol, n_ctrl, -1 );
+ Node *bolphi = split_thru_phi(bol, n_ctrl, -1);
guarantee(bolphi != NULL, "null boolean phi node");
- _igvn.replace_node( bol, bolphi );
- assert( iff->in(1) == bolphi, "" );
+ _igvn.replace_node(bol, bolphi);
+ assert(iff->in(1) == bolphi, "");
- if( bolphi->Value(&_igvn)->singleton() )
+ if (bolphi->Value(&_igvn)->singleton()) {
return;
+ }
// Conditional-move? Must split up now
- if( !iff->is_If() ) {
- Node *cmovphi = split_thru_phi( iff, n_ctrl, -1 );
- _igvn.replace_node( iff, cmovphi );
+ if (!iff->is_If()) {
+ Node *cmovphi = split_thru_phi(iff, n_ctrl, -1);
+ _igvn.replace_node(iff, cmovphi);
return;
}
// Now split the IF
- do_split_if( iff );
+ do_split_if(iff);
+ return;
+ }
+
+ // Two identical ifs back to back can be merged
+ if (identical_backtoback_ifs(n) && can_split_if(n->in(0))) {
+ Node *n_ctrl = n->in(0);
+ PhiNode* bolphi = PhiNode::make_blank(n_ctrl, n->in(1));
+ IfNode* dom_if = idom(n_ctrl)->as_If();
+ Node* proj_true = dom_if->proj_out(1);
+ Node* proj_false = dom_if->proj_out(0);
+ Node* con_true = _igvn.makecon(TypeInt::ONE);
+ Node* con_false = _igvn.makecon(TypeInt::ZERO);
+
+ for (uint i = 1; i < n_ctrl->req(); i++) {
+ if (is_dominator(proj_true, n_ctrl->in(i))) {
+ bolphi->init_req(i, con_true);
+ } else {
+ assert(is_dominator(proj_false, n_ctrl->in(i)), "bad if");
+ bolphi->init_req(i, con_false);
+ }
+ }
+ register_new_node(bolphi, n_ctrl);
+ _igvn.replace_input_of(n, 1, bolphi);
+
+ // Now split the IF
+ do_split_if(n);
return;
}
--- a/hotspot/src/share/vm/opto/memnode.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/memnode.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1709,38 +1709,10 @@
// unsafe field access may not have a constant offset
C->has_unsafe_access(),
"Field accesses must be precise" );
- // For oop loads, we expect the _type to be precise
- if (klass == env->String_klass() &&
- adr->is_AddP() && off != Type::OffsetBot) {
- // For constant Strings treat the final fields as compile time constants.
- // While we can list what field types java.lang.String has, it is more
- // future-proof to handle all possible field types, anticipating future
- // changes and experiments in String code.
- Node* base = adr->in(AddPNode::Base);
- const TypeOopPtr* t = phase->type(base)->isa_oopptr();
- if (t != NULL && t->singleton()) {
- ciField* field = env->String_klass()->get_field_by_offset(off, false);
- if (field != NULL && field->is_final()) {
- ciObject* string = t->const_oop();
- ciConstant constant = string->as_instance()->field_value(field);
- // Type::make_from_constant does not handle narrow oops, so handle it here.
- // Everything else can use the factory method.
- if ((constant.basic_type() == T_ARRAY || constant.basic_type() == T_OBJECT)
- && adr->bottom_type()->is_ptr_to_narrowoop()) {
- return TypeNarrowOop::make_from_constant(constant.as_object(), true);
- } else {
- return Type::make_from_constant(constant, true);
- }
- }
- }
- }
+ // For oop loads, we expect the _type to be precise.
// Optimizations for constant objects
ciObject* const_oop = tinst->const_oop();
if (const_oop != NULL) {
- // For constant Boxed value treat the target field as a compile time constant.
- if (tinst->is_ptr_to_boxed_value()) {
- return tinst->get_const_boxed_value();
- } else
// For constant CallSites treat the target field as a compile time constant.
if (const_oop->is_call_site()) {
ciCallSite* call_site = const_oop->as_call_site();
--- a/hotspot/src/share/vm/opto/stringopts.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/stringopts.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1552,8 +1552,7 @@
if (str->is_Con()) {
// Constant source string
- const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
- ciTypeArray* src_array_type = t->const_oop()->as_type_array();
+ ciTypeArray* src_array_type = get_constant_value(kit, str);
// Check encoding of constant string
bool src_is_byte = (get_constant_coder(kit, str) == java_lang_String::CODER_LATIN1);
@@ -1673,9 +1672,15 @@
int PhaseStringOpts::get_constant_length(GraphKit& kit, Node* str) {
assert(str->is_Con(), "String must be constant");
- Node* src_array = kit.load_String_value(kit.control(), str);
- const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
- return t->const_oop()->as_type_array()->length();
+ return get_constant_value(kit, str)->length();
+}
+
+ciTypeArray* PhaseStringOpts::get_constant_value(GraphKit& kit, Node* str) {
+ assert(str->is_Con(), "String must be constant");
+ const TypeOopPtr* str_type = kit.gvn().type(str)->isa_oopptr();
+ ciInstance* str_instance = str_type->const_oop()->as_instance();
+ ciObject* src_array = str_instance->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
+ return src_array->as_type_array();
}
void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
--- a/hotspot/src/share/vm/opto/stringopts.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/stringopts.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -97,6 +97,9 @@
// Returns the length of a constant string
int get_constant_length(GraphKit& kit, Node* str);
+ // Returns the value array of a constant string
+ ciTypeArray* get_constant_value(GraphKit& kit, Node* str);
+
// Clean up any leftover nodes
void record_dead_node(Node* node);
void remove_dead_nodes();
--- a/hotspot/src/share/vm/opto/superword.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/opto/superword.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -2253,6 +2253,9 @@
C->set_major_progress();
}
cl->mark_do_unroll_only();
+ if (do_reserve_copy()) {
+ cl->mark_loop_vectorized();
+ }
}
}
}
--- a/hotspot/src/share/vm/prims/methodComparator.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodComparator.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,6 @@
BytecodeStream *MethodComparator::_s_new;
ConstantPool* MethodComparator::_old_cp;
ConstantPool* MethodComparator::_new_cp;
-BciMap *MethodComparator::_bci_map;
-bool MethodComparator::_switchable_test;
-GrowableArray<int> *MethodComparator::_fwd_jmps;
bool MethodComparator::methods_EMCP(Method* old_method, Method* new_method) {
if (old_method->code_size() != new_method->code_size())
@@ -55,7 +52,6 @@
BytecodeStream s_new(new_method);
_s_old = &s_old;
_s_new = &s_new;
- _switchable_test = false;
Bytecodes::Code c_old, c_new;
while ((c_old = s_old.next()) >= 0) {
@@ -68,64 +64,6 @@
return true;
}
-
-bool MethodComparator::methods_switchable(Method* old_method, Method* new_method,
- BciMap &bci_map) {
- if (old_method->code_size() > new_method->code_size())
- // Something has definitely been deleted in the new method, compared to the old one.
- return false;
-
- if (! check_stack_and_locals_size(old_method, new_method))
- return false;
-
- _old_cp = old_method->constants();
- _new_cp = new_method->constants();
- BytecodeStream s_old(old_method);
- BytecodeStream s_new(new_method);
- _s_old = &s_old;
- _s_new = &s_new;
- _bci_map = &bci_map;
- _switchable_test = true;
- GrowableArray<int> fwd_jmps(16);
- _fwd_jmps = &fwd_jmps;
- Bytecodes::Code c_old, c_new;
-
- while ((c_old = s_old.next()) >= 0) {
- if ((c_new = s_new.next()) < 0)
- return false;
- if (! (c_old == c_new && args_same(c_old, c_new))) {
- int old_bci = s_old.bci();
- int new_st_bci = s_new.bci();
- bool found_match = false;
- do {
- c_new = s_new.next();
- if (c_new == c_old && args_same(c_old, c_new)) {
- found_match = true;
- break;
- }
- } while (c_new >= 0);
- if (! found_match)
- return false;
- int new_end_bci = s_new.bci();
- bci_map.store_fragment_location(old_bci, new_st_bci, new_end_bci);
- }
- }
-
- // Now we can test all forward jumps
- for (int i = 0; i < fwd_jmps.length() / 2; i++) {
- if (! bci_map.old_and_new_locations_same(fwd_jmps.at(i*2), fwd_jmps.at(i*2+1))) {
- RC_TRACE(0x00800000,
- ("Fwd jump miss: old dest = %d, calc new dest = %d, act new dest = %d",
- fwd_jmps.at(i*2), bci_map.new_bci_for_old(fwd_jmps.at(i*2)),
- fwd_jmps.at(i*2+1)));
- return false;
- }
- }
-
- return true;
-}
-
-
bool MethodComparator::args_same(Bytecodes::Code c_old, Bytecodes::Code c_new) {
// BytecodeStream returns the correct standard Java bytecodes for various "fast"
// bytecode versions, so we don't have to bother about them here..
@@ -275,22 +213,8 @@
case Bytecodes::_jsr : {
int old_ofs = _s_old->bytecode().get_offset_s2(c_old);
int new_ofs = _s_new->bytecode().get_offset_s2(c_new);
- if (_switchable_test) {
- int old_dest = _s_old->bci() + old_ofs;
- int new_dest = _s_new->bci() + new_ofs;
- if (old_ofs < 0 && new_ofs < 0) {
- if (! _bci_map->old_and_new_locations_same(old_dest, new_dest))
- return false;
- } else if (old_ofs > 0 && new_ofs > 0) {
- _fwd_jmps->append(old_dest);
- _fwd_jmps->append(new_dest);
- } else {
- return false;
- }
- } else {
- if (old_ofs != new_ofs)
- return false;
- }
+ if (old_ofs != new_ofs)
+ return false;
break;
}
@@ -312,73 +236,19 @@
case Bytecodes::_jsr_w : {
int old_ofs = _s_old->bytecode().get_offset_s4(c_old);
int new_ofs = _s_new->bytecode().get_offset_s4(c_new);
- if (_switchable_test) {
- int old_dest = _s_old->bci() + old_ofs;
- int new_dest = _s_new->bci() + new_ofs;
- if (old_ofs < 0 && new_ofs < 0) {
- if (! _bci_map->old_and_new_locations_same(old_dest, new_dest))
- return false;
- } else if (old_ofs > 0 && new_ofs > 0) {
- _fwd_jmps->append(old_dest);
- _fwd_jmps->append(new_dest);
- } else {
- return false;
- }
- } else {
- if (old_ofs != new_ofs)
- return false;
- }
+ if (old_ofs != new_ofs)
+ return false;
break;
}
case Bytecodes::_lookupswitch : // fall through
case Bytecodes::_tableswitch : {
- if (_switchable_test) {
- address aligned_bcp_old = (address) round_to((intptr_t)_s_old->bcp() + 1, jintSize);
- address aligned_bcp_new = (address) round_to((intptr_t)_s_new->bcp() + 1, jintSize);
- int default_old = (int) Bytes::get_Java_u4(aligned_bcp_old);
- int default_new = (int) Bytes::get_Java_u4(aligned_bcp_new);
- _fwd_jmps->append(_s_old->bci() + default_old);
- _fwd_jmps->append(_s_new->bci() + default_new);
- if (c_old == Bytecodes::_lookupswitch) {
- int npairs_old = (int) Bytes::get_Java_u4(aligned_bcp_old + jintSize);
- int npairs_new = (int) Bytes::get_Java_u4(aligned_bcp_new + jintSize);
- if (npairs_old != npairs_new)
- return false;
- for (int i = 0; i < npairs_old; i++) {
- int match_old = (int) Bytes::get_Java_u4(aligned_bcp_old + (2+2*i)*jintSize);
- int match_new = (int) Bytes::get_Java_u4(aligned_bcp_new + (2+2*i)*jintSize);
- if (match_old != match_new)
- return false;
- int ofs_old = (int) Bytes::get_Java_u4(aligned_bcp_old + (2+2*i+1)*jintSize);
- int ofs_new = (int) Bytes::get_Java_u4(aligned_bcp_new + (2+2*i+1)*jintSize);
- _fwd_jmps->append(_s_old->bci() + ofs_old);
- _fwd_jmps->append(_s_new->bci() + ofs_new);
- }
- } else if (c_old == Bytecodes::_tableswitch) {
- int lo_old = (int) Bytes::get_Java_u4(aligned_bcp_old + jintSize);
- int lo_new = (int) Bytes::get_Java_u4(aligned_bcp_new + jintSize);
- if (lo_old != lo_new)
- return false;
- int hi_old = (int) Bytes::get_Java_u4(aligned_bcp_old + 2*jintSize);
- int hi_new = (int) Bytes::get_Java_u4(aligned_bcp_new + 2*jintSize);
- if (hi_old != hi_new)
- return false;
- for (int i = 0; i < hi_old - lo_old + 1; i++) {
- int ofs_old = (int) Bytes::get_Java_u4(aligned_bcp_old + (3+i)*jintSize);
- int ofs_new = (int) Bytes::get_Java_u4(aligned_bcp_new + (3+i)*jintSize);
- _fwd_jmps->append(_s_old->bci() + ofs_old);
- _fwd_jmps->append(_s_new->bci() + ofs_new);
- }
- }
- } else { // !_switchable_test, can use fast rough compare
- int len_old = _s_old->instruction_size();
- int len_new = _s_new->instruction_size();
- if (len_old != len_new)
- return false;
- if (memcmp(_s_old->bcp(), _s_new->bcp(), len_old) != 0)
- return false;
- }
+ int len_old = _s_old->instruction_size();
+ int len_new = _s_new->instruction_size();
+ if (len_old != len_new)
+ return false;
+ if (memcmp(_s_old->bcp(), _s_new->bcp(), len_old) != 0)
+ return false;
break;
}
}
--- a/hotspot/src/share/vm/prims/methodComparator.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodComparator.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,6 @@
#include "oops/constantPool.hpp"
#include "oops/method.hpp"
-class BciMap;
-
// methodComparator provides an interface for determining if methods of
// different versions of classes are equivalent or switchable
@@ -39,9 +37,6 @@
static BytecodeStream *_s_old, *_s_new;
static ConstantPool* _old_cp;
static ConstantPool* _new_cp;
- static BciMap *_bci_map;
- static bool _switchable_test;
- static GrowableArray<int> *_fwd_jmps;
static bool args_same(Bytecodes::Code c_old, Bytecodes::Code c_new);
static bool pool_constants_same(int cpi_old, int cpi_new);
@@ -55,79 +50,6 @@
// these indices eventually point to the same constants for both method versions.
static bool methods_EMCP(Method* old_method, Method* new_method);
- static bool methods_switchable(Method* old_method, Method* new_method, BciMap &bci_map);
-};
-
-
-// ByteCode Index Map. For two versions of the same method, where the new version may contain
-// fragments not found in the old version, provides a mapping from an index of a bytecode in
-// the old method to the index of the same bytecode in the new method.
-
-class BciMap {
- private:
- int *_old_bci, *_new_st_bci, *_new_end_bci;
- int _cur_size, _cur_pos;
- int _pos;
-
- public:
- BciMap() {
- _cur_size = 50;
- _old_bci = (int*) malloc(sizeof(int) * _cur_size);
- _new_st_bci = (int*) malloc(sizeof(int) * _cur_size);
- _new_end_bci = (int*) malloc(sizeof(int) * _cur_size);
- _cur_pos = 0;
- }
-
- ~BciMap() {
- free(_old_bci);
- free(_new_st_bci);
- free(_new_end_bci);
- }
-
- // Store the position of an added fragment, e.g.
- //
- // |<- old_bci
- // -----------------------------------------
- // Old method |invokevirtual 5|aload 1|...
- // -----------------------------------------
- //
- // |<- new_st_bci |<- new_end_bci
- // --------------------------------------------------------------------
- // New method |invokevirual 5|aload 2|invokevirtual 6|aload 1|...
- // --------------------------------------------------------------------
- // ^^^^^^^^^^^^^^^^^^^^^^^^
- // Added fragment
-
- void store_fragment_location(int old_bci, int new_st_bci, int new_end_bci) {
- if (_cur_pos == _cur_size) {
- _cur_size += 10;
- _old_bci = (int*) realloc(_old_bci, sizeof(int) * _cur_size);
- _new_st_bci = (int*) realloc(_new_st_bci, sizeof(int) * _cur_size);
- _new_end_bci = (int*) realloc(_new_end_bci, sizeof(int) * _cur_size);
- }
- _old_bci[_cur_pos] = old_bci;
- _new_st_bci[_cur_pos] = new_st_bci;
- _new_end_bci[_cur_pos] = new_end_bci;
- _cur_pos++;
- }
-
- int new_bci_for_old(int old_bci) {
- if (_cur_pos == 0 || old_bci < _old_bci[0]) return old_bci;
- _pos = 1;
- while (_pos < _cur_pos && old_bci >= _old_bci[_pos])
- _pos++;
- return _new_end_bci[_pos-1] + (old_bci - _old_bci[_pos-1]);
- }
-
- // Test if two indexes - one in the old method and another in the new one - correspond
- // to the same bytecode
- bool old_and_new_locations_same(int old_dest_bci, int new_dest_bci) {
- if (new_bci_for_old(old_dest_bci) == new_dest_bci)
- return true;
- else if (_old_bci[_pos-1] == old_dest_bci)
- return (new_dest_bci == _new_st_bci[_pos-1]);
- else return false;
- }
};
#endif // SHARE_VM_PRIMS_METHODCOMPARATOR_HPP
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -63,30 +63,21 @@
bool MethodHandles::_enabled = false; // set true after successful native linkage
MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL;
-
/**
* Generates method handle adapters. Returns 'false' if memory allocation
* failed and true otherwise.
*/
-bool MethodHandles::generate_adapters() {
- if (SystemDictionary::MethodHandle_klass() == NULL) {
- return true;
- }
-
+void MethodHandles::generate_adapters() {
+ assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present");
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) {
- return false;
- }
-
CodeBuffer code(_adapter_code);
MethodHandlesAdapterGenerator g(&code);
g.generate();
code.log_section_sizes("MethodHandlesAdapterBlob");
- return true;
}
//------------------------------------------------------------------------------
@@ -1436,53 +1427,31 @@
};
/**
- * Helper method to register native methods.
- */
-static bool register_natives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) {
- int status = env->RegisterNatives(clazz, methods, nMethods);
- if (status != JNI_OK || env->ExceptionOccurred()) {
- warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
- env->ExceptionClear();
- return false;
- }
- return true;
-}
-
-/**
* This one function is exported, used by NativeLookup.
*/
JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
assert(!MethodHandles::enabled(), "must not be enabled");
- bool enable_MH = true;
+ assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present");
- jclass MH_class = NULL;
- if (SystemDictionary::MethodHandle_klass() == NULL) {
- enable_MH = false;
- } else {
- oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror();
- MH_class = (jclass) JNIHandles::make_local(env, mirror);
- }
+ oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror();
+ jclass MH_class = (jclass) JNIHandles::make_local(env, mirror);
- if (enable_MH) {
+ {
ThreadToNativeFromVM ttnfv(thread);
- if (enable_MH) {
- enable_MH = register_natives(env, MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod));
- }
- if (enable_MH) {
- enable_MH = register_natives(env, MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
- }
+ int status = env->RegisterNatives(MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod));
+ guarantee(status == JNI_OK && !env->ExceptionOccurred(),
+ "register java.lang.invoke.MethodHandleNative natives");
+
+ status = env->RegisterNatives(MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
+ guarantee(status == JNI_OK && !env->ExceptionOccurred(),
+ "register java.lang.invoke.MethodHandle natives");
}
if (TraceInvokeDynamic) {
tty->print_cr("MethodHandle support loaded (using LambdaForms)");
}
- if (enable_MH) {
- if (MethodHandles::generate_adapters() == false) {
- THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), "Out of space in CodeCache for method handle adapters");
- }
- MethodHandles::set_enabled(true);
- }
+ MethodHandles::set_enabled(true);
}
JVM_END
--- a/hotspot/src/share/vm/prims/methodHandles.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -81,7 +81,7 @@
static void flush_dependent_nmethods(Handle call_site, Handle target);
// Generate MethodHandles adapters.
- static bool generate_adapters();
+ static void 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 Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -660,6 +660,36 @@
Copy::conjoint_memory_atomic(src, dst, sz);
UNSAFE_END
+// This function is a leaf since if the source and destination are both in native memory
+// the copy may potentially be very large, and we don't want to disable GC if we can avoid it.
+// If either source or destination (or both) are on the heap, the function will enter VM using
+// JVM_ENTRY_FROM_LEAF
+JVM_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) {
+ UnsafeWrapper("Unsafe_CopySwapMemory0");
+
+ size_t sz = (size_t)size;
+ size_t esz = (size_t)elemSize;
+
+ if (srcObj == NULL && dstObj == NULL) {
+ // Both src & dst are in native memory
+ address src = (address)srcOffset;
+ address dst = (address)dstOffset;
+
+ Copy::conjoint_swap(src, dst, sz, esz);
+ } else {
+ // At least one of src/dst are on heap, transition to VM to access raw pointers
+
+ JVM_ENTRY_FROM_LEAF(env, void, Unsafe_CopySwapMemory0) {
+ oop srcp = JNIHandles::resolve(srcObj);
+ oop dstp = JNIHandles::resolve(dstObj);
+
+ address src = (address)index_oop_from_field_offset_long(srcp, srcOffset);
+ address dst = (address)index_oop_from_field_offset_long(dstp, dstOffset);
+
+ Copy::conjoint_swap(src, dst, sz, esz);
+ } JVM_END
+ }
+} JVM_END
////// Random queries
@@ -1363,6 +1393,7 @@
{CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)},
{CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)},
+ {CC "copySwapMemory0", CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
{CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)},
{CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)},
--- a/hotspot/src/share/vm/runtime/arguments.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -333,6 +333,8 @@
// --- Non-alias flags - sorted by obsolete_in then expired_in:
{ "MaxGCMinorPauseMillis", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() },
{ "UseParNewGC", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::jdk(10) },
+ { "ConvertSleepToYield", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
+ { "ConvertYieldToSleep", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
// --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
{ "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() },
--- a/hotspot/src/share/vm/runtime/globals.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/globals.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1239,9 +1239,8 @@
product_pd(bool, DontYieldALot, \
"Throw away obvious excess yield calls") \
\
- product_pd(bool, ConvertSleepToYield, \
- "Convert sleep(0) to thread yield " \
- "(may be off for Solaris to improve GUI)") \
+ product(bool, ConvertSleepToYield, true, \
+ "Convert sleep(0) to thread yield ") \
\
product(bool, ConvertYieldToSleep, false, \
"Convert yield to a sleep of MinSleepInterval to simulate Win32 " \
@@ -1279,10 +1278,6 @@
experimental(intx, hashCode, 5, \
"(Unstable) select hashCode generation algorithm") \
\
- experimental(intx, WorkAroundNPTLTimedWaitHang, 0, \
- "(Unstable, Linux-specific) " \
- "avoid NPTL-FUTEX hang pthread_cond_timedwait") \
- \
product(bool, FilterSpuriousWakeups, true, \
"When true prevents OS-level spurious, or premature, wakeups " \
"from Object.wait (Ignored for Windows)") \
@@ -2012,11 +2007,15 @@
range(min_intx, 100) \
\
product(uintx, InitiatingHeapOccupancyPercent, 45, \
- "Percentage of the (entire) heap occupancy to start a " \
- "concurrent GC cycle. It is used by GCs that trigger a " \
- "concurrent GC cycle based on the occupancy of the entire heap, " \
- "not just one of the generations (e.g., G1). A value of 0 " \
- "denotes 'do constant GC cycles'.") \
+ "The percent occupancy (IHOP) of the current old generation " \
+ "capacity above which a concurrent mark cycle will be initiated " \
+ "Its value may change over time if adaptive IHOP is enabled, " \
+ "otherwise the value remains constant. " \
+ "In the latter case a value of 0 will result as frequent as " \
+ "possible concurrent marking cycles. A value of 100 disables " \
+ "concurrent marking. " \
+ "Fragmentation waste in the old generation is not considered " \
+ "free space in this calculation. (G1 collector only)") \
range(0, 100) \
\
manageable(intx, CMSTriggerInterval, -1, \
--- a/hotspot/src/share/vm/runtime/init.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/init.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -145,6 +145,7 @@
}
javaClasses_init(); // must happen after vtable initialization
stubRoutines_init2(); // note: StubRoutines need 2-phase init
+ MethodHandles::generate_adapters();
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::StubRoutines2);
#if INCLUDE_NMT
@@ -181,8 +182,7 @@
}
}
-
-static bool _init_completed = false;
+static volatile bool _init_completed = false;
bool is_init_completed() {
return _init_completed;
--- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -417,6 +417,14 @@
os::verify_stack_alignment(); \
/* begin of body */
+#define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) \
+ TRACE_CALL(result_type, header) \
+ debug_only(ResetNoHandleMark __rnhm;) \
+ HandleMarkCleaner __hm(thread); \
+ Thread* THREAD = thread; \
+ os::verify_stack_alignment(); \
+ /* begin of body */
+
// ENTRY routines may lock, GC and throw exceptions
@@ -584,6 +592,14 @@
VM_LEAF_BASE(result_type, header)
+#define JVM_ENTRY_FROM_LEAF(env, result_type, header) \
+ { { \
+ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
+ ThreadInVMfromNative __tiv(thread); \
+ debug_only(VMNativeEntryWrapper __vew;) \
+ VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread)
+
+
#define JVM_END } }
#endif // SHARE_VM_RUNTIME_INTERFACESUPPORT_HPP
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -359,6 +359,11 @@
static address clean_opt_virtual_call_entry();
static address clean_static_call_entry();
+#if defined(X86) && defined(COMPILER1)
+ // For Object.hashCode, System.identityHashCode try to pull hashCode from object header if available.
+ static void inline_check_hashcode_from_object_header(MacroAssembler* masm, methodHandle method, Register obj_reg, Register result);
+#endif // X86 && COMPILER1
+
public:
// Read the array of BasicTypes from a Java signature, and compute where
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -37,7 +37,7 @@
StubCodeDesc* StubCodeDesc::_list = NULL;
int StubCodeDesc::_count = 0;
-
+bool StubCodeDesc::_frozen = false;
StubCodeDesc* StubCodeDesc::desc_for(address pc) {
StubCodeDesc* p = _list;
@@ -46,20 +46,23 @@
return p;
}
-
StubCodeDesc* StubCodeDesc::desc_for_index(int index) {
StubCodeDesc* p = _list;
while (p != NULL && p->index() != index) p = p->_next;
return p;
}
-
const char* StubCodeDesc::name_for(address pc) {
StubCodeDesc* p = desc_for(pc);
return p == NULL ? NULL : p->name();
}
+void StubCodeDesc::freeze() {
+ assert(!_frozen, "repeated freeze operation");
+ _frozen = true;
+}
+
void StubCodeDesc::print_on(outputStream* st) const {
st->print("%s", group());
st->print("::");
@@ -110,12 +113,10 @@
}
}
-
void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
// default implementation - do nothing
}
-
void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) {
// default implementation - record the cdesc
if (_first_stub == NULL) _first_stub = cdesc;
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -28,7 +28,7 @@
#include "asm/assembler.hpp"
#include "memory/allocation.hpp"
-// All the basic framework for stubcode generation/debugging/printing.
+// All the basic framework for stub code generation/debugging/printing.
// A StubCodeDesc describes a piece of generated code (usually stubs).
@@ -37,9 +37,10 @@
// this may have to change if searching becomes too slow.
class StubCodeDesc: public CHeapObj<mtCode> {
- protected:
+ private:
static StubCodeDesc* _list; // the list of all descriptors
static int _count; // length of list
+ static bool _frozen; // determines whether _list modifications are allowed
StubCodeDesc* _next; // the next element in the linked list
const char* _group; // the group to which the stub code belongs
@@ -68,6 +69,7 @@
static const char* name_for(address pc); // returns the name of the code containing pc or NULL
StubCodeDesc(const char* group, const char* name, address begin, address end = NULL) {
+ assert(!_frozen, "no modifications allowed");
assert(name != NULL, "no name specified");
_next = _list;
_group = group;
@@ -78,6 +80,8 @@
_list = this;
};
+ static void freeze();
+
const char* group() const { return _group; }
const char* name() const { return _name; }
int index() const { return _index; }
@@ -117,7 +121,7 @@
// later via an address pointing into it.
class StubCodeMark: public StackObj {
- protected:
+ private:
StubCodeGenerator* _cgen;
StubCodeDesc* _cdesc;
--- a/hotspot/src/share/vm/runtime/thread.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/runtime/thread.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -3600,6 +3600,9 @@
vm_exit_during_initialization("Failed to initialize tracing backend");
}
+ // No more stub generation allowed after that point.
+ StubCodeDesc::freeze();
+
// Set flag that basic initialization has completed. Used by exceptions and various
// debug stuff, that does not work until all basic classes have been initialized.
set_init_completed();
--- a/hotspot/src/share/vm/trace/trace.xml Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/trace/trace.xml Sat Mar 05 20:46:44 2016 -0800
@@ -283,6 +283,7 @@
<value type="BYTES64" field="edenUsedSize" label="Eden Used Size" />
<value type="BYTES64" field="edenTotalSize" label="Eden Total Size" />
<value type="BYTES64" field="survivorUsedSize" label="Survivor Used Size" />
+ <value type="UINT" field="numberOfRegions" label="Number of Regions" />
</event>
<event id="GCGarbageCollection" path="vm/gc/collector/garbage_collection" label="Garbage Collection"
@@ -478,6 +479,23 @@
<value type="BYTES64" field="size" label="Allocation Size" />
</event>
+ <event id="TenuringDistribution" path="vm/gc/detailed/tenuring_distribution" label="Tenuring Distribution"
+ is_instant="true">
+ <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
+ <value type="UINT" field="age" label="Age" />
+ <value type="BYTES64" field="size" label="Size" />
+ </event>
+
+ <event id="G1HeapRegionTypeChange" path="vm/gc/detailed/g1_heap_region_type_change" label="G1 Heap Region Type Change"
+ description="Information about a G1 heap region type change." is_instant="true">
+ <value type="UINT" field="index" label="Index" />
+ <value type="G1HEAPREGIONTYPE" field="from" label="From Type" />
+ <value type="G1HEAPREGIONTYPE" field="to" label="To Type" />
+ <value type="ADDRESS" field="start" label="Start" />
+ <value type="BYTES64" field="used" label="Used" />
+ <value type="UINT" field="allocContext" label="Allocation Context" />
+ </event>
+
<!-- Compiler events -->
<event id="Compilation" path="vm/compiler/compilation" label="Compilation"
--- a/hotspot/src/share/vm/trace/tracetypes.xml Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/trace/tracetypes.xml Sat Mar 05 20:46:44 2016 -0800
@@ -126,6 +126,11 @@
<value type="UTF8" field="when" label="when" />
</content_type>
+ <content_type id="G1HeapRegionType" hr_name="G1 Heap Region Type"
+ type="U1" jvm_type="G1HEAPREGIONTYPE">
+ <value type="UTF8" field="type" label="type" />
+ </content_type>
+
<content_type id="G1YCType" hr_name="G1 YC Type"
type="U1" jvm_type="G1YCTYPE">
<value type="UTF8" field="type" label="type" />
@@ -345,6 +350,10 @@
<primary_type symbol="GCWHEN" datatype="U1" contenttype="GCWHEN"
type="u1" sizeop="sizeof(u1)" />
+ <!-- G1HEAPREGIONTYPE -->
+ <primary_type symbol="G1HEAPREGIONTYPE" datatype="U1" contenttype="G1HEAPREGIONTYPE"
+ type="u1" sizeop="sizeof(u1)" />
+
<!-- G1YCType -->
<primary_type symbol="G1YCTYPE" datatype="U1" contenttype="G1YCTYPE"
type="u1" sizeop="sizeof(u1)" />
--- a/hotspot/src/share/vm/utilities/copy.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/utilities/copy.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, 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
@@ -53,6 +53,175 @@
}
}
+class CopySwap : AllStatic {
+public:
+ /**
+ * Copy and byte swap elements
+ *
+ * @param src address of source
+ * @param dst address of destination
+ * @param byte_count number of bytes to copy
+ * @param elem_size size of the elements to copy-swap
+ */
+ static void conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {
+ assert(src != NULL, "address must not be NULL");
+ assert(dst != NULL, "address must not be NULL");
+ assert(elem_size == 2 || elem_size == 4 || elem_size == 8,
+ "incorrect element size: " SIZE_FORMAT, elem_size);
+ assert(is_size_aligned(byte_count, elem_size),
+ "byte_count " SIZE_FORMAT " must be multiple of element size " SIZE_FORMAT, byte_count, elem_size);
+
+ address src_end = src + byte_count;
+
+ if (dst <= src || dst >= src_end) {
+ do_conjoint_swap<RIGHT>(src, dst, byte_count, elem_size);
+ } else {
+ do_conjoint_swap<LEFT>(src, dst, byte_count, elem_size);
+ }
+ }
+
+private:
+ /**
+ * Byte swap a 16-bit value
+ */
+ static uint16_t byte_swap(uint16_t x) {
+ return (x << 8) | (x >> 8);
+ }
+
+ /**
+ * Byte swap a 32-bit value
+ */
+ static uint32_t byte_swap(uint32_t x) {
+ uint16_t lo = (uint16_t)x;
+ uint16_t hi = (uint16_t)(x >> 16);
+
+ return ((uint32_t)byte_swap(lo) << 16) | (uint32_t)byte_swap(hi);
+ }
+
+ /**
+ * Byte swap a 64-bit value
+ */
+ static uint64_t byte_swap(uint64_t x) {
+ uint32_t lo = (uint32_t)x;
+ uint32_t hi = (uint32_t)(x >> 32);
+
+ return ((uint64_t)byte_swap(lo) << 32) | (uint64_t)byte_swap(hi);
+ }
+
+ enum CopyDirection {
+ RIGHT, // lower -> higher address
+ LEFT // higher -> lower address
+ };
+
+ /**
+ * Copy and byte swap elements
+ *
+ * <T> - type of element to copy
+ * <D> - copy direction
+ * <is_src_aligned> - true if src argument is aligned to element size
+ * <is_dst_aligned> - true if dst argument is aligned to element size
+ *
+ * @param src address of source
+ * @param dst address of destination
+ * @param byte_count number of bytes to copy
+ */
+ template <typename T, CopyDirection D, bool is_src_aligned, bool is_dst_aligned>
+ static void do_conjoint_swap(address src, address dst, size_t byte_count) {
+ address cur_src, cur_dst;
+
+ switch (D) {
+ case RIGHT:
+ cur_src = src;
+ cur_dst = dst;
+ break;
+ case LEFT:
+ cur_src = src + byte_count - sizeof(T);
+ cur_dst = dst + byte_count - sizeof(T);
+ break;
+ }
+
+ for (size_t i = 0; i < byte_count / sizeof(T); i++) {
+ T tmp;
+
+ if (is_src_aligned) {
+ tmp = *(T*)cur_src;
+ } else {
+ memcpy(&tmp, cur_src, sizeof(T));
+ }
+
+ tmp = byte_swap(tmp);
+
+ if (is_dst_aligned) {
+ *(T*)cur_dst = tmp;
+ } else {
+ memcpy(cur_dst, &tmp, sizeof(T));
+ }
+
+ switch (D) {
+ case RIGHT:
+ cur_src += sizeof(T);
+ cur_dst += sizeof(T);
+ break;
+ case LEFT:
+ cur_src -= sizeof(T);
+ cur_dst -= sizeof(T);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Copy and byte swap elements
+ *
+ * <T> - type of element to copy
+ * <D> - copy direction
+ *
+ * @param src address of source
+ * @param dst address of destination
+ * @param byte_count number of bytes to copy
+ */
+ template <typename T, CopyDirection direction>
+ static void do_conjoint_swap(address src, address dst, size_t byte_count) {
+ if (is_ptr_aligned(src, sizeof(T))) {
+ if (is_ptr_aligned(dst, sizeof(T))) {
+ do_conjoint_swap<T,direction,true,true>(src, dst, byte_count);
+ } else {
+ do_conjoint_swap<T,direction,true,false>(src, dst, byte_count);
+ }
+ } else {
+ if (is_ptr_aligned(dst, sizeof(T))) {
+ do_conjoint_swap<T,direction,false,true>(src, dst, byte_count);
+ } else {
+ do_conjoint_swap<T,direction,false,false>(src, dst, byte_count);
+ }
+ }
+ }
+
+
+ /**
+ * Copy and byte swap elements
+ *
+ * <D> - copy direction
+ *
+ * @param src address of source
+ * @param dst address of destination
+ * @param byte_count number of bytes to copy
+ * @param elem_size size of the elements to copy-swap
+ */
+ template <CopyDirection D>
+ static void do_conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {
+ switch (elem_size) {
+ case 2: do_conjoint_swap<uint16_t,D>(src, dst, byte_count); break;
+ case 4: do_conjoint_swap<uint32_t,D>(src, dst, byte_count); break;
+ case 8: do_conjoint_swap<uint64_t,D>(src, dst, byte_count); break;
+ default: guarantee(false, "do_conjoint_swap: Invalid elem_size %zd\n", elem_size);
+ }
+ }
+};
+
+void Copy::conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size) {
+ CopySwap::conjoint_swap(src, dst, byte_count, elem_size);
+}
// Fill bytes; larger units are filled atomically if everything is aligned.
void Copy::fill_to_memory_atomic(void* to, size_t size, jubyte value) {
--- a/hotspot/src/share/vm/utilities/copy.hpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/utilities/copy.hpp Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -227,6 +227,16 @@
}
}
+ /**
+ * Copy and *unconditionally* byte swap elements
+ *
+ * @param src address of source
+ * @param dst address of destination
+ * @param byte_count number of bytes to copy
+ * @param elem_size size of the elements to copy-swap
+ */
+ static void conjoint_swap(address src, address dst, size_t byte_count, size_t elem_size);
+
// Fill methods
// Fill word-aligned words, not atomic on each word
--- a/hotspot/src/share/vm/utilities/quickSort.cpp Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/src/share/vm/utilities/quickSort.cpp Sat Mar 05 20:46:44 2016 -0800
@@ -44,6 +44,31 @@
}
return 1;
}
+
+static void print_array(const char* prefix, int* array, int length) {
+ tty->print("%s:", prefix);
+ for (int i = 0; i < length; i++) {
+ tty->print(" %d", array[i]);
+ }
+ tty->cr();
+}
+
+static bool compare_arrays(int* actual, int* expected, int length) {
+ for (int i = 0; i < length; i++) {
+ if (actual[i] != expected[i]) {
+ print_array("Sorted array ", actual, length);
+ print_array("Expected array", expected, length);
+ return false;
+ }
+ }
+ return true;
+}
+
+template <class C>
+static bool sort_and_compare(int* arrayToSort, int* expectedResult, int length, C comparator, bool idempotent = false) {
+ QuickSort::sort<int, C>(arrayToSort, length, comparator, idempotent);
+ return compare_arrays(arrayToSort, expectedResult, length);
+}
#endif // ASSERT
static int test_even_odd_comparator(int a, int b) {
@@ -72,31 +97,6 @@
}
}
-static void print_array(const char* prefix, int* array, int length) {
- tty->print("%s:", prefix);
- for (int i = 0; i < length; i++) {
- tty->print(" %d", array[i]);
- }
- tty->cr();
-}
-
-static bool compare_arrays(int* actual, int* expected, int length) {
- for (int i = 0; i < length; i++) {
- if (actual[i] != expected[i]) {
- print_array("Sorted array ", actual, length);
- print_array("Expected array", expected, length);
- return false;
- }
- }
- return true;
-}
-
-template <class C>
-static bool sort_and_compare(int* arrayToSort, int* expectedResult, int length, C comparator, bool idempotent = false) {
- QuickSort::sort<int, C>(arrayToSort, length, comparator, idempotent);
- return compare_arrays(arrayToSort, expectedResult, length);
-}
-
void QuickSort_test() {
{
int* test_array = NULL;
--- a/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics2.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics2.java Sat Mar 05 20:46:44 2016 -0800
@@ -33,9 +33,10 @@
*
* @run main/othervm
* -Xbootclasspath/a:.
+ * -Xmixed
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
- * -XX:MaxInlineSize=100
+ * -XX:MaxInlineSize=70
* -XX:MinInliningThreshold=0
* TestStringIntrinsics2
*/
--- a/hotspot/test/compiler/loopopts/superword/ProdRed_Double.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/ProdRed_Double.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8074981
* @summary Add C2 x86 Superword support for scalar product reduction optimizations : float test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 ProdRed_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 ProdRed_Double
--- a/hotspot/test/compiler/loopopts/superword/ProdRed_Float.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/ProdRed_Float.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8074981
* @summary Add C2 x86 Superword support for scalar product reduction optimizations : float test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 ProdRed_Float
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 ProdRed_Float
--- a/hotspot/test/compiler/loopopts/superword/ProdRed_Int.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/ProdRed_Int.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8074981
* @summary Add C2 x86 Superword support for scalar product reduction optimizations : int test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 ProdRed_Int
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 ProdRed_Int
--- a/hotspot/test/compiler/loopopts/superword/ReductionPerf.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/ReductionPerf.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8074981
* @summary Add C2 x86 Superword support for scalar product reduction optimizations : int test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:CompileThresholdScaling=0.1 -XX:CompileCommand=exclude,ReductionPerf::main ReductionPerf
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:CompileThresholdScaling=0.1 -XX:CompileCommand=exclude,ReductionPerf::main ReductionPerf
--- a/hotspot/test/compiler/loopopts/superword/SumRedSqrt_Double.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/SumRedSqrt_Double.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,7 +26,7 @@
* @test
* @bug 8135028
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : double sqrt test
-* @requires os.arch=="x86" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
+* @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
--- a/hotspot/test/compiler/loopopts/superword/SumRed_Double.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/SumRed_Double.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8074981
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : double test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRed_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRed_Double
--- a/hotspot/test/compiler/loopopts/superword/SumRed_Float.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/SumRed_Float.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8074981
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : float test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRed_Float
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRed_Float
--- a/hotspot/test/compiler/loopopts/superword/SumRed_Int.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/SumRed_Int.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8074981
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : int test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRed_Int
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRed_Int
--- a/hotspot/test/compiler/loopopts/superword/SumRed_Long.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/compiler/loopopts/superword/SumRed_Long.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
* @test
* @bug 8076276
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : long test
+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRed_Long
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRed_Long
--- a/hotspot/test/runtime/CommandLine/VMDeprecatedOptions.java Sat Mar 05 10:10:20 2016 +0100
+++ b/hotspot/test/runtime/CommandLine/VMDeprecatedOptions.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -40,6 +40,8 @@
// deprecated non-alias flags:
{"MaxGCMinorPauseMillis", "1032"},
{"UseParNewGC", "false"},
+ {"ConvertSleepToYield", "false" },
+ {"ConvertYieldToSleep", "false" },
// deprecated alias flags (see also aliased_jvm_flags):
{"DefaultMaxRAMFraction", "4"},
--- a/jaxp/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -349,3 +349,4 @@
58448465334e1d8bf1cfc09052783937b1cc21c0 jdk-9+104
5acf6071d4d610068a19c79e004ba8e59cf1b087 jdk-9+105
65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106
+781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -97,19 +97,9 @@
public class XML11DTDScannerImpl
extends XMLDTDScannerImpl {
- /** Array of 3 strings. */
- private String[] fStrings = new String[3];
-
- /** String. */
- private XMLString fString = new XMLString();
-
/** String buffer. */
private XMLStringBuffer fStringBuffer = new XMLStringBuffer();
- /** String buffer. */
- private XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
- private XMLStringBuffer fStringBuffer3 = new XMLStringBuffer();
-
//
// Constructors
//
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -46,7 +46,6 @@
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
-import com.sun.xml.internal.stream.Entity;
/**
* This class is responsible for scanning the declarations found
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -23,7 +23,6 @@
import com.sun.xml.internal.stream.XMLBufferListener;
import com.sun.xml.internal.stream.XMLEntityStorage;
-import com.sun.xml.internal.stream.XMLInputFactoryImpl;
import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
import java.io.EOFException;
@@ -50,17 +49,11 @@
import com.sun.org.apache.xerces.internal.xni.Augmentations;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
-import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
-import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit;
-import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.State;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
-import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
-import javax.xml.XMLConstants;
import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.events.XMLEvent;
/**
*
@@ -210,12 +203,12 @@
null,
null,
null,
- EXTERNAL_ACCESS_DEFAULT
+ null
};
private static final char [] cdata = {'[','C','D','A','T','A','['};
static final char [] xmlDecl = {'<','?','x','m','l'};
- private static final char [] endTag = {'<','/'};
+ // private static final char [] endTag = {'<','/'};
// debugging
/** Debug scanner state. */
@@ -2066,7 +2059,7 @@
*/
String checkAccess(String systemId, String allowedProtocols) throws IOException {
String baseSystemId = fEntityScanner.getBaseSystemId();
- String expandedSystemId = fEntityManager.expandSystemId(systemId, baseSystemId,fStrictURI);
+ String expandedSystemId = XMLEntityManager.expandSystemId(systemId, baseSystemId, fStrictURI);
return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, Constants.ACCESS_EXTERNAL_ALL);
}
@@ -2602,8 +2595,6 @@
//
// Driver methods
//
- private boolean fContinueDispatching = true;
- private boolean fScanningForMarkup = true;
/**
* decides the appropriate state of the parser
@@ -3266,7 +3257,7 @@
protected XMLString getString(){
if(fAttributeCacheUsedCount < initialCacheCount || fAttributeCacheUsedCount < attributeValueCache.size()){
- return (XMLString)attributeValueCache.get(fAttributeCacheUsedCount++);
+ return attributeValueCache.get(fAttributeCacheUsedCount++);
} else{
XMLString str = new XMLString();
fAttributeCacheUsedCount++;
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -31,7 +31,6 @@
import com.sun.org.apache.xerces.internal.xni.Augmentations;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
-import com.sun.org.apache.xerces.internal.xni.XMLString;
import com.sun.org.apache.xerces.internal.xni.XNIException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
@@ -224,9 +223,6 @@
/** A DTD Description. */
private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null);
- /** String. */
- private XMLString fString = new XMLString();
-
private static final char [] DOCTYPE = {'D','O','C','T','Y','P','E'};
private static final char [] COMMENTSTRING = {'-','-'};
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -370,7 +370,7 @@
protected Map<String, Entity> fEntities = new HashMap<>();
/** Entity stack. */
- protected Stack fEntityStack = new Stack();
+ protected Stack<Entity> fEntityStack = new Stack<>();
/** Current entity. */
protected Entity.ScannedEntity fCurrentEntity = null;
@@ -633,10 +633,10 @@
final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource;
// set request properties
- Iterator propIter = httpInputSource.getHTTPRequestProperties();
+ Iterator<Map.Entry<String, String>> propIter = httpInputSource.getHTTPRequestProperties();
while (propIter.hasNext()) {
- Map.Entry entry = (Map.Entry) propIter.next();
- urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue());
+ Map.Entry<String, String> entry = propIter.next();
+ urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
}
// set preference for redirection
@@ -1057,7 +1057,6 @@
String literalSystemId = resourceIdentifier.getLiteralSystemId();
String baseSystemId = resourceIdentifier.getBaseSystemId();
String expandedSystemId = resourceIdentifier.getExpandedSystemId();
- String namespace = resourceIdentifier.getNamespace();
// if no base systemId given, assume that it's relative
// to the systemId of the current scanned entity
@@ -2067,14 +2066,6 @@
// system id has to be a valid URI
if (strict) {
-
-
- // check if there is a system id before
- // trying to expand it.
- if (systemId == null) {
- return null;
- }
-
try {
// if it's already an absolute one, return it
new URI(systemId);
@@ -2968,7 +2959,7 @@
if (!fCurrentEntity.xmlDeclChunkRead)
{
fCurrentEntity.xmlDeclChunkRead = true;
- len = fCurrentEntity.DEFAULT_XMLDECL_BUFFER_SIZE;
+ len = Entity.ScannedEntity.DEFAULT_XMLDECL_BUFFER_SIZE;
}
return fInputStream.read(b, off, len);
}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -25,8 +25,6 @@
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter;
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
-import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl;
-import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
import com.sun.org.apache.xerces.internal.util.XMLSymbols;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.QName;
@@ -34,13 +32,9 @@
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
-import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
-import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.events.XMLEvent;
/**
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -25,7 +25,6 @@
import com.sun.xml.internal.stream.XMLEntityStorage;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashMap;
import javax.xml.stream.events.XMLEvent;
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
@@ -120,8 +119,8 @@
//we should have a feature when set to true computes this value
private boolean fNeedNonNormalizedValue = false;
- protected ArrayList attributeValueCache = new ArrayList();
- protected ArrayList stringBufferCache = new ArrayList();
+ protected ArrayList<XMLString> attributeValueCache = new ArrayList<>();
+ protected ArrayList<XMLStringBuffer> stringBufferCache = new ArrayList<>();
protected int fStringBufferIndex = 0;
protected boolean fAttributeCacheInitDone = false;
protected int fAttributeCacheUsedCount = 0;
@@ -1470,7 +1469,7 @@
XMLStringBuffer getStringBuffer(){
if((fStringBufferIndex < initialCacheCount )|| (fStringBufferIndex < stringBufferCache.size())){
- return (XMLStringBuffer)stringBufferCache.get(fStringBufferIndex++);
+ return stringBufferCache.get(fStringBufferIndex++);
}else{
XMLStringBuffer tmpObj = new XMLStringBuffer();
fStringBufferIndex++;
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -1172,7 +1172,7 @@
if (max != SchemaSymbols.OCCURRENCE_UNBOUNDED) {
// maxOccurLimit is only check in secure mode
- if (fSchemaHandler.fSecureProcessing != null) {
+ if (fSchemaHandler.fSecurityManager != null) {
String localName = element.getLocalName();
// The maxOccurs restriction no longer applies to elements
@@ -1191,8 +1191,8 @@
if (!optimize) {
//Revisit :: IMO this is not right place to check
// maxOccurNodeLimit.
- int maxOccurNodeLimit = fSchemaHandler.fSecureProcessing.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT);
- if (max > maxOccurNodeLimit && !fSchemaHandler.fSecureProcessing.isNoLimit(maxOccurNodeLimit)) {
+ int maxOccurNodeLimit = fSchemaHandler.fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT);
+ if (max > maxOccurNodeLimit && !fSchemaHandler.fSecurityManager.isNoLimit(maxOccurNodeLimit)) {
reportSchemaFatalError("MaxOccurLimit", new Object[] {new Integer(maxOccurNodeLimit)}, element);
// reset max values in case processing continues on error
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -194,6 +194,7 @@
/** Property identifier: entity resolver. */
public static final String ENTITY_RESOLVER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+
/** Property identifier: entity manager. */
protected static final String ENTITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
@@ -214,16 +215,13 @@
protected static final String SECURITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
- private static final String SECURE_PROCESSING =
- Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
-
/** Property identifier: locale. */
protected static final String LOCALE =
Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
- /** Property identifier: Security property manager. */
+ /** Property identifier: Security property manager. */
private static final String XML_SECURITY_PROPERTY_MANAGER =
- Constants.XML_SECURITY_PROPERTY_MANAGER;
+ Constants.XML_SECURITY_PROPERTY_MANAGER;
protected static final boolean DEBUG_NODE_POOL = false;
@@ -243,17 +241,12 @@
// as unlikely as possible to cause collisions.
public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi";
- //
- //protected data that can be accessable by any traverser
+ //protected data that can be accessible by any traverser
protected XSDeclarationPool fDeclPool = null;
- /**
- * <p>Security manager in effect.</p>
- *
- * <p>Protected to allow access by any traverser.</p>
- */
- protected XMLSecurityManager fSecureProcessing = null;
+ // the Security manager in effect.
+ protected XMLSecurityManager fSecurityManager = null;
private String fAccessExternalSchema;
private String fAccessExternalDTD;
@@ -266,27 +259,28 @@
// XSDocumentInfoRegistry we can easily get the corresponding
// XSDocumentInfo object.
private boolean registryEmpty = true;
- private Map<String, Element> fUnparsedAttributeRegistry = new HashMap();
- private Map<String, Element> fUnparsedAttributeGroupRegistry = new HashMap();
- private Map<String, Element> fUnparsedElementRegistry = new HashMap();
- private Map<String, Element> fUnparsedGroupRegistry = new HashMap();
- private Map<String, Element> fUnparsedIdentityConstraintRegistry = new HashMap();
- private Map<String, Element> fUnparsedNotationRegistry = new HashMap();
- private Map<String, Element> fUnparsedTypeRegistry = new HashMap();
+ private Map<String, Element> fUnparsedAttributeRegistry = new HashMap<>();
+ private Map<String, Element> fUnparsedAttributeGroupRegistry = new HashMap<>();
+ private Map<String, Element> fUnparsedElementRegistry = new HashMap<>();
+ private Map<String, Element> fUnparsedGroupRegistry = new HashMap<>();
+ private Map<String, Element> fUnparsedIdentityConstraintRegistry = new HashMap<>();
+ private Map<String, Element> fUnparsedNotationRegistry = new HashMap<>();
+ private Map<String, Element> fUnparsedTypeRegistry = new HashMap<>();
// Compensation for the above maps to locate XSDocumentInfo,
// Since we may take Schema Element directly, so can not get the
// corresponding XSDocumentInfo object just using above maps.
- private Map<String, XSDocumentInfo> fUnparsedAttributeRegistrySub = new HashMap();
- private Map<String, XSDocumentInfo> fUnparsedAttributeGroupRegistrySub = new HashMap();
- private Map<String, XSDocumentInfo> fUnparsedElementRegistrySub = new HashMap();
- private Map<String, XSDocumentInfo> fUnparsedGroupRegistrySub = new HashMap();
- private Map<String, XSDocumentInfo> fUnparsedIdentityConstraintRegistrySub = new HashMap();
- private Map<String, XSDocumentInfo> fUnparsedNotationRegistrySub = new HashMap();
- private Map<String, XSDocumentInfo> fUnparsedTypeRegistrySub = new HashMap();
+ private Map<String, XSDocumentInfo> fUnparsedAttributeRegistrySub = new HashMap<>();
+ private Map<String, XSDocumentInfo> fUnparsedAttributeGroupRegistrySub = new HashMap<>();
+ private Map<String, XSDocumentInfo> fUnparsedElementRegistrySub = new HashMap<>();
+ private Map<String, XSDocumentInfo> fUnparsedGroupRegistrySub = new HashMap<>();
+ private Map<String, XSDocumentInfo> fUnparsedIdentityConstraintRegistrySub = new HashMap<>();
+ private Map<String, XSDocumentInfo> fUnparsedNotationRegistrySub = new HashMap<>();
+ private Map<String, XSDocumentInfo> fUnparsedTypeRegistrySub = new HashMap<>();
// Stores XSDocumentInfo (keyed by component name), to check for duplicate
// components declared within the same xsd document
- private Map fUnparsedRegistriesExt[] = new HashMap[] {
+ @SuppressWarnings("unchecked")
+ private Map<String, XSDocumentInfo> fUnparsedRegistriesExt[] = new HashMap[] {
null,
null, // ATTRIBUTE_TYPE
null, // ATTRIBUTEGROUP_TYPE
@@ -300,17 +294,19 @@
// this map is keyed on by XSDocumentInfo objects. Its values
// are Vectors containing the XSDocumentInfo objects <include>d,
// <import>ed or <redefine>d by the key XSDocumentInfo.
- private Map<XSDocumentInfo, Vector> fDependencyMap = new HashMap();
+ private Map<XSDocumentInfo, Vector<XSDocumentInfo>> fDependencyMap = new HashMap<>();
// this map is keyed on by a target namespace. Its values
// are Vectors containing namespaces imported by schema documents
// with the key target namespace.
- // if an imprted schema has absent namespace, the value "null" is stored.
- private Map<String, Vector> fImportMap = new HashMap();
+ // if an imported schema has absent namespace, the value "null" is stored.
+ private Map<String, Vector> fImportMap = new HashMap<> ();
+
// all namespaces that imports other namespaces
// if the importing schema has absent namespace, empty string is stored.
// (because the key of a map can't be null.)
- private Vector fAllTNSs = new Vector();
+ private Vector<String> fAllTNSs = new Vector<>();
+
// stores instance document mappings between namespaces and schema hints
private Map<String, XMLSchemaLoader.LocationArray> fLocationPairs = null;
@@ -333,7 +329,7 @@
if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){
documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI();
}
- return documentURI != null ? documentURI : (String) fDoc2SystemId.get(ele);
+ return documentURI != null ? documentURI : fDoc2SystemId.get(ele);
}
// This vector stores strings which are combinations of the
@@ -341,11 +337,11 @@
// schema document. This combination is used so that the user's
// EntityResolver can provide a consistent way of identifying a
// schema document that is included in multiple other schemas.
- private Map fTraversed = new HashMap();
+ private Map<XSDKey, Element> fTraversed = new HashMap<>();
// this map contains a mapping from Schema Element to its systemId
// this is useful to resolve a uri relative to the referring document
- private Map fDoc2SystemId = new HashMap();
+ private Map<Element, String> fDoc2SystemId = new HashMap<>();
// the primary XSDocumentInfo we were called to parse
private XSDocumentInfo fRoot = null;
@@ -387,7 +383,15 @@
// the XMLErrorReporter
private XMLErrorReporter fErrorReporter;
- private XMLEntityResolver fEntityResolver;
+
+ // the XMLErrorHandler
+ private XMLErrorHandler fErrorHandler;
+
+ // the Locale
+ private Locale fLocale;
+
+ // the XMLEntityManager
+ private XMLEntityResolver fEntityManager;
// the XSAttributeChecker
private XSAttributeChecker fAttributeChecker;
@@ -404,6 +408,9 @@
// the Grammar Pool
private XMLGrammarPool fGrammarPool;
+ // the security property manager
+ private XMLSecurityPropertyManager fSecurityPropertyMgr = null;
+
//************ Traversers **********
XSDAttributeGroupTraverser fAttributeGroupTraverser;
XSDAttributeTraverser fAttributeTraverser;
@@ -638,7 +645,7 @@
// for all grammars with <import>s
for (int i = fAllTNSs.size() - 1; i >= 0; i--) {
// get its target namespace
- String tns = (String)fAllTNSs.elementAt(i);
+ String tns = fAllTNSs.elementAt(i);
// get all namespaces it imports
Vector ins = (Vector)fImportMap.get(tns);
// get the grammar
@@ -696,12 +703,13 @@
fAnnotationValidator.setFeature(VALIDATION, true);
fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true);
fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter);
+ /** set security manager and XML Security Property Manager **/
+ fAnnotationValidator.setProperty(SECURITY_MANAGER, (fSecurityManager != null) ? fSecurityManager : new XMLSecurityManager(true));
+ fAnnotationValidator.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
/** Set error handler. **/
- XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler();
- fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler());
+ fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
/** Set locale. **/
- Locale locale = fErrorReporter.getLocale();
- fAnnotationValidator.setProperty(LOCALE, locale);
+ fAnnotationValidator.setProperty(LOCALE, fLocale);
}
/**
@@ -880,10 +888,10 @@
// store the document and its location
// REVISIT: don't expose the DOM tree
- sg.addDocument(null, (String)fDoc2SystemId.get(currSchemaInfo.fSchemaElement));
+ sg.addDocument(null, fDoc2SystemId.get(currSchemaInfo.fSchemaElement));
fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo);
- Vector dependencies = new Vector();
+ Vector<XSDocumentInfo> dependencies = new Vector<>();
Element rootNode = schemaRoot;
Element newSchemaRoot = null;
@@ -1334,9 +1342,9 @@
} // end for
// now we're done with this one!
- DOMUtil.setHidden(currDoc, fHiddenNodes);
+ DOMUtil.setHidden(currDoc, fHiddenNodes);
// now add the schemas this guy depends on
- Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc);
+ Vector<XSDocumentInfo> currSchemaDepends = fDependencyMap.get(currSchemaDoc);
for (int i = 0; i < currSchemaDepends.size(); i++) {
schemasToProcess.push(currSchemaDepends.elementAt(i));
}
@@ -1466,7 +1474,7 @@
DOMUtil.setHidden(currDoc, fHiddenNodes);
// now add the schemas this guy depends on
- Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc);
+ Vector<XSDocumentInfo> currSchemaDepends = fDependencyMap.get(currSchemaDoc);
for (int i = 0; i < currSchemaDepends.size(); i++) {
schemasToProcess.push(currSchemaDepends.elementAt(i));
}
@@ -1915,7 +1923,7 @@
}
public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) {
- return (String)fDoc2SystemId.get(schemaDoc.fSchemaElement);
+ return fDoc2SystemId.get(schemaDoc.fSchemaElement);
}
// This method determines whether there is a group
@@ -2044,7 +2052,7 @@
XMLInputSource schemaSource = null;
try {
Map<String, XMLSchemaLoader.LocationArray> pairs = usePairs ? fLocationPairs : Collections.emptyMap();
- schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver);
+ schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager);
}
catch (IOException ex) {
if (mustResolve) {
@@ -2097,7 +2105,7 @@
XMLInputSource schemaSource = null;
try {
Map<String, XMLSchemaLoader.LocationArray> pairs = usePairs ? fLocationPairs : Collections.emptyMap();
- schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver);
+ schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager);
}
catch (IOException ex) {
if (mustResolve) {
@@ -2152,7 +2160,7 @@
if (referType != XSDDescription.CONTEXT_PREPARSE){
schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
key = new XSDKey(schemaId, referType, schemaNamespace);
- if((schemaElement = (Element)fTraversed.get(key)) != null) {
+ if((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -2211,7 +2219,7 @@
if (referType != XSDDescription.CONTEXT_PREPARSE) {
schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), schemaSource.getBaseSystemId(), false);
key = new XSDKey(schemaId, referType, schemaNamespace);
- if ((schemaElement = (Element) fTraversed.get(key)) != null) {
+ if ((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -2238,9 +2246,8 @@
namespacePrefixes = true;
// If this is a Xerces SAX parser set the security manager if there is one
if (parser instanceof SAXParser) {
- Object securityManager = fSchemaParser.getProperty(SECURITY_MANAGER);
- if (securityManager != null) {
- parser.setProperty(SECURITY_MANAGER, securityManager);
+ if (fSecurityManager != null) {
+ parser.setProperty(SECURITY_MANAGER, fSecurityManager);
}
}
}
@@ -2347,7 +2354,7 @@
}
if (isDocument) {
key = new XSDKey(schemaId, referType, schemaNamespace);
- if ((schemaElement = (Element) fTraversed.get(key)) != null) {
+ if ((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -2402,7 +2409,7 @@
}
if (isDocument) {
key = new XSDKey(schemaId, referType, schemaNamespace);
- if ((schemaElement = (Element) fTraversed.get(key)) != null) {
+ if ((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -3502,40 +3509,21 @@
// set symbol table
fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE);
- fSecureProcessing = null;
- if( componentManager!=null ) {
- fSecureProcessing = (XMLSecurityManager) componentManager.getProperty(SECURE_PROCESSING, null);
- }
+ // set security manager
+ fSecurityManager = (XMLSecurityManager) componentManager.getProperty(SECURITY_MANAGER, null);
+
+ //set entity manager
+ fEntityManager = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER);
//set entity resolver
- fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER);
XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER);
if (er != null)
fSchemaParser.setEntityResolver(er);
// set error reporter
- fErrorReporter =
- (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER);
- try {
- XMLErrorHandler currErrorHandler = fErrorReporter.getErrorHandler();
- // Setting a parser property can be much more expensive
- // than checking its value. Don't set the ERROR_HANDLER
- // or LOCALE properties unless they've actually changed.
- if (currErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) {
- fSchemaParser.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler());
- if (fAnnotationValidator != null) {
- fAnnotationValidator.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler());
- }
- }
- Locale currentLocale = fErrorReporter.getLocale();
- if (currentLocale != fSchemaParser.getProperty(LOCALE)) {
- fSchemaParser.setProperty(LOCALE, currentLocale);
- if (fAnnotationValidator != null) {
- fAnnotationValidator.setProperty(LOCALE, currentLocale);
- }
- }
- }
- catch (XMLConfigurationException e) {}
+ fErrorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER);
+ fErrorHandler = fErrorReporter.getErrorHandler();
+ fLocale = fErrorReporter.getLocale();
fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false);
fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false);
@@ -3543,56 +3531,66 @@
fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false);
try {
- fSchemaParser.setFeature(
- CONTINUE_AFTER_FATAL_ERROR,
- fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR));
- } catch (XMLConfigurationException e) {
+ // Setting a parser property can be much more expensive
+ // than checking its value. Don't set the ERROR_HANDLER
+ // or LOCALE properties unless they've actually changed.
+ if (fErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) {
+ fSchemaParser.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
+ if (fAnnotationValidator != null) {
+ fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
+ }
+ }
+ if (fLocale != fSchemaParser.getProperty(LOCALE)) {
+ fSchemaParser.setProperty(LOCALE, fLocale);
+ if (fAnnotationValidator != null) {
+ fAnnotationValidator.setProperty(LOCALE, fLocale);
+ }
+ }
}
+ catch (XMLConfigurationException e) {}
+
+ try {
+ fSchemaParser.setFeature(CONTINUE_AFTER_FATAL_ERROR, fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR));
+ } catch (XMLConfigurationException e) {}
try {
if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) {
fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true);
}
- } catch (XMLConfigurationException e) {
- }
+ } catch (XMLConfigurationException e) {}
+
try {
if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) {
fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true);
}
- } catch (XMLConfigurationException e) {
- }
+ } catch (XMLConfigurationException e) {}
try {
- fGrammarPool =
- (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL);
+ fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL);
} catch (XMLConfigurationException e) {
fGrammarPool = null;
}
+
// security features
try {
if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) {
fSchemaParser.setFeature(DISALLOW_DOCTYPE, true);
}
- } catch (XMLConfigurationException e) {
- }
+ } catch (XMLConfigurationException e) {}
+
try {
- Object security = componentManager.getProperty(SECURITY_MANAGER, null);
- if (security != null){
- fSchemaParser.setProperty(SECURITY_MANAGER, security);
+ if (fSecurityManager != null) {
+ fSchemaParser.setProperty(SECURITY_MANAGER, fSecurityManager);
}
- } catch (XMLConfigurationException e) {
- }
-
- XMLSecurityPropertyManager securityPropertyMgr = (XMLSecurityPropertyManager)
- componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
+ } catch (XMLConfigurationException e) {}
+
+ fSecurityPropertyMgr = (XMLSecurityPropertyManager) componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
+
//Passing on the setting to the parser
- fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, securityPropertyMgr);
-
- fAccessExternalDTD = securityPropertyMgr.getValue(
- XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
-
- fAccessExternalSchema = securityPropertyMgr.getValue(
- XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
+ fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
+
+ fAccessExternalDTD = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
+ fAccessExternalSchema = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
} // reset(XMLComponentManager)
@@ -4051,7 +4049,7 @@
so long as there's some include/import/redefine path amongst them.
If they rver reverse this decision the code's right here though... - neilg
// now look in fDependencyMap to see if this is reachable
- if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) {
+ if((fDependencyMap.get(currSchema)).contains(declDocInfo)) {
return declDocInfo;
}
// obviously the requesting doc didn't include, redefine or
@@ -4072,9 +4070,9 @@
if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) {
// make it visible
DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes);
- Vector dependingSchemas = (Vector)fDependencyMap.get(startSchema);
+ Vector<XSDocumentInfo> dependingSchemas = fDependencyMap.get(startSchema);
for (int i = 0; i < dependingSchemas.size(); i++) {
- setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i));
+ setSchemasVisible(dependingSchemas.elementAt(i));
}
}
// if it's visible already than so must be its children
@@ -4107,7 +4105,7 @@
ElementImpl ele = (ElementImpl)e;
// get system id from document object
Document doc = ele.getOwnerDocument();
- String sid = (String)fDoc2SystemId.get(DOMUtil.getRoot(doc));
+ String sid = fDoc2SystemId.get(DOMUtil.getRoot(doc));
// line/column numbers are stored in the element node
int line = ele.getLineNumber();
int column = ele.getColumnNumber();
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -52,7 +52,6 @@
import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
import com.sun.org.apache.xerces.internal.util.PropertyState;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
-import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
@@ -166,59 +165,57 @@
protected static final String USE_GRAMMAR_POOL_ONLY =
Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
- // feature identifiers
+ // feature identifiers
- /** Feature identifier: validation. */
- protected static final String VALIDATION =
- Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+ /** Feature identifier: validation. */
+ protected static final String VALIDATION =
+ Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
- /** Feature identifier: namespaces. */
- protected static final String NAMESPACES =
- Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+ /** Feature identifier: namespaces. */
+ protected static final String NAMESPACES =
+ Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
- /** Feature identifier: external general entities. */
- protected static final String EXTERNAL_GENERAL_ENTITIES =
- Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
+ /** Feature identifier: external general entities. */
+ protected static final String EXTERNAL_GENERAL_ENTITIES =
+ Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
- /** Feature identifier: external parameter entities. */
- protected static final String EXTERNAL_PARAMETER_ENTITIES =
- Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
+ /** Feature identifier: external parameter entities. */
+ protected static final String EXTERNAL_PARAMETER_ENTITIES =
+ Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
- /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */
- protected static final String IGNORE_XSI_TYPE =
- Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE;
+ /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */
+ protected static final String IGNORE_XSI_TYPE =
+ Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE;
- /** Feature identifier: whether to ignore ID/IDREF errors */
- protected static final String ID_IDREF_CHECKING =
- Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE;
+ /** Feature identifier: whether to ignore ID/IDREF errors */
+ protected static final String ID_IDREF_CHECKING =
+ Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE;
- /** Feature identifier: whether to ignore unparsed entity errors */
- protected static final String UNPARSED_ENTITY_CHECKING =
- Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE;
+ /** Feature identifier: whether to ignore unparsed entity errors */
+ protected static final String UNPARSED_ENTITY_CHECKING =
+ Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE;
- /** Feature identifier: whether to ignore identity constraint errors */
- protected static final String IDENTITY_CONSTRAINT_CHECKING =
- Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE;
+ /** Feature identifier: whether to ignore identity constraint errors */
+ protected static final String IDENTITY_CONSTRAINT_CHECKING =
+ Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE;
// property identifiers
+ /** Property identifier: xml string. */
+ protected static final String XML_STRING =
+ Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
- /** Property identifier: xml string. */
- protected static final String XML_STRING =
- Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
-
- /** Property identifier: symbol table. */
- protected static final String SYMBOL_TABLE =
- Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
- /** Property identifier: error handler. */
- protected static final String ERROR_HANDLER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+ /** Property identifier: error handler. */
+ protected static final String ERROR_HANDLER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
- /** Property identifier: entity resolver. */
- protected static final String ENTITY_RESOLVER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
-
+ /** Property identifier: entity resolver. */
+ protected static final String ENTITY_RESOLVER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
/** Property identifier: XML Schema validator. */
protected static final String SCHEMA_VALIDATOR =
@@ -232,8 +229,6 @@
protected static final String SCHEMA_NONS_LOCATION =
Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
- // property identifiers
-
/** Property identifier: error reporter. */
protected static final String ERROR_REPORTER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
@@ -313,33 +308,33 @@
// Data
//
- protected SymbolTable fSymbolTable;
+ protected SymbolTable fSymbolTable;
protected XMLInputSource fInputSource;
protected ValidationManager fValidationManager;
- protected XMLVersionDetector fVersionDetector;
+ protected XMLVersionDetector fVersionDetector;
protected XMLLocator fLocator;
- protected Locale fLocale;
+ protected Locale fLocale;
- /** XML 1.0 Components. */
- protected ArrayList fComponents;
+ /** XML 1.0 Components. */
+ protected ArrayList<XMLComponent> fComponents;
- /** XML 1.1. Components. */
- protected ArrayList fXML11Components = null;
+ /** XML 1.1. Components. */
+ protected ArrayList<XMLComponent> fXML11Components = null;
- /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */
- protected ArrayList fCommonComponents = null;
+ /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */
+ protected ArrayList<XMLComponent> fCommonComponents = null;
- /** The document handler. */
- protected XMLDocumentHandler fDocumentHandler;
+ /** The document handler. */
+ protected XMLDocumentHandler fDocumentHandler;
- /** The DTD handler. */
- protected XMLDTDHandler fDTDHandler;
+ /** The DTD handler. */
+ protected XMLDTDHandler fDTDHandler;
- /** The DTD content model handler. */
- protected XMLDTDContentModelHandler fDTDContentModelHandler;
+ /** The DTD content model handler. */
+ protected XMLDTDContentModelHandler fDTDContentModelHandler;
- /** Last component in the document pipeline */
- protected XMLDocumentSource fLastComponent;
+ /** Last component in the document pipeline */
+ protected XMLDocumentSource fLastComponent;
/**
* True if a parse is in progress. This state is needed because
@@ -477,15 +472,15 @@
// create a vector to hold all the components in use
// XML 1.0 specialized components
- fComponents = new ArrayList();
+ fComponents = new ArrayList<>();
// XML 1.1 specialized components
- fXML11Components = new ArrayList();
+ fXML11Components = new ArrayList<>();
// Common components for XML 1.1. and XML 1.0
- fCommonComponents = new ArrayList();
+ fCommonComponents = new ArrayList<>();
// create table for features and properties
- fFeatures = new HashMap();
- fProperties = new HashMap();
+ fFeatures = new HashMap<>();
+ fProperties = new HashMap<>();
// add default recognized features
final String[] recognizedFeatures =
@@ -580,35 +575,35 @@
}
fEntityManager = new XMLEntityManager();
- fProperties.put(ENTITY_MANAGER, fEntityManager);
+ fProperties.put(ENTITY_MANAGER, fEntityManager);
addCommonComponent(fEntityManager);
fErrorReporter = new XMLErrorReporter();
fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
- fProperties.put(ERROR_REPORTER, fErrorReporter);
+ fProperties.put(ERROR_REPORTER, fErrorReporter);
addCommonComponent(fErrorReporter);
fNamespaceScanner = new XMLNSDocumentScannerImpl();
- fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
+ fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
addComponent((XMLComponent) fNamespaceScanner);
fDTDScanner = new XMLDTDScannerImpl();
- fProperties.put(DTD_SCANNER, fDTDScanner);
+ fProperties.put(DTD_SCANNER, fDTDScanner);
addComponent((XMLComponent) fDTDScanner);
fDTDProcessor = new XMLDTDProcessor();
- fProperties.put(DTD_PROCESSOR, fDTDProcessor);
+ fProperties.put(DTD_PROCESSOR, fDTDProcessor);
addComponent((XMLComponent) fDTDProcessor);
fDTDValidator = new XMLNSDTDValidator();
- fProperties.put(DTD_VALIDATOR, fDTDValidator);
+ fProperties.put(DTD_VALIDATOR, fDTDValidator);
addComponent(fDTDValidator);
fDatatypeValidatorFactory = DTDDVFactory.getInstance();
- fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory);
+ fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory);
fValidationManager = new ValidationManager();
- fProperties.put(VALIDATION_MANAGER, fValidationManager);
+ fProperties.put(VALIDATION_MANAGER, fValidationManager);
fVersionDetector = new XMLVersionDetector();
@@ -935,20 +930,20 @@
// forward to every XML 1.0 component
int count = fComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fComponents.get(i);
+ XMLComponent c = fComponents.get(i);
c.setFeature(featureId, state);
}
// forward it to common components
count = fCommonComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fCommonComponents.get(i);
+ XMLComponent c = fCommonComponents.get(i);
c.setFeature(featureId, state);
}
// forward to every XML 1.1 component
count = fXML11Components.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fXML11Components.get(i);
+ XMLComponent c = fXML11Components.get(i);
try{
c.setFeature(featureId, state);
}
@@ -996,19 +991,19 @@
// forward to every XML 1.0 component
int count = fComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fComponents.get(i);
+ XMLComponent c = fComponents.get(i);
c.setProperty(propertyId, value);
}
// forward it to every common Component
count = fCommonComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fCommonComponents.get(i);
+ XMLComponent c = fCommonComponents.get(i);
c.setProperty(propertyId, value);
}
// forward it to every XML 1.1 component
count = fXML11Components.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fXML11Components.get(i);
+ XMLComponent c = fXML11Components.get(i);
try{
c.setProperty(propertyId, value);
}
@@ -1034,7 +1029,7 @@
protected void reset() throws XNIException {
int count = fComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fComponents.get(i);
+ XMLComponent c = fComponents.get(i);
c.reset(this);
}
@@ -1047,7 +1042,7 @@
// reset common components
int count = fCommonComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fCommonComponents.get(i);
+ XMLComponent c = fCommonComponents.get(i);
c.reset(this);
}
@@ -1061,7 +1056,7 @@
// reset every component
int count = fXML11Components.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fXML11Components.get(i);
+ XMLComponent c = fXML11Components.get(i);
c.reset(this);
}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java Sat Mar 05 20:46:44 2016 -0800
@@ -51,7 +51,7 @@
protected boolean fFollowRedirects = true;
/** HTTP request properties. **/
- protected Map fHTTPRequestProperties = new HashMap();
+ protected Map<String, String> fHTTPRequestProperties = new HashMap<>();
//
// Constructors
@@ -159,7 +159,7 @@
* been set
*/
public String getHTTPRequestProperty(String key) {
- return (String) fHTTPRequestProperties.get(key);
+ return fHTTPRequestProperties.get(key);
} // getHTTPRequestProperty(String):String
/**
@@ -172,7 +172,7 @@
* @return an iterator for the request properties this
* input source contains
*/
- public Iterator getHTTPRequestProperties() {
+ public Iterator<Map.Entry<String, String>> getHTTPRequestProperties() {
return fHTTPRequestProperties.entrySet().iterator();
} // getHTTPRequestProperties():Iterator
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+<xs:annotation>
+ <xs:appinfo>Testapp for XSD annotation issue</xs:appinfo>
+ <xs:documentation xml:lang="en">This is an XSD annotation, just for the sake of it.</xs:documentation>
+</xs:annotation>
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, 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 validation;
+
+import java.io.File;
+
+import javax.xml.XMLConstants;
+import javax.xml.validation.SchemaFactory;
+
+import org.testng.annotations.Test;
+
+/*
+ * @summary Test Schema creation
+ * @bug 8149915
+ */
+public class SchemaTest {
+
+ /*
+ * @bug 8149915
+ * Verifies that the annotation validator is initialized with the security manager for schema
+ * creation with http://apache.org/xml/features/validate-annotations=true.
+ */
+ @Test
+ public void testValidation() throws Exception {
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ factory.setFeature("http://apache.org/xml/features/validate-annotations", true);
+ factory.newSchema(new File(getClass().getResource("Bug8149915.xsd").getFile()));
+ }
+}
--- a/jaxws/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/jaxws/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -352,3 +352,4 @@
0f557aa096e2a5c9733d406d8cf0c2e6b1f8ca60 jdk-9+104
45a666c58e4c7d07638878684ad09decb3229dc9 jdk-9+105
c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106
+fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107
--- a/jdk/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -350,3 +350,4 @@
55518739e399a1066c8613e19100d51b38d9f223 jdk-9+105
6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106
8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107
+42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108
--- a/jdk/make/gendata/GendataHtml32dtd.gmk Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/make/gendata/GendataHtml32dtd.gmk Sat Mar 05 20:46:44 2016 -0800
@@ -30,6 +30,6 @@
$(call LogInfo, Generating HTML DTD file)
$(MKDIR) -p $(@D)
$(RM) $@
- ($(TOOL_DTDBUILDER) $(LOG_INFO) html32 > $@) || exit 1
+ ($(TOOL_DTDBUILDER) html32 > $@) || exit 1
TARGETS += $(HTML32DTD)
--- a/jdk/make/gensrc/GensrcCLDR.gmk Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/make/gensrc/GensrcCLDR.gmk Sat Mar 05 20:46:44 2016 -0800
@@ -30,7 +30,7 @@
GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.localedata
CLDR_BASEMETAINFO_FILE := $(GENSRC_BASEDIR)/sun/util/cldr/CLDRBaseLocaleDataMetaInfo.java
-CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo_jdk_localedata.java
+CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.java
CLDR_BASE_LOCALES := "en-US"
--- a/jdk/make/gensrc/GensrcMisc.gmk Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/make/gensrc/GensrcMisc.gmk Sat Mar 05 20:46:44 2016 -0800
@@ -25,11 +25,11 @@
##########################################################################################
# Install the launcher name, release version string, full version
-# string and the runtime name into the Version.java file.
+# string and the runtime name into the VersionProps.java file.
$(eval $(call SetupTextFileProcessing, BUILD_VERSION_JAVA, \
- SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template, \
- OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java, \
+ SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/VersionProps.java.template, \
+ OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/VersionProps.java, \
REPLACEMENTS := \
@@LAUNCHER_NAME@@ => $(LAUNCHER_NAME) ; \
@@RUNTIME_NAME@@ => $(RUNTIME_NAME) ; \
--- a/jdk/make/mapfiles/libjava/mapfile-vers Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Sat Mar 05 20:46:44 2016 -0800
@@ -268,8 +268,6 @@
Java_sun_reflect_Reflection_getCallerClass__;
Java_sun_reflect_Reflection_getCallerClass__I;
Java_sun_reflect_Reflection_getClassAccessFlags;
- Java_sun_misc_Version_getJdkVersionInfo;
- Java_sun_misc_Version_getJvmVersionInfo;
Java_jdk_internal_misc_VM_latestUserDefinedLoader;
Java_jdk_internal_misc_VM_getuid;
Java_jdk_internal_misc_VM_geteuid;
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -133,39 +133,62 @@
}
/**
- * This method has the same contract as ensureCapacity, but is
- * never synchronized.
+ * For positive values of {@code minimumCapacity}, this method
+ * behaves like {@code ensureCapacity}, however it is never
+ * synchronized.
+ * If {@code minimumCapacity} is non positive due to numeric
+ * overflow, this method throws {@code OutOfMemoryError}.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
- int capacity = value.length >> coder;
- if (minimumCapacity - capacity > 0) {
- expandCapacity(minimumCapacity);
+ int oldCapacity = value.length >> coder;
+ if (minimumCapacity - oldCapacity > 0) {
+ value = Arrays.copyOf(value,
+ newCapacity(minimumCapacity) << coder);
}
}
/**
- * This implements the expansion semantics of ensureCapacity with no
- * size check or synchronization.
+ * The maximum size of array to allocate (unless necessary).
+ * Some VMs reserve some header words in an array.
+ * Attempts to allocate larger arrays may result in
+ * OutOfMemoryError: Requested array size exceeds VM limit
*/
- private void expandCapacity(int minimumCapacity) {
- int newCapacity = (value.length >> coder) * 2 + 2;
- if (newCapacity - minimumCapacity < 0) {
- newCapacity = minimumCapacity;
+ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+ /**
+ * Returns a capacity at least as large as the given minimum capacity.
+ * Returns the current capacity increased by the same amount + 2 if
+ * that suffices.
+ * Will not return a capacity greater than
+ * {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity
+ * is greater than that.
+ *
+ * @param minCapacity the desired minimum capacity
+ * @throws OutOfMemoryError if minCapacity is less than zero or
+ * greater than (Integer.MAX_VALUE >> coder)
+ */
+ private int newCapacity(int minCapacity) {
+ // overflow-conscious code
+ int oldCapacity = value.length >> coder;
+ int newCapacity = (oldCapacity << 1) + 2;
+ if (newCapacity - minCapacity < 0) {
+ newCapacity = minCapacity;
}
- if (newCapacity < 0) {
- if (minimumCapacity < 0) {// overflow
- throw new OutOfMemoryError();
- }
- newCapacity = Integer.MAX_VALUE;
+ int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
+ return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
+ ? hugeCapacity(minCapacity)
+ : newCapacity;
+ }
+
+ private int hugeCapacity(int minCapacity) {
+ int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
+ int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
+ if (UNSAFE_BOUND - minCapacity < 0) { // overflow
+ throw new OutOfMemoryError();
}
- if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
- if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
- throw new OutOfMemoryError();
- }
- newCapacity = StringUTF16.MAX_LENGTH;
- }
- this.value = Arrays.copyOf(value, newCapacity << coder);
+ return (minCapacity > SAFE_BOUND)
+ ? minCapacity : SAFE_BOUND;
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/System.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, 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
@@ -1418,8 +1418,7 @@
* for the given {@code caller}.
*
* @param name the name of the logger.
- * @param caller the class for which the logger is being requested;
- * can be {@code null}.
+ * @param caller the class for which the logger is being requested.
*
* @return a {@link Logger logger} suitable for the given caller's
* use.
@@ -1831,7 +1830,7 @@
lineSeparator = props.getProperty("line.separator");
- sun.misc.Version.init();
+ VersionProps.init();
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.io.PrintStream;
+
+class VersionProps {
+
+
+ private static final String launcher_name =
+ "@@LAUNCHER_NAME@@";
+
+ private static final String java_version =
+ "@@VERSION_SHORT@@";
+
+ private static final String java_runtime_name =
+ "@@RUNTIME_NAME@@";
+
+ private static final String java_runtime_version =
+ "@@VERSION_STRING@@";
+
+ static {
+ init();
+ }
+
+ public static void init() {
+ System.setProperty("java.version", java_version);
+ System.setProperty("java.runtime.version", java_runtime_version);
+ System.setProperty("java.runtime.name", java_runtime_name);
+ }
+
+ /**
+ * In case you were wondering this method is called by java -version.
+ * Sad that it prints to stderr; would be nicer if default printed on
+ * stdout.
+ */
+ public static void print() {
+ print(System.err);
+ }
+
+ /**
+ * This is the same as print except that it adds an extra line-feed
+ * at the end, typically used by the -showversion in the launcher
+ */
+ public static void println() {
+ print(System.err);
+ System.err.println();
+ }
+
+ /**
+ * Give a stream, it will print version info on it.
+ */
+ public static void print(PrintStream ps) {
+ boolean isHeadless = false;
+
+ /* Report that we're running headless if the property is true */
+ String headless = System.getProperty("java.awt.headless");
+ if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
+ isHeadless = true;
+ }
+
+ /* First line: platform version. */
+ ps.println(launcher_name + " version \"" + java_version + "\"");
+
+ /* Second line: runtime version (ie, libraries). */
+
+ String jdk_debug_level = System.getProperty("jdk.debug", "release");
+ /* Debug level is not printed for "release" builds */
+ if ("release".equals(jdk_debug_level)) {
+ jdk_debug_level = "";
+ } else {
+ jdk_debug_level = jdk_debug_level + " ";
+ }
+
+ ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
+
+ if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
+ // embedded builds report headless state
+ ps.print(", headless");
+ }
+ ps.println(')');
+
+ /* Third line: JVM information. */
+ String java_vm_name = System.getProperty("java.vm.name");
+ String java_vm_version = System.getProperty("java.vm.version");
+ String java_vm_info = System.getProperty("java.vm.info");
+ ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " +
+ java_vm_info + ")");
+ }
+
+}
\ No newline at end of file
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Sat Mar 05 20:46:44 2016 -0800
@@ -3268,12 +3268,17 @@
* <li>This list of types is called the "common prefix".
* </ol>
* <p>
- * <em>Step 1B: Determine loop parameters.</em><ol type="a">
- * <li>Examine init function parameter lists.
- * <li>Omitted init functions are deemed to have {@code null} parameter lists.
- * <li>All init function parameter lists must be effectively identical.
- * <li>The longest parameter list (which is necessarily unique) is called the "common suffix".
+ * <em>Step 1B: Determine loop parameters.</em><ul>
+ * <li><b>If at least one init function is given,</b><ol type="a">
+ * <li>Examine init function parameter lists.
+ * <li>Omitted init functions are deemed to have {@code null} parameter lists.
+ * <li>All init function parameter lists must be effectively identical.
+ * <li>The longest parameter list (which is necessarily unique) is called the "common suffix".
* </ol>
+ * <li><b>If no init function is given,</b><ol type="a">
+ * <li>Examine the suffixes of the step, pred, and fini parameter lists, after removing the "common prefix".
+ * <li>The longest of these suffixes is taken as the "common suffix".
+ * </ol></ul>
* <p>
* <em>Step 1C: Determine loop return type.</em><ol type="a">
* <li>Examine fini function return types, disregarding omitted fini functions.
@@ -3286,9 +3291,6 @@
* <li>Every non-omitted pred function must have a {@code boolean} return type.
* </ol>
* <p>
- * (Implementation Note: Steps 1A, 1B, 1C, 1D are logically independent of each other, and may be performed in any
- * order.)
- * <p>
* <em>Step 2: Determine parameter lists.</em><ol type="a">
* <li>The parameter list for the resulting loop handle will be the "common suffix".
* <li>The parameter list for init functions will be adjusted to the "common suffix". (Note that their parameter
@@ -3375,10 +3377,10 @@
* <blockquote><pre>{@code
* // iterative implementation of the factorial function as a loop handle
* static int one(int k) { return 1; }
- * int inc(int i, int acc, int k) { return i + 1; }
- * int mult(int i, int acc, int k) { return i * acc; }
- * boolean pred(int i, int acc, int k) { return i < k; }
- * int fin(int i, int acc, int k) { return acc; }
+ * static int inc(int i, int acc, int k) { return i + 1; }
+ * static int mult(int i, int acc, int k) { return i * acc; }
+ * static boolean pred(int i, int acc, int k) { return i < k; }
+ * static int fin(int i, int acc, int k) { return acc; }
* // assume MH_one, MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods
* // null initializer for counter, should initialize to 0
* MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
@@ -3436,9 +3438,7 @@
collect(Collectors.toList());
// Step 1B: determine loop parameters.
- final List<Class<?>> empty = new ArrayList<>();
- final List<Class<?>> commonSuffix = init.stream().filter(Objects::nonNull).map(MethodHandle::type).
- map(MethodType::parameterList).reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+ final List<Class<?>> commonSuffix = buildCommonSuffix(init, step, pred, fini, commonPrefix.size());
checkLoop1b(init, commonSuffix);
// Step 1C: determine loop return type.
@@ -3520,15 +3520,15 @@
* @apiNote Example:
* <blockquote><pre>{@code
* // implement the zip function for lists as a loop handle
- * List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); }
- * boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); }
- * List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+ * static List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); }
+ * static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); }
+ * static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
* zip.add(a.next());
* zip.add(b.next());
* return zip;
* }
* // assume MH_initZip, MH_zipPred, and MH_zipStep are handles to the above methods
- * MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred);
+ * MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep);
* List<String> a = Arrays.asList("a", "b", "c", "d");
* List<String> b = Arrays.asList("e", "f", "g", "h");
* List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
@@ -3594,9 +3594,9 @@
* @apiNote Example:
* <blockquote><pre>{@code
* // int i = 0; while (i < limit) { ++i; } return i; => limit
- * int zero(int limit) { return 0; }
- * int step(int i, int limit) { return i + 1; }
- * boolean pred(int i, int limit) { return i < limit; }
+ * static int zero(int limit) { return 0; }
+ * static int step(int i, int limit) { return i + 1; }
+ * static boolean pred(int i, int limit) { return i < limit; }
* // assume MH_zero, MH_step, and MH_pred are handles to the above methods
* MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
* assertEquals(23, loop.invoke(23));
@@ -3664,8 +3664,8 @@
* <blockquote><pre>{@code
* // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
* // => a variation on a well known theme
- * String start(String arg) { return arg; }
- * String step(int counter, String v, String arg) { return "na " + v; }
+ * static String start(String arg) { return arg; }
+ * static String step(int counter, String v, String arg) { return "na " + v; }
* // assume MH_start and MH_step are handles to the two methods above
* MethodHandle fit13 = MethodHandles.constant(int.class, 13);
* MethodHandle loop = MethodHandles.countedLoop(fit13, MH_start, MH_step);
@@ -3808,11 +3808,11 @@
* @apiNote Example:
* <blockquote><pre>{@code
* // reverse a list
- * List<String> reverseStep(String e, List<String> r, List<String> l) {
+ * static List<String> reverseStep(String e, List<String> r, List<String> l) {
* r.add(0, e);
* return r;
* }
- * List<String> newArrayList(List<String> l) { return new ArrayList<>(); }
+ * static List<String> newArrayList(List<String> l) { return new ArrayList<>(); }
* // assume MH_reverseStep, MH_newArrayList are handles to the above methods
* MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
* List<String> list = Arrays.asList("a", "b", "c", "d", "e");
@@ -4084,6 +4084,21 @@
}
}
+ private static List<Class<?>> buildCommonSuffix(List<MethodHandle> init, List<MethodHandle> step, List<MethodHandle> pred, List<MethodHandle> fini, int cpSize) {
+ final List<Class<?>> empty = List.of();
+ final List<MethodHandle> nonNullInits = init.stream().filter(Objects::nonNull).collect(Collectors.toList());
+ if (nonNullInits.isEmpty()) {
+ final List<Class<?>> longest = Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).
+ // take only those that can contribute to a common suffix because they are longer than the prefix
+ map(MethodHandle::type).filter(t -> t.parameterCount() > cpSize).map(MethodType::parameterList).
+ reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+ return longest.size() == 0 ? empty : longest.subList(cpSize, longest.size());
+ } else {
+ return nonNullInits.stream().map(MethodHandle::type).map(MethodType::parameterList).
+ reduce((p, q) -> p.size() >= q.size() ? p : q).get();
+ }
+ }
+
private static void checkLoop1b(List<MethodHandle> init, List<Class<?>> commonSuffix) {
if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::parameterList).
anyMatch(pl -> !pl.equals(commonSuffix.subList(0, pl.size())))) {
@@ -4109,8 +4124,10 @@
}
private static void checkLoop2(List<MethodHandle> step, List<MethodHandle> pred, List<MethodHandle> fini, List<Class<?>> commonParameterSequence) {
+ final int cpSize = commonParameterSequence.size();
if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type).
- map(MethodType::parameterList).anyMatch(pl -> !pl.equals(commonParameterSequence.subList(0, pl.size())))) {
+ map(MethodType::parameterList).
+ anyMatch(pl -> pl.size() > cpSize || !pl.equals(commonParameterSequence.subList(0, pl.size())))) {
throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step +
"\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")");
}
@@ -4137,8 +4154,10 @@
// The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the
// target parameter list.
int cleanupArgIndex = rtype == void.class ? 1 : 2;
- if (!cleanupParamTypes.subList(cleanupArgIndex, cleanupParamTypes.size()).
- equals(target.type().parameterList().subList(0, cleanupParamTypes.size() - cleanupArgIndex))) {
+ List<Class<?>> cleanupArgSuffix = cleanupParamTypes.subList(cleanupArgIndex, cleanupParamTypes.size());
+ List<Class<?>> targetParamTypes = target.type().parameterList();
+ if (targetParamTypes.size() < cleanupArgSuffix.size() ||
+ !cleanupArgSuffix.equals(targetParamTypes.subList(0, cleanupParamTypes.size() - cleanupArgIndex))) {
throw misMatchedTypes("cleanup parameters after (Throwable,result) and target parameter list prefix",
cleanup.type(), target.type());
}
--- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -27,9 +27,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
-import java.io.InterruptedIOException;
import java.util.Set;
-import java.util.HashSet;
/**
* Abstract datagram and multicast socket implementation base class.
@@ -352,32 +350,32 @@
}
}
- private static final Set<SocketOption<?>> dgSocketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> dgSocketOptions;
- private static final Set<SocketOption<?>> mcSocketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> mcSocketOptions;
static {
- dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
- dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
- dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- dgSocketOptions.add(StandardSocketOptions.IP_TOS);
+ dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
+ StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.IP_TOS);
- mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF);
- mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
- mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- mcSocketOptions.add(StandardSocketOptions.IP_TOS);
- mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF);
- mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL);
- mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP);
- };
+ mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
+ StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.IP_TOS,
+ StandardSocketOptions.IP_MULTICAST_IF,
+ StandardSocketOptions.IP_MULTICAST_TTL,
+ StandardSocketOptions.IP_MULTICAST_LOOP);
+ }
/**
* Returns a set of SocketOptions supported by this impl
* and by this impl's socket (DatagramSocket or MulticastSocket)
*
* @return a Set of SocketOptions
+ *
+ * @since 9
*/
protected Set<SocketOption<?>> supportedOptions() {
if (getDatagramSocket() instanceof MulticastSocket) {
--- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -30,8 +30,6 @@
import java.io.OutputStream;
import java.io.FileDescriptor;
import java.util.Set;
-import java.util.HashSet;
-import java.util.Collections;
/**
* The abstract class {@code SocketImpl} is a common superclass
@@ -445,31 +443,31 @@
}
}
- private static final Set<SocketOption<?>> socketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> socketOptions;
- private static final Set<SocketOption<?>> serverSocketOptions =
- new HashSet<>();
+ private static final Set<SocketOption<?>> serverSocketOptions;
static {
- socketOptions.add(StandardSocketOptions.SO_KEEPALIVE);
- socketOptions.add(StandardSocketOptions.SO_SNDBUF);
- socketOptions.add(StandardSocketOptions.SO_RCVBUF);
- socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- socketOptions.add(StandardSocketOptions.SO_LINGER);
- socketOptions.add(StandardSocketOptions.IP_TOS);
- socketOptions.add(StandardSocketOptions.TCP_NODELAY);
+ socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE,
+ StandardSocketOptions.SO_SNDBUF,
+ StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.SO_LINGER,
+ StandardSocketOptions.IP_TOS,
+ StandardSocketOptions.TCP_NODELAY);
- serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
- serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
- serverSocketOptions.add(StandardSocketOptions.IP_TOS);
- };
+ serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
+ StandardSocketOptions.SO_REUSEADDR,
+ StandardSocketOptions.IP_TOS);
+ }
/**
* Returns a set of SocketOptions supported by this impl
* and by this impl's socket (Socket or ServerSocket)
*
* @return a Set of SocketOptions
+ *
+ * @since 9
*/
protected Set<SocketOption<?>> supportedOptions() {
if (getSocket() != null) {
--- a/jdk/src/java.base/share/classes/java/nio/Bits.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Bits.java Sat Mar 05 20:46:44 2016 -0800
@@ -736,202 +736,9 @@
});
}
- // -- Bulk get/put acceleration --
-
// These numbers represent the point at which we have empirically
// determined that the average cost of a JNI call exceeds the expense
// of an element by element copy. These numbers may change over time.
static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
-
- // This number limits the number of bytes to copy per call to Unsafe's
- // copyMemory method. A limit is imposed to allow for safepoint polling
- // during a large copy
- static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
-
- // These methods do no bounds checking. Verification that the copy will not
- // result in memory corruption should be done prior to invocation.
- // All positions and lengths are specified in bytes.
-
- /**
- * Copy from given source array to destination address.
- *
- * @param src
- * source array
- * @param srcBaseOffset
- * offset of first element of storage in source array
- * @param srcPos
- * offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
- long dstAddr, long length)
- {
- long offset = srcBaseOffset + srcPos;
- while (length > 0) {
- long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
- unsafe.copyMemory(src, offset, null, dstAddr, size);
- length -= size;
- offset += size;
- dstAddr += size;
- }
- }
-
- /**
- * Copy from source address into given destination array.
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array
- * @param dstBaseOffset
- * offset of first element of storage in destination array
- * @param dstPos
- * offset within destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,
- long length)
- {
- long offset = dstBaseOffset + dstPos;
- while (length > 0) {
- long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
- unsafe.copyMemory(null, srcAddr, dst, offset, size);
- length -= size;
- srcAddr += size;
- offset += size;
- }
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 16-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 16-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 16-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 16-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
- }
-
- /**
- * Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 32-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);
- }
-
- /**
- * Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 32-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);
- }
-
- /**
- * Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory
- *
- * @param src
- * the source array, must be a 64-bit primitive array type
- * @param srcPos
- * byte offset within source array of the first element to read
- * @param dstAddr
- * destination address
- * @param length
- * number of bytes to copy
- */
- static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {
- unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);
- }
-
- /**
- * Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array
- *
- * @param srcAddr
- * source address
- * @param dst
- * destination array, must be a 64-bit primitive array type
- * @param dstPos
- * byte offset within the destination array of the first element to write
- * @param length
- * number of bytes to copy
- */
- static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {
- unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);
- }
}
--- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -270,16 +270,22 @@
if (length > rem)
throw new BufferUnderflowException();
+ long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
#if[!byte]
if (order() != ByteOrder.nativeOrder())
- Bits.copyTo$Memtype$Array(ix(pos), dst,
- (long)offset << $LG_BYTES_PER_VALUE$,
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copySwapMemory(null,
+ ix(pos),
+ dst,
+ dstOffset,
+ (long)length << $LG_BYTES_PER_VALUE$,
+ (long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
- Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
- (long)offset << $LG_BYTES_PER_VALUE$,
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copyMemory(null,
+ ix(pos),
+ dst,
+ dstOffset,
+ (long)length << $LG_BYTES_PER_VALUE$);
position(pos + length);
} else {
super.get(dst, offset, length);
@@ -362,18 +368,22 @@
if (length > rem)
throw new BufferOverflowException();
+ long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
#if[!byte]
if (order() != ByteOrder.nativeOrder())
- Bits.copyFrom$Memtype$Array(src,
- (long)offset << $LG_BYTES_PER_VALUE$,
- ix(pos),
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copySwapMemory(src,
+ srcOffset,
+ null,
+ ix(pos),
+ (long)length << $LG_BYTES_PER_VALUE$,
+ (long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
- Bits.copyFromArray(src, arrayBaseOffset,
- (long)offset << $LG_BYTES_PER_VALUE$,
- ix(pos),
- (long)length << $LG_BYTES_PER_VALUE$);
+ unsafe.copyMemory(src,
+ srcOffset,
+ null,
+ ix(pos),
+ (long)length << $LG_BYTES_PER_VALUE$);
position(pos + length);
} else {
super.put(src, offset, length);
--- a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -606,7 +606,7 @@
try
{
DateFormatSymbols other = (DateFormatSymbols)super.clone();
- copyMembers(this, other);
+ copyMembers(new SymbolsCacheEntry(locale), other);
return other;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
@@ -669,7 +669,7 @@
/**
* Cache to hold DateFormatSymbols instances per Locale.
*/
- private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
+ private static final ConcurrentMap<Locale, SoftReference<SymbolsCacheEntry>> cachedInstances
= new ConcurrentHashMap<>(3);
private transient int lastZoneIndex;
@@ -683,10 +683,10 @@
locale = desiredLocale;
// Copy values of a cached instance if any.
- SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
- DateFormatSymbols dfs;
- if (ref != null && (dfs = ref.get()) != null) {
- copyMembers(dfs, this);
+ SoftReference<SymbolsCacheEntry> ref = cachedInstances.get(locale);
+ SymbolsCacheEntry sce;
+ if (ref != null && (sce = ref.get()) != null) {
+ copyMembers(sce, this);
return;
}
@@ -717,11 +717,11 @@
weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
- // Put a clone in the cache
- ref = new SoftReference<>((DateFormatSymbols)this.clone());
- SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
+ sce = new SymbolsCacheEntry(locale);
+ ref = new SoftReference<>(sce);
+ SoftReference<SymbolsCacheEntry> x = cachedInstances.putIfAbsent(locale, ref);
if (x != null) {
- DateFormatSymbols y = x.get();
+ SymbolsCacheEntry y = x.get();
if (y == null) {
// Replace the empty SoftReference with ref.
cachedInstances.put(locale, ref);
@@ -812,7 +812,7 @@
* @param src the source DateFormatSymbols.
* @param dst the target DateFormatSymbols.
*/
- private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
+ private void copyMembers(SymbolsCacheEntry src, DateFormatSymbols dst)
{
dst.eras = Arrays.copyOf(src.eras, src.eras.length);
dst.months = Arrays.copyOf(src.months, src.months.length);
@@ -821,7 +821,7 @@
dst.shortWeekdays = Arrays.copyOf(src.shortWeekdays, src.shortWeekdays.length);
dst.ampms = Arrays.copyOf(src.ampms, src.ampms.length);
if (src.zoneStrings != null) {
- dst.zoneStrings = src.getZoneStringsImpl(true);
+ dst.zoneStrings = getZoneStringsImpl(true);
} else {
dst.zoneStrings = null;
}
@@ -842,4 +842,43 @@
}
stream.defaultWriteObject();
}
+
+ private static class SymbolsCacheEntry {
+
+ final String eras[];
+ final String months[];
+ final String shortMonths[];
+ final String weekdays[];
+ final String shortWeekdays[];
+ final String ampms[];
+ final String zoneStrings[][];
+ final String localPatternChars;
+
+ SymbolsCacheEntry(Locale locale) {
+ // Initialize the fields from the ResourceBundle for locale.
+ LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
+ // Avoid any potential recursions
+ if (!(adapter instanceof ResourceBundleBasedAdapter)) {
+ adapter = LocaleProviderAdapter.getResourceBundleBased();
+ }
+ ResourceBundle resource = ((ResourceBundleBasedAdapter) adapter).getLocaleData().getDateFormatData(locale);
+ if (resource.containsKey("Eras")) {
+ this.eras = resource.getStringArray("Eras");
+ } else if (resource.containsKey("long.Eras")) {
+ this.eras = resource.getStringArray("long.Eras");
+ } else if (resource.containsKey("short.Eras")) {
+ this.eras = resource.getStringArray("short.Eras");
+ } else {
+ this.eras = null;
+ }
+ this.months = resource.getStringArray("MonthNames");
+ this.shortMonths = resource.getStringArray("MonthAbbreviations");
+ this.weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
+ this.shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
+ this.ampms = resource.getStringArray("AmPmMarkers");
+ this.zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
+ this.localPatternChars = resource.getString("DateTimePatternChars");
+
+ }
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Sat Mar 05 20:46:44 2016 -0800
@@ -219,12 +219,20 @@
return seed += gamma;
}
+ // IllegalArgumentException messages
+ static final String BAD_BOUND = "bound must be positive";
+ static final String BAD_RANGE = "bound must be greater than origin";
+ static final String BAD_SIZE = "size must be non-negative";
+
/**
* The seed generator for default constructors.
*/
- private static final AtomicLong defaultGen = new AtomicLong(initialSeed());
+ private static final AtomicLong defaultGen
+ = new AtomicLong(mix64(System.currentTimeMillis()) ^
+ mix64(System.nanoTime()));
- private static long initialSeed() {
+ // at end of <clinit> to survive static initialization circularity
+ static {
if (java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Boolean>() {
public Boolean run() {
@@ -234,17 +242,10 @@
long s = (long)seedBytes[0] & 0xffL;
for (int i = 1; i < 8; ++i)
s = (s << 8) | ((long)seedBytes[i] & 0xffL);
- return s;
+ defaultGen.set(s);
}
- return (mix64(System.currentTimeMillis()) ^
- mix64(System.nanoTime()));
}
- // IllegalArgumentException messages
- static final String BAD_BOUND = "bound must be positive";
- static final String BAD_RANGE = "bound must be greater than origin";
- static final String BAD_SIZE = "size must be non-negative";
-
/*
* Internal versions of nextX methods used by streams, as well as
* the public nextX(origin, bound) methods. These exist mainly to
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Sat Mar 05 20:46:44 2016 -0800
@@ -125,53 +125,6 @@
* but we provide identical statistical properties.
*/
- /** Generates per-thread initialization/probe field */
- private static final AtomicInteger probeGenerator = new AtomicInteger();
-
- /**
- * The next seed for default constructors.
- */
- private static final AtomicLong seeder = new AtomicLong(initialSeed());
-
- private static long initialSeed() {
- if (java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Boolean>() {
- public Boolean run() {
- return Boolean.getBoolean("java.util.secureRandomSeed");
- }})) {
- byte[] seedBytes = java.security.SecureRandom.getSeed(8);
- long s = (long)seedBytes[0] & 0xffL;
- for (int i = 1; i < 8; ++i)
- s = (s << 8) | ((long)seedBytes[i] & 0xffL);
- return s;
- }
- return (mix64(System.currentTimeMillis()) ^
- mix64(System.nanoTime()));
- }
-
- /**
- * The seed increment.
- */
- private static final long GAMMA = 0x9e3779b97f4a7c15L;
-
- /**
- * The increment for generating probe values.
- */
- private static final int PROBE_INCREMENT = 0x9e3779b9;
-
- /**
- * The increment of seeder per new instance.
- */
- private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
-
- // Constants from SplittableRandom
- private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
- private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
-
- /** Rarely-used holder for the second of a pair of Gaussians */
- private static final ThreadLocal<Double> nextLocalGaussian =
- new ThreadLocal<>();
-
private static long mix64(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
@@ -194,9 +147,6 @@
initialized = true; // false during super() call
}
- /** The common ThreadLocalRandom */
- static final ThreadLocalRandom instance = new ThreadLocalRandom();
-
/**
* Initialize Thread fields for the current thread. Called only
* when Thread.threadLocalRandomProbe is zero, indicating that a
@@ -248,11 +198,6 @@
return (int)(mix64(nextSeed()) >>> (64 - bits));
}
- // IllegalArgumentException messages
- static final String BAD_BOUND = "bound must be positive";
- static final String BAD_RANGE = "bound must be greater than origin";
- static final String BAD_SIZE = "size must be non-negative";
-
/**
* The form of nextLong used by LongStream Spliterators. If
* origin is greater than bound, acts as unbounded form of
@@ -1050,6 +995,32 @@
return current();
}
+ // Static initialization
+
+ /**
+ * The seed increment.
+ */
+ private static final long GAMMA = 0x9e3779b97f4a7c15L;
+
+ /**
+ * The increment for generating probe values.
+ */
+ private static final int PROBE_INCREMENT = 0x9e3779b9;
+
+ /**
+ * The increment of seeder per new instance.
+ */
+ private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
+
+ // Constants from SplittableRandom
+ private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
+ private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
+
+ // IllegalArgumentException messages
+ static final String BAD_BOUND = "bound must be positive";
+ static final String BAD_RANGE = "bound must be greater than origin";
+ static final String BAD_SIZE = "size must be non-negative";
+
// Unsafe mechanics
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long SEED;
@@ -1067,4 +1038,36 @@
throw new Error(e);
}
}
+
+ /** Rarely-used holder for the second of a pair of Gaussians */
+ private static final ThreadLocal<Double> nextLocalGaussian =
+ new ThreadLocal<>();
+
+ /** Generates per-thread initialization/probe field */
+ private static final AtomicInteger probeGenerator = new AtomicInteger();
+
+ /** The common ThreadLocalRandom */
+ static final ThreadLocalRandom instance = new ThreadLocalRandom();
+
+ /**
+ * The next seed for default constructors.
+ */
+ private static final AtomicLong seeder
+ = new AtomicLong(mix64(System.currentTimeMillis()) ^
+ mix64(System.nanoTime()));
+
+ // at end of <clinit> to survive static initialization circularity
+ static {
+ if (java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ return Boolean.getBoolean("java.util.secureRandomSeed");
+ }})) {
+ byte[] seedBytes = java.security.SecureRandom.getSeed(8);
+ long s = (long)seedBytes[0] & 0xffL;
+ for (int i = 1; i < 8; ++i)
+ s = (s << 8) | ((long)seedBytes[i] & 0xffL);
+ seeder.set(s);
+ }
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Sat Mar 05 20:46:44 2016 -0800
@@ -158,7 +158,7 @@
RUNTIME_VERSION = AccessController.doPrivileged(
new PrivilegedAction<Integer>() {
public Integer run() {
- Integer v = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 Version integrated
+ Integer v = jdk.Version.current().major();
Integer i = Integer.getInteger("jdk.util.jar.version", v);
i = i < 0 ? 0 : i;
return i > v ? v : i;
@@ -359,7 +359,7 @@
}
private boolean runtimeVersionExists() {
- int version = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 integrated
+ int version = jdk.Version.current().major();
try {
Release.valueOf(version);
return true;
@@ -893,11 +893,15 @@
}
private JarEntry verifiableEntry(ZipEntry ze) {
- if (!(ze instanceof JarFileEntry)) {
- ze = getJarEntry(ze.getName());
+ if (ze instanceof JarFileEntry) {
+ // assure the name and entry match for verification
+ return ((JarFileEntry)ze).reifiedEntry();
}
- // assure the name and entry match for verification
- return ze == null ? null : ((JarFileEntry)ze).reifiedEntry();
+ ze = getJarEntry(ze.getName());
+ if (ze instanceof JarFileEntry) {
+ return ((JarFileEntry)ze).reifiedEntry();
+ }
+ return (JarEntry)ze;
}
// Statics for hand-coded Boyer-Moore search
--- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -327,6 +327,8 @@
@Override
@SuppressWarnings("unchecked")
public S onClose(Runnable closeHandler) {
+ if (linkedOrConsumed)
+ throw new IllegalStateException(MSG_STREAM_LINKED);
Objects.requireNonNull(closeHandler);
Runnable existingHandler = sourceStage.sourceCloseAction;
sourceStage.sourceCloseAction =
--- a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -949,24 +949,100 @@
*/
public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() {
- double t = seed;
+ Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ double prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ double t;
+ if (started)
+ t = f.applyAsDouble(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.doubleStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code DoubleStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code DoubleStream.iterate} should produce the same sequence of
+ * elements as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (double index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code DoubleStream}
+ * @since 9
+ */
+ public static DoubleStream iterate(double seed, DoublePredicate predicate, DoubleUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ double prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ double t;
+ if (started)
+ t = f.applyAsDouble(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public double nextDouble() {
- double v = t;
- t = f.applyAsDouble(t);
- return v;
+ public void forEachRemaining(DoubleConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ double t = started ? f.applyAsDouble(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsDouble(t);
+ }
}
};
- return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.doubleStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -885,28 +885,104 @@
* @param seed the initial element
* @param f a function to be applied to the previous element to produce
* a new element
- * @return A new sequential {@code IntStream}
+ * @return a new sequential {@code IntStream}
*/
public static IntStream iterate(final int seed, final IntUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfInt iterator = new PrimitiveIterator.OfInt() {
- int t = seed;
+ Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ int prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(IntConsumer action) {
+ Objects.requireNonNull(action);
+ int t;
+ if (started)
+ t = f.applyAsInt(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.intStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code IntStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code IntStream.iterate} should produce the same sequence of elements
+ * as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (int index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code IntStream}
+ * @since 9
+ */
+ public static IntStream iterate(int seed, IntPredicate predicate, IntUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ int prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ int t;
+ if (started)
+ t = f.applyAsInt(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public int nextInt() {
- int v = t;
- t = f.applyAsInt(t);
- return v;
+ public void forEachRemaining(IntConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ int t = started ? f.applyAsInt(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsInt(t);
+ }
}
};
- return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.intStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -879,24 +879,100 @@
*/
public static LongStream iterate(final long seed, final LongUnaryOperator f) {
Objects.requireNonNull(f);
- final PrimitiveIterator.OfLong iterator = new PrimitiveIterator.OfLong() {
- long t = seed;
+ Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ long prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(LongConsumer action) {
+ Objects.requireNonNull(action);
+ long t;
+ if (started)
+ t = f.applyAsLong(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.longStream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code LongStream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code LongStream.iterate} should produce the same sequence of elements
+ * as produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (long index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code LongStream}
+ * @since 9
+ */
+ public static LongStream iterate(long seed, LongPredicate predicate, LongUnaryOperator f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
+ long prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(LongConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ long t;
+ if (started)
+ t = f.applyAsLong(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public long nextLong() {
- long v = t;
- t = f.applyAsLong(t);
- return v;
+ public void forEachRemaining(LongConsumer action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ long t = started ? f.applyAsLong(prev) : seed;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.applyAsLong(t);
+ }
}
};
- return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
+ return StreamSupport.longStream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.Objects;
import java.util.Optional;
import java.util.Spliterator;
@@ -1185,23 +1184,103 @@
*/
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
Objects.requireNonNull(f);
- final Iterator<T> iterator = new Iterator<T>() {
- @SuppressWarnings("unchecked")
- T t = (T) Streams.NONE;
+ Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE) {
+ T prev;
+ boolean started;
@Override
- public boolean hasNext() {
+ public boolean tryAdvance(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ T t;
+ if (started)
+ t = f.apply(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ action.accept(prev = t);
+ return true;
+ }
+ };
+ return StreamSupport.stream(spliterator, false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream} produced by iterative
+ * application of a function to an initial element, conditioned on
+ * satisfying the supplied predicate. The stream terminates as soon as
+ * the predicate returns false.
+ *
+ * <p>
+ * {@code Stream.iterate} should produce the same sequence of elements as
+ * produced by the corresponding for-loop:
+ * <pre>{@code
+ * for (T index=seed; predicate.test(index); index = f.apply(index)) {
+ * ...
+ * }
+ * }</pre>
+ *
+ * <p>
+ * The resulting sequence may be empty if the predicate does not hold on
+ * the seed value. Otherwise the first element will be the supplied seed
+ * value, the next element (if present) will be the result of applying the
+ * function f to the seed value, and so on iteratively until the predicate
+ * indicates that the stream should terminate.
+ *
+ * @param <T> the type of stream elements
+ * @param seed the initial element
+ * @param predicate a predicate to apply to elements to determine when the
+ * stream must terminate.
+ * @param f a function to be applied to the previous element to produce
+ * a new element
+ * @return a new sequential {@code Stream}
+ * @since 9
+ */
+ public static<T> Stream<T> iterate(T seed, Predicate<? super T> predicate, UnaryOperator<T> f) {
+ Objects.requireNonNull(f);
+ Objects.requireNonNull(predicate);
+ Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
+ Spliterator.ORDERED | Spliterator.IMMUTABLE) {
+ T prev;
+ boolean started, finished;
+
+ @Override
+ public boolean tryAdvance(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return false;
+ T t;
+ if (started)
+ t = f.apply(prev);
+ else {
+ t = seed;
+ started = true;
+ }
+ if (!predicate.test(t)) {
+ prev = null;
+ finished = true;
+ return false;
+ }
+ action.accept(prev = t);
return true;
}
@Override
- public T next() {
- return t = (t == Streams.NONE) ? seed : f.apply(t);
+ public void forEachRemaining(Consumer<? super T> action) {
+ Objects.requireNonNull(action);
+ if (finished)
+ return;
+ finished = true;
+ T t = started ? f.apply(prev) : seed;
+ prev = null;
+ while (predicate.test(t)) {
+ action.accept(t);
+ t = f.apply(t);
+ }
}
};
- return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
- iterator,
- Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
+ return StreamSupport.stream(spliterator, false);
}
/**
--- a/jdk/src/java.base/share/classes/java/util/stream/Streams.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/Streams.java Sat Mar 05 20:46:44 2016 -0800
@@ -49,14 +49,6 @@
}
/**
- * An object instance representing no value, that cannot be an actual
- * data element of a stream. Used when processing streams that can contain
- * {@code null} elements to distinguish between a {@code null} value and no
- * value.
- */
- static final Object NONE = new Object();
-
- /**
* An {@code int} range spliterator.
*/
static final class RangeIntSpliterator implements Spliterator.OfInt {
--- a/jdk/src/java.base/share/classes/jdk/Version.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/Version.java Sat Mar 05 20:46:44 2016 -0800
@@ -28,10 +28,10 @@
import java.math.BigInteger;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@@ -208,11 +208,10 @@
+ s + "'");
// $VNUM is a dot-separated list of integers of arbitrary length
- version
- = Collections.unmodifiableList(
- Arrays.stream(m.group(VNUM_GROUP).split("\\."))
- .map(Integer::parseInt)
- .collect(Collectors.toList()));
+ List<Integer> list = new ArrayList<>();
+ for (String i : m.group(VNUM_GROUP).split("\\."))
+ list.add(Integer.parseInt(i));
+ version = Collections.unmodifiableList(list);
pre = Optional.ofNullable(m.group(PRE_GROUP));
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java Sat Mar 05 20:46:44 2016 -0800
@@ -118,6 +118,8 @@
}
public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() {
+ if (javaNetInetAddressAccess == null)
+ unsafe.ensureClassInitialized(java.net.InetAddress.class);
return javaNetInetAddressAccess;
}
--- a/jdk/src/java.base/share/classes/sun/misc/Version.java.template Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-import java.io.PrintStream;
-
-public class Version {
-
-
- private static final String launcher_name =
- "@@LAUNCHER_NAME@@";
-
- private static final String java_version =
- "@@VERSION_SHORT@@";
-
- private static final String java_runtime_name =
- "@@RUNTIME_NAME@@";
-
- private static final String java_runtime_version =
- "@@VERSION_STRING@@";
-
- static {
- init();
- }
-
- public static void init() {
- System.setProperty("java.version", java_version);
- System.setProperty("java.runtime.version", java_runtime_version);
- System.setProperty("java.runtime.name", java_runtime_name);
- }
-
- private static boolean versionsInitialized = false;
- private static int jvm_major_version = 0;
- private static int jvm_minor_version = 0;
- private static int jvm_security_version = 0;
- private static int jvm_patch_version = 0;
- private static int jvm_build_number = 0;
- private static int jdk_major_version = 0;
- private static int jdk_minor_version = 0;
- private static int jdk_security_version = 0;
- private static int jdk_patch_version = 0;
- private static int jdk_build_number = 0;
-
- /**
- * In case you were wondering this method is called by java -version.
- * Sad that it prints to stderr; would be nicer if default printed on
- * stdout.
- */
- public static void print() {
- print(System.err);
- }
-
- /**
- * This is the same as print except that it adds an extra line-feed
- * at the end, typically used by the -showversion in the launcher
- */
- public static void println() {
- print(System.err);
- System.err.println();
- }
-
- /**
- * Give a stream, it will print version info on it.
- */
- public static void print(PrintStream ps) {
- boolean isHeadless = false;
-
- /* Report that we're running headless if the property is true */
- String headless = System.getProperty("java.awt.headless");
- if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
- isHeadless = true;
- }
-
- /* First line: platform version. */
- ps.println(launcher_name + " version \"" + java_version + "\"");
-
- /* Second line: runtime version (ie, libraries). */
-
- String jdk_debug_level = System.getProperty("jdk.debug", "release");
- /* Debug level is not printed for "release" builds */
- if ("release".equals(jdk_debug_level)) {
- jdk_debug_level = "";
- } else {
- jdk_debug_level = jdk_debug_level + " ";
- }
-
- ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
-
- if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
- // embedded builds report headless state
- ps.print(", headless");
- }
- ps.println(')');
-
- /* Third line: JVM information. */
- String java_vm_name = System.getProperty("java.vm.name");
- String java_vm_version = System.getProperty("java.vm.version");
- String java_vm_info = System.getProperty("java.vm.info");
- ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " +
- java_vm_info + ")");
- }
-
-
- /**
- * Returns the major version of the running JVM.
- * @return the major version of the running JVM
- * @since 1.6
- */
- public static synchronized int jvmMajorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_major_version;
- }
-
- /**
- * Returns the minor version of the running JVM.
- * @return the minor version of the running JVM
- * @since 1.6
- */
- public static synchronized int jvmMinorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_minor_version;
- }
-
-
- /**
- * Returns the security version of the running JVM.
- * @return the security version of the running JVM
- * @since 9
- */
- public static synchronized int jvmSecurityVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_security_version;
- }
-
- /**
- * Returns the patch release version of the running JVM.
- * @return the patch release version of the running JVM
- * @since 9
- */
- public static synchronized int jvmPatchVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_patch_version;
- }
-
- /**
- * Returns the build number of the running JVM.
- * @return the build number of the running JVM
- * @since 1.6
- */
- public static synchronized int jvmBuildNumber() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jvm_build_number;
- }
-
- /**
- * Returns the major version of the running JDK.
- * @return the major version of the running JDK
- * @since 1.6
- */
- public static synchronized int jdkMajorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_major_version;
- }
-
- /**
- * Returns the minor version of the running JDK.
- * @return the minor version of the running JDK
- * @since 1.6
- */
- public static synchronized int jdkMinorVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_minor_version;
- }
-
- /**
- * Returns the security version of the running JDK.
- * @return the security version of the running JDK
- * @since 9
- */
- public static synchronized int jdkSecurityVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_security_version;
- }
-
- /**
- * Returns the patch release version of the running JDK.
- * @return the patch release version of the running JDK
- * @since 9
- */
- public static synchronized int jdkPatchVersion() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_patch_version;
- }
-
- /**
- * Returns the build number of the running JDK.
- * @return the build number of the running JDK
- * @since 1.6
- */
- public static synchronized int jdkBuildNumber() {
- if (!versionsInitialized) {
- initVersions();
- }
- return jdk_build_number;
- }
-
- private static synchronized void initVersions() {
- if (versionsInitialized) {
- return;
- }
- if (!getJvmVersionInfo()) {
- throw new InternalError("Unable to obtain JVM version info");
- }
- getJdkVersionInfo();
- versionsInitialized = true;
- }
-
- // Gets the JVM version info if available and sets the jvm_*_version fields
- // and its capabilities.
- private static native boolean getJvmVersionInfo();
- private static native void getJdkVersionInfo();
-}
-
-// Help Emacs a little because this file doesn't end in .java.
-//
-// Local Variables: ***
-// mode: java ***
-// End: ***
--- a/jdk/src/java.base/share/conf/security/java.security Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/conf/security/java.security Sat Mar 05 20:46:44 2016 -0800
@@ -578,7 +578,7 @@
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024
# Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
# processing in JSSE implementation.
--- a/jdk/src/java.base/share/native/libjava/Version.c Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, 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.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jdk_util.h"
-
-#include "sun_misc_Version.h"
-
-static void setStaticIntField(JNIEnv* env, jclass cls, const char* name, jint value)
-{
- jfieldID fid;
- fid = (*env)->GetStaticFieldID(env, cls, name, "I");
- if (fid != 0) {
- (*env)->SetStaticIntField(env, cls, fid, value);
- }
-}
-
-typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t);
-
-JNIEXPORT jboolean JNICALL
-Java_sun_misc_Version_getJvmVersionInfo(JNIEnv *env, jclass cls)
-{
- jvm_version_info info;
- GetJvmVersionInfo_fp func_p;
-
- if (!JDK_InitJvmHandle()) {
- JNU_ThrowInternalError(env, "Handle for JVM not found for symbol lookup");
- return JNI_FALSE;
- }
- func_p = (GetJvmVersionInfo_fp) JDK_FindJvmEntry("JVM_GetVersionInfo");
- if (func_p == NULL) {
- return JNI_FALSE;
- }
-
- (*func_p)(env, &info, sizeof(info));
- setStaticIntField(env, cls, "jvm_major_version", JVM_VERSION_MAJOR(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_minor_version", JVM_VERSION_MINOR(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_security_version", JVM_VERSION_SECURITY(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_build_number", JVM_VERSION_BUILD(info.jvm_version));
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
- setStaticIntField(env, cls, "jvm_patch_version", info.patch_version);
- JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
-
- return JNI_TRUE;
-}
-
-JNIEXPORT void JNICALL
-Java_sun_misc_Version_getJdkVersionInfo(JNIEnv *env, jclass cls)
-{
- jdk_version_info info;
-
- JDK_GetVersionInfo0(&info, sizeof(info));
- setStaticIntField(env, cls, "jdk_major_version", JDK_VERSION_MAJOR(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_minor_version", JDK_VERSION_MINOR(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_security_version", JDK_VERSION_SECURITY(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_build_number", JDK_VERSION_BUILD(info.jdk_version));
- JNU_CHECK_EXCEPTION(env);
- setStaticIntField(env, cls, "jdk_patch_version", info.patch_version);
- JNU_CHECK_EXCEPTION(env);
-}
--- a/jdk/src/java.base/share/native/libjli/java.c Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.base/share/native/libjli/java.c Sat Mar 05 20:46:44 2016 -0800
@@ -1470,7 +1470,7 @@
jclass ver;
jmethodID print;
- NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version"));
+ NULL_CHECK(ver = FindBootStrapClass(env, "java/lang/VersionProps"));
NULL_CHECK(print = (*env)->GetStaticMethodID(env,
ver,
(extraLF == JNI_TRUE) ? "println" : "print",
--- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java Sat Mar 05 20:46:44 2016 -0800
@@ -839,6 +839,7 @@
* @param level One of the message level identifiers, e.g., SEVERE
* @param msgSupplier A function, which when called, produces the
* desired log message
+ * @since 1.8
*/
public void log(Level level, Supplier<String> msgSupplier) {
if (!isLoggable(level)) {
--- a/jdk/test/TEST.groups Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/TEST.groups Sat Mar 05 20:46:44 2016 -0800
@@ -28,7 +28,6 @@
tier1 = \
:jdk_lang \
-java/lang/ProcessHandle/TreeTest.java \
- -java/util/zip/TestLocalTime.java \
:jdk_util \
-java/util/WeakHashMap/GCDuringIteration.java \
-java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
@@ -40,7 +39,6 @@
tier2 = \
java/lang/ProcessHandle/TreeTest.java \
- java/util/zip/TestLocalTime.java \
java/util/WeakHashMap/GCDuringIteration.java \
java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
--- a/jdk/test/java/lang/ProcessHandle/Basic.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/Basic.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,8 @@
/*
* @test
* @library /test/lib/share/classes
- * @run testng InfoTest
+ * @modules jdk.management
+ * @run testng Basic
* @summary Basic tests for ProcessHandler
* @author Roger Riggs
*/
--- a/jdk/test/java/lang/ProcessHandle/InfoTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -49,6 +49,7 @@
* @test
* @bug 8077350 8081566 8081567 8098852 8136597
* @library /test/lib/share/classes
+ * @modules jdk.management
* @build jdk.test.lib.Platform jdk.test.lib.Utils
* @run testng InfoTest
* @summary Functions of ProcessHandle.Info
@@ -114,9 +115,13 @@
long cpuLoopTime = 100; // 100 ms
String[] extraArgs = {"pid", "parent", "stdin"};
JavaChild p1 = JavaChild.spawnJavaChild((Object[])extraArgs);
- Instant afterStart = Instant.now();
+ Instant afterStart = null;
try (BufferedReader lines = p1.outputReader()) {
+ // Read the args line to know the subprocess has started
+ lines.readLine();
+ afterStart = Instant.now();
+
Duration lastCpu = Duration.ofMillis(0L);
for (int j = 0; j < 10; j++) {
@@ -126,8 +131,7 @@
// Read cputime from child
Duration childCpuTime = null;
// Read lines from the child until the result from cputime is returned
- String s;
- while ((s = lines.readLine()) != null) {
+ for (String s; (s = lines.readLine()) != null;) {
String[] split = s.trim().split(" ");
if (split.length == 3 && split[1].equals("cputime")) {
long nanos = Long.valueOf(split[2]);
--- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@
/*
* @test
* @library /test/lib/share/classes
+ * @modules jdk.management
* @build jdk.test.lib.Platform jdk.test.lib.Utils
* @run testng OnExitTest
* @summary Functions of Process.onExit and ProcessHandle.onExit
--- a/jdk/test/java/lang/ProcessHandle/TreeTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@
/*
* @test
* @library /test/lib/share/classes
+ * @modules jdk.management
* @build jdk.test.lib.Utils
* @run testng/othervm TreeTest
* @summary Test counting and JavaChild.spawning and counting of Processes.
--- a/jdk/test/java/lang/StackWalker/StackStreamTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/StackWalker/StackStreamTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
* @test
* @bug 8140450
* @summary Stack Stream Test
+ * @modules java.logging
* @run main/othervm StackStreamTest
*/
public class StackStreamTest {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/Capacity.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2016, 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 8149330
+ * @summary Basic set of tests of capacity management
+ * @run testng Capacity
+ */
+
+import java.lang.reflect.Field;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.SplittableRandom;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.*;
+
+public class Capacity {
+ static final int DEFAULT_CAPACITY = 16;
+
+ private static int newCapacity(int oldCapacity,
+ int desiredCapacity)
+ {
+ return Math.max(oldCapacity * 2 + 2, desiredCapacity);
+ }
+
+ private static int nextNewCapacity(int oldCapacity) {
+ return newCapacity(oldCapacity, oldCapacity + 1);
+ }
+
+ @Test(dataProvider = "singleChar")
+ public void defaultCapacity(Character ch) {
+ StringBuilder sb = new StringBuilder();
+ assertEquals(sb.capacity(), DEFAULT_CAPACITY);
+ for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), DEFAULT_CAPACITY);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(DEFAULT_CAPACITY));
+ }
+
+ @Test(dataProvider = "charCapacity")
+ public void explicitCapacity(Character ch, int initCapacity) {
+ StringBuilder sb = new StringBuilder(initCapacity);
+ assertEquals(sb.capacity(), initCapacity);
+ for (int i = 0; i < initCapacity; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), initCapacity);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(initCapacity));
+ }
+
+ @Test(dataProvider = "singleChar")
+ public void sbFromString(Character ch) {
+ String s = "string " + ch;
+ int expectedCapacity = s.length() + DEFAULT_CAPACITY;
+ StringBuilder sb = new StringBuilder(s);
+ assertEquals(sb.capacity(), expectedCapacity);
+ for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), expectedCapacity);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity));
+ }
+
+ @Test(dataProvider = "singleChar")
+ public void sbFromCharSeq(Character ch) {
+ CharSequence cs = new MyCharSeq("char seq " + ch);
+ int expectedCapacity = cs.length() + DEFAULT_CAPACITY;
+ StringBuilder sb = new StringBuilder(cs);
+ assertEquals(sb.capacity(), expectedCapacity);
+ for (int i = 0; i < DEFAULT_CAPACITY; i++) {
+ sb.append(ch);
+ assertEquals(sb.capacity(), expectedCapacity);
+ }
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity));
+ }
+
+ @Test(dataProvider = "charCapacity")
+ public void ensureCapacity(Character ch, int cap) {
+ StringBuilder sb = new StringBuilder(0);
+ assertEquals(sb.capacity(), 0);
+ sb.ensureCapacity(cap); // only has effect if cap > 0
+ int newCap = (cap == 0) ? 0 : newCapacity(0, cap);
+ assertEquals(sb.capacity(), newCap);
+ sb.ensureCapacity(newCap + 1);
+ assertEquals(sb.capacity(), nextNewCapacity(newCap));
+ sb.append(ch);
+ assertEquals(sb.capacity(), nextNewCapacity(newCap));
+ }
+
+ @Test(dataProvider = "negativeCapacity",
+ expectedExceptions = NegativeArraySizeException.class)
+ public void negativeInitialCapacity(int negCap) {
+ StringBuilder sb = new StringBuilder(negCap);
+ }
+
+ @Test(dataProvider = "negativeCapacity")
+ public void ensureNegativeCapacity(int negCap) {
+ StringBuilder sb = new StringBuilder();
+ sb.ensureCapacity(negCap);
+ assertEquals(sb.capacity(), DEFAULT_CAPACITY);
+ }
+
+ @Test(dataProvider = "charCapacity")
+ public void trimToSize(Character ch, int cap) {
+ StringBuilder sb = new StringBuilder(cap);
+ int halfOfCap = cap / 2;
+ for (int i = 0; i < halfOfCap; i++) {
+ sb.append(ch);
+ }
+ sb.trimToSize();
+ // according to the spec, capacity doesn't have to
+ // become exactly the size
+ assertTrue(sb.capacity() >= halfOfCap);
+ }
+
+ @DataProvider
+ public Object[][] singleChar() {
+ return new Object[][] { {'J'}, {'\u042b'} };
+ }
+
+ @DataProvider
+ public Object[][] charCapacity() {
+ return new Object[][] {
+ {'J', 0},
+ {'J', 1},
+ {'J', 15},
+ {'J', DEFAULT_CAPACITY},
+ {'J', 1024},
+ {'\u042b', 0},
+ {'\u042b', 1},
+ {'\u042b', 15},
+ {'\u042b', DEFAULT_CAPACITY},
+ {'\u042b', 1024},
+ };
+ }
+
+ @DataProvider
+ public Object[][] negativeCapacity() {
+ return new Object[][] { {-1}, {Integer.MIN_VALUE} };
+ }
+
+ private static class MyCharSeq implements CharSequence {
+ private CharSequence s;
+ public MyCharSeq(CharSequence s) { this.s = s; }
+ public char charAt(int i) { return s.charAt(i); }
+ public int length() { return s.length(); }
+ public CharSequence subSequence(int st, int e) {
+ return s.subSequence(st, e);
+ }
+ public String toString() { return s.toString(); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/HugeCapacity.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, 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 8149330
+ * @summary Capacity should not get close to Integer.MAX_VALUE unless
+ * necessary
+ * @run main/othervm -Xmx5G HugeCapacity
+ * @ignore This test has huge memory requirements
+ */
+
+public class HugeCapacity {
+ private static int failures = 0;
+
+ public static void main(String[] args) {
+ testLatin1();
+ testUtf16();
+ if (failures > 0) {
+ throw new RuntimeException(failures + " tests failed");
+ }
+ }
+
+ private static void testLatin1() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ sb.ensureCapacity(Integer.MAX_VALUE / 2);
+ sb.ensureCapacity(Integer.MAX_VALUE / 2 + 1);
+ } catch (OutOfMemoryError oom) {
+ oom.printStackTrace();
+ failures++;
+ }
+ }
+
+ private static void testUtf16() {
+ try {
+ StringBuilder sb = new StringBuilder();
+ sb.append('\u042b');
+ sb.ensureCapacity(Integer.MAX_VALUE / 4);
+ sb.ensureCapacity(Integer.MAX_VALUE / 4 + 1);
+ } catch (OutOfMemoryError oom) {
+ oom.printStackTrace();
+ failures++;
+ }
+ }
+}
--- a/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
* @bug 8140364
* @summary Tests System.Logger.Level names and severity.
* @author danielfuchs
+ * @modules java.logging
*/
public class LoggerLevelTest {
public static void main(String[] args) {
--- a/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -56,7 +56,7 @@
* @summary Tests default loggers returned by System.getLogger, and in
* particular the implementation of the the System.Logger method
* performed by the default binding.
- *
+ * @modules java.logging
* @build DefaultLoggerTest AccessSystemLogger
* @run driver AccessSystemLogger
* @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest NOSECURITY
--- a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -52,6 +52,7 @@
* @bug 8140364
* @summary Tests the default implementation of System.Logger, when
* JUL is the default backend.
+ * @modules java.logging
* @build AccessSystemLogger DefaultLoggerFinderTest
* @run driver AccessSystemLogger
* @run main/othervm -Xbootclasspath/a:boot DefaultLoggerFinderTest NOSECURITY
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -52,6 +52,7 @@
Tests the behavior of bootstrap loggers (and SimpleConsoleLoggers
* too).
* @modules java.base/jdk.internal.logger
+ * java.logging
* @build BootstrapLoggerUtils LogStream
* @run main/othervm BootstrapLoggerTest NO_SECURITY
* @run main/othervm BootstrapLoggerTest SECURE
--- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -58,7 +58,9 @@
* @summary JDK implementation specific unit test for JDK internal artifacts.
* Tests all bridge methods with the a custom backend whose
* loggers implement PlatformLogger.Bridge.
- * @modules java.base/sun.util.logging java.base/jdk.internal.logger
+ * @modules java.base/sun.util.logging
+ * java.base/jdk.internal.logger
+ * java.logging
* @build CustomSystemClassLoader LoggerBridgeTest
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOSECURITY
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOPERMISSIONS
--- a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@
* Tests all bridge methods from PlatformLogger with the a custom
* backend whose loggers implement PlatformLogger.Bridge.
* @modules java.base/sun.util.logging
+ * java.logging
* @build CustomSystemClassLoader PlatformLoggerBridgeTest
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOSECURITY
* @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOPERMISSIONS
--- a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
* Tests the consistency of the LoggerFinder and JDK extensions.
* @modules java.base/sun.util.logging
* java.base/jdk.internal.logger
+ * java.logging
* @run main LoggerFinderAPITest
*/
--- a/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
* @bug 8011194
* @summary Test value of file.encoding for corresponding value of LANG, etc
* @library ../../../../tools/launcher/ ../
+ * @modules jdk.compiler
* @build TestHelper TestFileEncoding ExpectedEncoding
* @run main TestFileEncoding UTF-8
* @run main/othervm -Dfile.encoding=MyEncoding -DuserEncoding=MyEncoding TestFileEncoding MyEncoding
--- a/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -27,9 +27,8 @@
* @summary Tests and benchmarks the JVMTI RedefineClasses when a
* single class (and its parent) contains many methods.
*
- * @modules java.compiler
+ * @modules jdk.compiler
* java.instrument
- * jdk.compiler
* @run build ManyMethodsBenchmarkApp ManyMethodsBenchmarkAgent
* @run shell MakeJAR3.sh ManyMethodsBenchmarkAgent 'Can-Retransform-Classes: true'
* @run main/othervm -javaagent:ManyMethodsBenchmarkAgent.jar ManyMethodsBenchmarkApp
--- a/jdk/test/java/lang/instrument/RetransformAgent.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/instrument/RetransformAgent.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
* @author Robert Field, Sun Microsystems
*
* @modules java.base/jdk.internal.org.objectweb.asm
+ * java.instrument
* @run shell/timeout=240 MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true'
* @run main/othervm -javaagent:RetransformAgent.jar RetransformApp
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/FindAccessTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, 2016, 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
+ * @bug 8139885
+ * @run testng/othervm -ea -esa test.java.lang.invoke.FindAccessTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for Lookup.findClass/accessClass extensions added in JEP 274.
+ */
+public class FindAccessTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testFindSpecial() throws Throwable {
+ FindSpecial.C c = new FindSpecial.C();
+ assertEquals("I1.m", c.m());
+ MethodType t = MethodType.methodType(String.class);
+ MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class);
+ assertEquals("I1.m", (String) ci1m.invoke(c));
+ }
+
+ @Test
+ public static void testFindSpecialAbstract() throws Throwable {
+ FindSpecial.C c = new FindSpecial.C();
+ assertEquals("q", c.q());
+ MethodType t = MethodType.methodType(String.class);
+ boolean caught = false;
+ try {
+ MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class);
+ } catch (Throwable thrown) {
+ if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) {
+ throw new AssertionError(thrown.getMessage(), thrown);
+ }
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test(expectedExceptions = {ClassNotFoundException.class})
+ public static void testFindClassCNFE() throws ClassNotFoundException, IllegalAccessException {
+ LOOKUP.findClass("does.not.Exist");
+ }
+
+ static class FindSpecial {
+
+ interface I1 {
+ default String m() {
+ return "I1.m";
+ }
+ }
+
+ interface I2 {
+ default String m() {
+ return "I2.m";
+ }
+ }
+
+ interface I3 {
+ String q();
+ }
+
+ static class C implements I1, I2, I3 {
+ public String m() {
+ return I1.super.m();
+ }
+ public String q() {
+ return "q";
+ }
+ }
+
+ static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.FindAccessTest$FindSpecial$I3.q()String/invokeSpecial";
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/FoldTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 2016, 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
+ * @bug 8139885
+ * @run testng/othervm -ea -esa test.java.lang.invoke.FoldTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the new fold method handle combinator added in JEP 274.
+ */
+public class FoldTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testFold0a() throws Throwable {
+ // equivalence to foldArguments(MethodHandle,MethodHandle)
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder);
+ assertEquals(Fold.MT_folded1, fold.type());
+ assertEquals(720, (int) fold.invoke(3, 4, 5));
+ }
+
+ @Test
+ public static void testFold1a() throws Throwable {
+ // test foldArguments for folding position 1
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1);
+ assertEquals(Fold.MT_folded1, fold.type());
+ assertEquals(540, (int) fold.invoke(3, 4, 5));
+ }
+
+ @Test
+ public static void testFold0b() throws Throwable {
+ // test foldArguments equivalence with multiple types
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb);
+ assertEquals(Fold.MT_folded2, fold.type());
+ assertEquals(23, (int) fold.invoke("true", true, 23));
+ }
+
+ @Test
+ public static void testFold1b() throws Throwable {
+ // test folgArguments for folding position 1, with multiple types
+ MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2);
+ assertEquals(Fold.MT_folded3, fold.type());
+ assertEquals(1, (int) fold.invoke(true, true, 1));
+ assertEquals(-1, (int) fold.invoke(true, false, -1));
+ }
+
+ @Test
+ public static void testFoldArgumentsExample() throws Throwable {
+ // test the JavaDoc foldArguments-with-pos example
+ StringWriter swr = new StringWriter();
+ MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr);
+ MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class));
+ assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+ MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace);
+ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+ assertEquals("jum", swr.toString());
+ }
+
+ static class Fold {
+
+ static int adder(int a, int b, int c) {
+ return a + b + c;
+ }
+
+ static int adder1(int a, int b) {
+ return a + b;
+ }
+
+ static int multer(int x, int q, int r, int s) {
+ return x * q * r * s;
+ }
+
+ static int str(boolean b1, String s, boolean b2, int x) {
+ return b1 && s.equals(String.valueOf(b2)) ? x : -x;
+ }
+
+ static boolean comb(String s, boolean b2) {
+ return !s.equals(b2);
+ }
+
+ static String comb2(boolean b2, int x) {
+ int ib = b2 ? 1 : 0;
+ return ib == x ? "true" : "false";
+ }
+
+ static final Class<Fold> FOLD = Fold.class;
+
+ static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_adder1 = methodType(int.class, int.class, int.class);
+ static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class);
+ static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class);
+ static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class);
+ static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class);
+
+ static final MethodHandle MH_adder;
+ static final MethodHandle MH_adder1;
+ static final MethodHandle MH_multer;
+ static final MethodHandle MH_str;
+ static final MethodHandle MH_comb;
+ static final MethodHandle MH_comb2;
+
+ static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class);
+ static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class);
+
+ static {
+ try {
+ MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder);
+ MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1);
+ MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer);
+ MH_str = LOOKUP.findStatic(FOLD, "str", MT_str);
+ MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb);
+ MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+ }
+
+}
--- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -690,7 +690,7 @@
{{
{} /// JAVADOC
// implement the zip function for lists as a loop handle
-MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred);
+MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep);
List<String> a = Arrays.asList("a", "b", "c", "d");
List<String> b = Arrays.asList("e", "f", "g", "h");
List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,803 @@
+/*
+ * Copyright (c) 2015, 2016, 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
+ * @bug 8139885
+ * @bug 8150635
+ * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.util.*;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the loop combinators introduced in JEP 274.
+ */
+public class LoopCombinatorTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testLoopFac() throws Throwable {
+ MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+ assertEquals(Fac.MT_fac, loop.type());
+ assertEquals(120, loop.invoke(5));
+ }
+
+ @Test
+ public static void testLoopFacNullInit() throws Throwable {
+ // null initializer for counter, should initialize to 0
+ MethodHandle[] counterClause = new MethodHandle[]{null, Fac.MH_inc};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+ assertEquals(Fac.MT_fac, loop.type());
+ assertEquals(120, loop.invoke(5));
+ }
+
+ @Test
+ public static void testLoopNullInit() throws Throwable {
+ // null initializer for counter, should initialize to 0, one-clause loop
+ MethodHandle[] counterClause = new MethodHandle[]{null, Loop.MH_inc, Loop.MH_pred, Loop.MH_fin};
+ MethodHandle loop = MethodHandles.loop(counterClause);
+ assertEquals(Loop.MT_loop, loop.type());
+ assertEquals(10, loop.invoke(10));
+ }
+
+ @Test
+ public static void testLoopVoid1() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{Empty.MH_f, Empty.MH_f, Empty.MH_pred, null});
+ assertEquals(MethodType.methodType(void.class), loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testLoopVoid2() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state,
+ // initialized implicitly from the step type
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, null});
+ assertEquals(MethodType.methodType(void.class), loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testLoopVoid3() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state,
+ // and that has a void finalizer
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_f});
+ assertEquals(MethodType.methodType(void.class), loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testLoopFacWithVoidState() throws Throwable {
+ // like testLoopFac, but with additional void state that outputs a dot
+ MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+ MethodHandle[] dotClause = new MethodHandle[]{null, Fac.MH_dot};
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause, dotClause);
+ assertEquals(Fac.MT_fac, loop.type());
+ assertEquals(120, loop.invoke(5));
+ }
+
+ @Test
+ public static void testLoopVoidInt() throws Throwable {
+ // construct a post-checked loop that only does one iteration and has a void body and void local state,
+ // and that returns a constant
+ MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_c});
+ assertEquals(MethodType.methodType(int.class), loop.type());
+ assertEquals(23, loop.invoke());
+ }
+
+ @Test
+ public static void testLoopWithVirtuals() throws Throwable {
+ // construct a loop (to calculate factorial) that uses a mix of static and virtual methods
+ MethodHandle[] counterClause = new MethodHandle[]{null, LoopWithVirtuals.permute(LoopWithVirtuals.MH_inc)};
+ MethodHandle[] accumulatorClause = new MethodHandle[]{
+ // init function must indicate the loop arguments (there is no other means to determine them)
+ MethodHandles.dropArguments(LoopWithVirtuals.MH_one, 0, LoopWithVirtuals.class),
+ LoopWithVirtuals.permute(LoopWithVirtuals.MH_mult),
+ LoopWithVirtuals.permute(LoopWithVirtuals.MH_pred),
+ LoopWithVirtuals.permute(LoopWithVirtuals.MH_fin)
+ };
+ MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+ assertEquals(LoopWithVirtuals.MT_loop, loop.type());
+ assertEquals(120, loop.invoke(new LoopWithVirtuals(), 5));
+ }
+
+ @DataProvider
+ static Object[][] negativeTestData() {
+ MethodHandle i0 = MethodHandles.constant(int.class, 0);
+ MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class);
+ MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class);
+ MethodHandle i3 = MethodHandles.dropArguments(i0, 0, int.class, int.class, int.class);
+ List<MethodHandle> inits = Arrays.asList(ii, id, i3);
+ List<Class<?>> ints = Arrays.asList(int.class, int.class, int.class);
+ List<MethodHandle> finis = Arrays.asList(Fac.MH_fin, Fac.MH_inc, Counted.MH_step);
+ List<MethodHandle> preds1 = Arrays.asList(null, null, null);
+ List<MethodHandle> preds2 = Arrays.asList(null, Fac.MH_fin, null);
+ MethodHandle eek = MethodHandles.dropArguments(i0, 0, int.class, int.class, double.class);
+ List<MethodHandle> nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot);
+ List<MethodHandle> nepreds = Arrays.asList(null, Fac.MH_pred, null);
+ List<MethodHandle> nefinis = Arrays.asList(null, Fac.MH_fin, null);
+ List<MethodHandle> lvsteps = Arrays.asList(LoopWithVirtuals.MH_inc, LoopWithVirtuals.MH_mult);
+ List<MethodHandle> lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred);
+ List<MethodHandle> lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin);
+ return new Object[][] {
+ {null, "null or no clauses passed"},
+ {new MethodHandle[][]{}, "null or no clauses passed"},
+ {new MethodHandle[][]{{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
+ "All loop clauses must be represented as MethodHandle arrays with at most 4 elements."},
+ {new MethodHandle[][]{{null, Fac.MH_inc}, null}, "null clauses are not allowed"},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_dot}},
+ "clause 0: init and step return types must match: int != void"},
+ {new MethodHandle[][]{{ii}, {id}, {i3}},
+ "found non-effectively identical init parameter type lists: " + inits +
+ " (common suffix: " + ints + ")"},
+ {new MethodHandle[][]{{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
+ {null, Counted.MH_start, null, Counted.MH_step}},
+ "found non-identical finalizer return types: " + finis + " (return type: int)"},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin},
+ {null, Fac.MH_dot}}, "no predicate found: " + preds1},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin},
+ {null, Fac.MH_dot}}, "predicates must have boolean return type: " + preds2},
+ {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin},
+ {null, Fac.MH_dot}},
+ "found non-effectively identical parameter type lists:\nstep: " + nesteps +
+ "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")"},
+ {new MethodHandle[][]{{null, LoopWithVirtuals.MH_inc},
+ {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}},
+ "found non-effectively identical parameter type lists:\nstep: " + lvsteps +
+ "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints + ")"}
+ };
+ }
+
+ static final MethodHandle MH_loop;
+
+ static {
+ try {
+ MH_loop = LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class));
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ @Test(dataProvider = "negativeTestData")
+ public static void testLoopNegative(MethodHandle[][] clauses, String expectedMessage) throws Throwable {
+ boolean caught = false;
+ try {
+ MH_loop.invokeWithArguments(clauses);
+ } catch (IllegalArgumentException iae) {
+ assertEquals(expectedMessage, iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test
+ public static void testWhileLoop() throws Throwable {
+ // int i = 0; while (i < limit) { ++i; } return i; => limit
+ MethodHandle loop = MethodHandles.whileLoop(While.MH_zero, While.MH_pred, While.MH_step);
+ assertEquals(While.MT_while, loop.type());
+ assertEquals(23, loop.invoke(23));
+ }
+
+ @Test
+ public static void testWhileLoopNoIteration() throws Throwable {
+ // a while loop that never executes its body because the predicate evaluates to false immediately
+ MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString);
+ assertEquals(While.MT_string, loop.type());
+ assertEquals("a", loop.invoke());
+ }
+
+ @Test
+ public static void testDoWhileLoop() throws Throwable {
+ // int i = 0; do { ++i; } while (i < limit); return i; => limit
+ MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zero, While.MH_step, While.MH_pred);
+ assertEquals(While.MT_while, loop.type());
+ assertEquals(23, loop.invoke(23));
+ }
+
+ @Test
+ public static void testDoWhileNullInit() throws Throwable {
+ While w = new While();
+ int v = 5;
+ MethodHandle loop = MethodHandles.doWhileLoop(null, While.MH_voidBody.bindTo(w), While.MH_voidPred.bindTo(w));
+ assertEquals(While.MT_void, loop.type());
+ loop.invoke(v);
+ assertEquals(v, w.i);
+ }
+
+ @Test
+ public static void testWhileZip() throws Throwable {
+ MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred);
+ assertEquals(While.MT_zip, loop.type());
+ List<String> a = Arrays.asList("a", "b", "c", "d");
+ List<String> b = Arrays.asList("e", "f", "g", "h");
+ List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
+ assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
+ }
+
+ @Test
+ public static void testWhileNullInit() throws Throwable {
+ While w = new While();
+ int v = 5;
+ MethodHandle loop = MethodHandles.whileLoop(null, While.MH_voidPred.bindTo(w), While.MH_voidBody.bindTo(w));
+ assertEquals(While.MT_void, loop.type());
+ loop.invoke(v);
+ assertEquals(v, w.i);
+ }
+
+ @Test
+ public static void testCountedLoop() throws Throwable {
+ // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
+ MethodHandle fit13 = MethodHandles.constant(int.class, 13);
+ MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step);
+ assertEquals(Counted.MT_counted, loop.type());
+ assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+ }
+
+ @Test
+ public static void testCountedArrayLoop() throws Throwable {
+ // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
+ MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
+ MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray);
+ assertEquals(Counted.MT_arrayCounted, loop.type());
+ int[] a = new int[]{0};
+ loop.invoke(a);
+ assertEquals(13, a[0]);
+ }
+
+ @Test
+ public static void testCountedPrintingLoop() throws Throwable {
+ MethodHandle fit5 = MethodHandles.constant(int.class, 5);
+ MethodHandle loop = MethodHandles.countedLoop(fit5, null, Counted.MH_printHello);
+ assertEquals(Counted.MT_countedPrinting, loop.type());
+ loop.invoke();
+ }
+
+ @Test
+ public static void testCountedRangeLoop() throws Throwable {
+ // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme
+ MethodHandle fitm5 = MethodHandles.dropArguments(Counted.MH_m5, 0, String.class);
+ MethodHandle fit8 = MethodHandles.dropArguments(Counted.MH_8, 0, String.class);
+ MethodHandle loop = MethodHandles.countedLoop(fitm5, fit8, Counted.MH_start, Counted.MH_step);
+ assertEquals(Counted.MT_counted, loop.type());
+ assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+ }
+
+ @Test
+ public static void testIterateSum() throws Throwable {
+ // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21
+ MethodHandle loop = MethodHandles.iteratedLoop(Iterate.MH_sumIterator, Iterate.MH_sumInit, Iterate.MH_sumStep);
+ assertEquals(Iterate.MT_sum, loop.type());
+ assertEquals(21, loop.invoke(new Integer[]{1, 2, 3, 4, 5, 6}));
+ }
+
+ @Test
+ public static void testIterateReverse() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_reverseInit, Iterate.MH_reverseStep);
+ assertEquals(Iterate.MT_reverse, loop.type());
+ List<String> list = Arrays.asList("a", "b", "c", "d", "e");
+ List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
+ assertEquals(reversedList, (List<String>) loop.invoke(list));
+ }
+
+ @Test
+ public static void testIterateLength() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_lengthInit, Iterate.MH_lengthStep);
+ assertEquals(Iterate.MT_length, loop.type());
+ List<Double> list = Arrays.asList(23.0, 148.0, 42.0);
+ assertEquals(list.size(), (int) loop.invoke(list));
+ }
+
+ @Test
+ public static void testIterateMap() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_mapInit, Iterate.MH_mapStep);
+ assertEquals(Iterate.MT_map, loop.type());
+ List<String> list = Arrays.asList("Hello", "world", "!");
+ List<String> upList = Arrays.asList("HELLO", "WORLD", "!");
+ assertEquals(upList, (List<String>) loop.invoke(list));
+ }
+
+ @Test
+ public static void testIteratePrint() throws Throwable {
+ MethodHandle loop = MethodHandles.iteratedLoop(null, null, Iterate.MH_printStep);
+ assertEquals(Iterate.MT_print, loop.type());
+ loop.invoke(Arrays.asList("hello", "world"));
+ }
+
+ @Test
+ public static void testIterateNullBody() {
+ boolean caught = false;
+ try {
+ MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null);
+ } catch (IllegalArgumentException iae) {
+ assertEquals("iterated loop body must not be null", iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ static class Empty {
+
+ static void f() { }
+
+ static boolean pred() {
+ return false;
+ }
+
+ static int c() {
+ return 23;
+ }
+
+ static final Class<Empty> EMPTY = Empty.class;
+
+ static final MethodType MT_f = methodType(void.class);
+ static final MethodType MT_pred = methodType(boolean.class);
+ static final MethodType MT_c = methodType(int.class);
+
+ static final MethodHandle MH_f;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_c;
+
+ static {
+ try {
+ MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f);
+ MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred);
+ MH_c = LOOKUP.findStatic(EMPTY, "c", MT_c);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+ }
+
+ static class Fac {
+
+ static int zero(int k) {
+ return 0;
+ }
+
+ static int one(int k) {
+ return 1;
+ }
+
+ static boolean pred(int i, int acc, int k) {
+ return i < k;
+ }
+
+ static int inc(int i, int acc, int k) {
+ return i + 1;
+ }
+
+ static int mult(int i, int acc, int k) {
+ return i * acc;
+ }
+
+ static void dot(int i, int acc, int k) {
+ System.out.print('.');
+ }
+
+ static int fin(int i, int acc, int k) {
+ return acc;
+ }
+
+ static final Class<Fac> FAC = Fac.class;
+
+ static final MethodType MT_init = methodType(int.class, int.class);
+ static final MethodType MT_fn = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_dot = methodType(void.class, int.class, int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
+
+ static final MethodHandle MH_zero;
+ static final MethodHandle MH_one;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_inc;
+ static final MethodHandle MH_mult;
+ static final MethodHandle MH_dot;
+ static final MethodHandle MH_fin;
+
+ static final MethodType MT_fac = methodType(int.class, int.class);
+
+ static {
+ try {
+ MH_zero = LOOKUP.findStatic(FAC, "zero", MT_init);
+ MH_one = LOOKUP.findStatic(FAC, "one", MT_init);
+ MH_pred = LOOKUP.findStatic(FAC, "pred", MT_pred);
+ MH_inc = LOOKUP.findStatic(FAC, "inc", MT_fn);
+ MH_mult = LOOKUP.findStatic(FAC, "mult", MT_fn);
+ MH_dot = LOOKUP.findStatic(FAC, "dot", MT_dot);
+ MH_fin = LOOKUP.findStatic(FAC, "fin", MT_fn);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class Loop {
+
+ static int inc(int i, int k) {
+ return i + 1;
+ }
+
+ static boolean pred(int i, int k) {
+ return i < k;
+ }
+
+ static int fin(int i, int k) {
+ return k;
+ }
+
+ static final Class<Loop> LOOP = Loop.class;
+
+ static final MethodType MT_inc = methodType(int.class, int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
+ static final MethodType MT_fin = methodType(int.class, int.class, int.class);
+
+ static final MethodHandle MH_inc;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_fin;
+
+ static final MethodType MT_loop = methodType(int.class, int.class);
+
+ static {
+ try {
+ MH_inc = LOOKUP.findStatic(LOOP, "inc", MT_inc);
+ MH_pred = LOOKUP.findStatic(LOOP, "pred", MT_pred);
+ MH_fin = LOOKUP.findStatic(LOOP, "fin", MT_fin);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class LoopWithVirtuals {
+
+ static int one(int k) {
+ return 1;
+ }
+
+ int inc(int i, int acc, int k) {
+ return i + 1;
+ }
+
+ int mult(int i, int acc, int k) {
+ return i * acc;
+ }
+
+ boolean pred(int i, int acc, int k) {
+ return i < k;
+ }
+
+ int fin(int i, int acc, int k) {
+ return acc;
+ }
+
+ static final Class<LoopWithVirtuals> LOOP_WITH_VIRTUALS = LoopWithVirtuals.class;
+
+ static final MethodType MT_one = methodType(int.class, int.class);
+ static final MethodType MT_inc = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_mult = methodType(int.class, int.class, int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
+ static final MethodType MT_fin = methodType(int.class, int.class, int.class, int.class);
+
+ static final MethodHandle MH_one;
+ static final MethodHandle MH_inc;
+ static final MethodHandle MH_mult;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_fin;
+
+ static final MethodType MT_loop = methodType(int.class, LOOP_WITH_VIRTUALS, int.class);
+
+ static {
+ try {
+ MH_one = LOOKUP.findStatic(LOOP_WITH_VIRTUALS, "one", MT_one);
+ MH_inc = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "inc", MT_inc);
+ MH_mult = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "mult", MT_mult);
+ MH_pred = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "pred", MT_pred);
+ MH_fin = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "fin", MT_fin);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ static MethodHandle permute(MethodHandle h) {
+ // The handles representing virtual methods need to be rearranged to match the required order of arguments
+ // (loop-local state comes first, then loop arguments). As the receiver comes first in the signature but is
+ // a loop argument, it must be moved to the appropriate position in the signature.
+ return MethodHandles.permuteArguments(h,
+ methodType(h.type().returnType(), int.class, int.class, LOOP_WITH_VIRTUALS, int.class), 2, 0, 1, 3);
+ }
+
+ }
+
+ static class While {
+
+ static int zero(int limit) {
+ return 0;
+ }
+
+ static boolean pred(int i, int limit) {
+ return i < limit;
+ }
+
+ static int step(int i, int limit) {
+ return i + 1;
+ }
+
+ static String initString() {
+ return "a";
+ }
+
+ static boolean predString(String s) {
+ return s.length() != 1;
+ }
+
+ static String stepString(String s) {
+ return s + "a";
+ }
+
+ static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) {
+ return new ArrayList<>();
+ }
+
+ static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) {
+ return a.hasNext() && b.hasNext();
+ }
+
+ static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+ zip.add(a.next());
+ zip.add(b.next());
+ return zip;
+ }
+
+ private int i = 0;
+
+ void voidBody(int k) {
+ ++i;
+ }
+
+ boolean voidPred(int k) {
+ return i < k;
+ }
+
+ static final Class<While> WHILE = While.class;
+
+ static final MethodType MT_zero = methodType(int.class, int.class);
+ static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
+ static final MethodType MT_fn = methodType(int.class, int.class, int.class);
+ static final MethodType MT_initString = methodType(String.class);
+ static final MethodType MT_predString = methodType(boolean.class, String.class);
+ static final MethodType MT_stepString = methodType(String.class, String.class);
+ static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_voidBody = methodType(void.class, int.class);
+ static final MethodType MT_voidPred = methodType(boolean.class, int.class);
+
+ static final MethodHandle MH_zero;
+ static final MethodHandle MH_pred;
+ static final MethodHandle MH_step;
+ static final MethodHandle MH_initString;
+ static final MethodHandle MH_predString;
+ static final MethodHandle MH_stepString;
+ static final MethodHandle MH_zipInitZip;
+ static final MethodHandle MH_zipPred;
+ static final MethodHandle MH_zipStep;
+ static final MethodHandle MH_voidBody;
+ static final MethodHandle MH_voidPred;
+
+ static final MethodType MT_while = methodType(int.class, int.class);
+ static final MethodType MT_string = methodType(String.class);
+ static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class);
+ static final MethodType MT_void = methodType(void.class, int.class);
+
+ static {
+ try {
+ MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero);
+ MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred);
+ MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn);
+ MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString);
+ MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString);
+ MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString);
+ MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
+ MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
+ MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
+ MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody);
+ MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class Counted {
+
+ static String start(String arg) {
+ return arg;
+ }
+
+ static String step(int counter, String v, String arg) {
+ return "na " + v;
+ }
+
+ static void stepUpdateArray(int counter, int[] a) {
+ ++a[0];
+ }
+
+ static void printHello(int counter) {
+ System.out.print("hello");
+ }
+
+ static final Class<Counted> COUNTED = Counted.class;
+
+ static final MethodType MT_start = methodType(String.class, String.class);
+ static final MethodType MT_step = methodType(String.class, int.class, String.class, String.class);
+ static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class);
+ static final MethodType MT_printHello = methodType(void.class, int.class);
+
+ static final MethodHandle MH_13;
+ static final MethodHandle MH_m5;
+ static final MethodHandle MH_8;
+ static final MethodHandle MH_start;
+ static final MethodHandle MH_step;
+ static final MethodHandle MH_stepUpdateArray;
+ static final MethodHandle MH_printHello;
+
+ static final MethodType MT_counted = methodType(String.class, String.class);
+ static final MethodType MT_arrayCounted = methodType(void.class, int[].class);
+ static final MethodType MT_countedPrinting = methodType(void.class);
+
+ static {
+ try {
+ MH_13 = MethodHandles.constant(int.class, 13);
+ MH_m5 = MethodHandles.constant(int.class, -5);
+ MH_8 = MethodHandles.constant(int.class, 8);
+ MH_start = LOOKUP.findStatic(COUNTED, "start", MT_start);
+ MH_step = LOOKUP.findStatic(COUNTED, "step", MT_step);
+ MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray);
+ MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+ static class Iterate {
+
+ static Iterator<Integer> sumIterator(Integer[] a) {
+ return Arrays.asList(a).iterator();
+ }
+
+ static int sumInit(Integer[] a) {
+ return 0;
+ }
+
+ static int sumStep(int s, int e, Integer[] a) {
+ return s + e;
+ }
+
+ static List<String> reverseInit(List<String> l) {
+ return new ArrayList<>();
+ }
+
+ static List<String> reverseStep(String e, List<String> r, List<String> l) {
+ r.add(0, e);
+ return r;
+ }
+
+ static int lengthInit(List<Double> l) {
+ return 0;
+ }
+
+ static int lengthStep(Object o, int len, List<Double> l) {
+ return len + 1;
+ }
+
+ static List<String> mapInit(List<String> l) {
+ return new ArrayList<>();
+ }
+
+ static List<String> mapStep(String e, List<String> r, List<String> l) {
+ r.add(e.toUpperCase());
+ return r;
+ }
+
+ static void printStep(String s, List<String> l) {
+ System.out.print(s);
+ }
+
+ static final Class<Iterate> ITERATE = Iterate.class;
+
+ static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class);
+
+ static final MethodType MT_sumInit = methodType(int.class, Integer[].class);
+ static final MethodType MT_reverseInit = methodType(List.class, List.class);
+ static final MethodType MT_lenghInit = methodType(int.class, List.class);
+ static final MethodType MT_mapInit = methodType(List.class, List.class);
+
+ static final MethodType MT_sumStep = methodType(int.class, int.class, int.class, Integer[].class);
+ static final MethodType MT_reverseStep = methodType(List.class, String.class, List.class, List.class);
+ static final MethodType MT_lengthStep = methodType(int.class, Object.class, int.class, List.class);
+ static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class);
+ static final MethodType MT_printStep = methodType(void.class, String.class, List.class);
+
+ static final MethodHandle MH_sumIterator;
+ static final MethodHandle MH_sumInit;
+ static final MethodHandle MH_sumStep;
+ static final MethodHandle MH_printStep;
+
+ static final MethodHandle MH_reverseInit;
+ static final MethodHandle MH_reverseStep;
+
+ static final MethodHandle MH_lengthInit;
+ static final MethodHandle MH_lengthStep;
+
+ static final MethodHandle MH_mapInit;
+ static final MethodHandle MH_mapStep;
+
+ static final MethodType MT_sum = methodType(int.class, Integer[].class);
+ static final MethodType MT_reverse = methodType(List.class, List.class);
+ static final MethodType MT_length = methodType(int.class, List.class);
+ static final MethodType MT_map = methodType(List.class, List.class);
+ static final MethodType MT_print = methodType(void.class, List.class);
+
+ static {
+ try {
+ MH_sumIterator = LOOKUP.findStatic(ITERATE, "sumIterator", MT_sumIterator);
+ MH_sumInit = LOOKUP.findStatic(ITERATE, "sumInit", MT_sumInit);
+ MH_sumStep = LOOKUP.findStatic(ITERATE, "sumStep", MT_sumStep);
+ MH_reverseInit = LOOKUP.findStatic(ITERATE, "reverseInit", MT_reverseInit);
+ MH_reverseStep = LOOKUP.findStatic(ITERATE, "reverseStep", MT_reverseStep);
+ MH_lengthInit = LOOKUP.findStatic(ITERATE, "lengthInit", MT_lenghInit);
+ MH_lengthStep = LOOKUP.findStatic(ITERATE, "lengthStep", MT_lengthStep);
+ MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit);
+ MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep);
+ MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/SpreadCollectTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015, 2016, 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
+ * @bug 8139885
+ * @bug 8143798
+ * @run testng/othervm -ea -esa test.java.lang.invoke.SpreadCollectTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.*;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the new asSpreader/asCollector API added in JEP 274.
+ */
+public class SpreadCollectTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testAsSpreader() throws Throwable {
+ MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3);
+ assertEquals(SpreadCollect.MT_spreader, spreader.type());
+ assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B"));
+ }
+
+ @Test
+ public static void testAsSpreaderExample() throws Throwable {
+ // test the JavaDoc asSpreader-with-pos example
+ MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
+ MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
+ Object[] ints = new Object[]{3, 9, 7, 7};
+ Comparator<Integer> cmp = (a, b) -> a - b;
+ assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
+ assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
+ assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
+ }
+
+ @DataProvider
+ static Object[][] asSpreaderIllegalPositions() {
+ return new Object[][]{{-7}, {3}, {19}};
+ }
+
+ @Test(dataProvider = "asSpreaderIllegalPositions")
+ public static void testAsSpreaderIllegalPos(int p) throws Throwable {
+ boolean caught = false;
+ try {
+ SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3);
+ } catch (IllegalArgumentException iae) {
+ assertEquals("bad spread position", iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test(expectedExceptions = {WrongMethodTypeException.class})
+ public static void testAsSpreaderIllegalMethodType() {
+ MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class);
+ MethodHandle s = h.asSpreader(String[].class, 1);
+ }
+
+ @Test
+ public static void testAsCollector() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collector1, collector.type());
+ assertEquals("A4B", (String) collector.invoke("A", 4, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collector2, collector.type());
+ assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collector3, collector.type());
+ assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B"));
+ }
+
+ @Test
+ public static void testAsCollectorInvokeWithArguments() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collector1, collector.type());
+ assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collector2, collector.type());
+ assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B"));
+ collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collector3, collector.type());
+ assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B"));
+ }
+
+ @Test
+ public static void testAsCollectorLeading() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
+ assertEquals("7Q", (String) collector.invoke(7, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
+ assertEquals("78Q", (String) collector.invoke(7, 8, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
+ assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q"));
+ }
+
+ @Test
+ public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
+ assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
+ assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
+ assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
+ assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q"));
+ collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
+ assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
+ assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q"));
+ }
+
+ @Test
+ public static void testAsCollectorNone() throws Throwable {
+ MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0);
+ assertEquals(SpreadCollect.MT_collector0, collector.type());
+ assertEquals("AB", (String) collector.invoke("A", "B"));
+ }
+
+ @DataProvider
+ static Object[][] asCollectorIllegalPositions() {
+ return new Object[][]{{-1}, {17}};
+ }
+
+ @Test(dataProvider = "asCollectorIllegalPositions")
+ public static void testAsCollectorIllegalPos(int p) {
+ boolean caught = false;
+ try {
+ SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0);
+ } catch (IllegalArgumentException iae) {
+ assertEquals("bad collect position", iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ @Test
+ public static void testAsCollectorExample() throws Throwable {
+ // test the JavaDoc asCollector-with-pos example
+ StringWriter swr = new StringWriter();
+ MethodHandle swWrite = LOOKUP.
+ findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).
+ bindTo(swr);
+ MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
+ swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
+ assertEquals("BC", swr.toString());
+ swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
+ assertEquals("BCPQRS", swr.toString());
+ swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
+ assertEquals("BCPQRSZ", swr.toString());
+ }
+
+ static class SpreadCollect {
+
+ static String forSpreading(String s1, int i1, int i2, int i3, String s2) {
+ return s1 + i1 + i2 + i3 + s2;
+ }
+
+ static String forCollecting(String s1, int[] is, String s2) {
+ StringBuilder sb = new StringBuilder(s1);
+ for (int i : is) {
+ sb.append(i);
+ }
+ return sb.append(s2).toString();
+ }
+
+ static String forCollectingLeading(int[] is, String s) {
+ return forCollecting("", is, s);
+ }
+
+ static final Class<SpreadCollect> SPREAD_COLLECT = SpreadCollect.class;
+
+ static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
+ static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class);
+ static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class);
+
+ static final MethodHandle MH_forSpreading;
+ static final MethodHandle MH_forCollecting;
+ static final MethodHandle MH_forCollectingLeading;
+
+ static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class);
+ static final MethodType MT_collector0 = methodType(String.class, String.class, String.class);
+ static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class);
+ static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class);
+ static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
+ static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class);
+ static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class);
+ static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class);
+
+ static final String NONE_ERROR = "zero array length in MethodHandle.asCollector";
+
+ static {
+ try {
+ MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading);
+ MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting);
+ MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+}
--- a/jdk/test/java/lang/invoke/T8139885.java Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1097 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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
- * @bug 8139885
- * @bug 8143798
- * @run testng/othervm -ea -esa test.java.lang.invoke.T8139885
- */
-
-package test.java.lang.invoke;
-
-import java.io.StringWriter;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.WrongMethodTypeException;
-import java.util.*;
-
-import static java.lang.invoke.MethodType.methodType;
-
-import static org.testng.AssertJUnit.*;
-
-import org.testng.annotations.*;
-
-/**
- * Example-scale and negative tests for JEP 274 extensions.
- */
-public class T8139885 {
-
- static final Lookup LOOKUP = MethodHandles.lookup();
-
- //
- // Tests.
- //
-
- @Test
- public static void testLoopFac() throws Throwable {
- MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
- MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
- MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
- assertEquals(Fac.MT_fac, loop.type());
- assertEquals(120, loop.invoke(5));
- }
-
- @Test
- public static void testLoopFacNullInit() throws Throwable {
- // null initializer for counter, should initialize to 0
- MethodHandle[] counterClause = new MethodHandle[]{null, Fac.MH_inc};
- MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
- MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
- assertEquals(Fac.MT_fac, loop.type());
- assertEquals(120, loop.invoke(5));
- }
-
- @Test
- public static void testLoopVoid1() throws Throwable {
- // construct a post-checked loop that only does one iteration and has a void body and void local state
- MethodHandle loop = MethodHandles.loop(new MethodHandle[]{Empty.MH_f, Empty.MH_f, Empty.MH_pred, null});
- assertEquals(MethodType.methodType(void.class), loop.type());
- loop.invoke();
- }
-
- @Test
- public static void testLoopVoid2() throws Throwable {
- // construct a post-checked loop that only does one iteration and has a void body and void local state,
- // initialized implicitly from the step type
- MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, null});
- assertEquals(MethodType.methodType(void.class), loop.type());
- loop.invoke();
- }
-
- @Test
- public static void testLoopFacWithVoidState() throws Throwable {
- // like testLoopFac, but with additional void state that outputs a dot
- MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
- MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
- MethodHandle[] dotClause = new MethodHandle[]{null, Fac.MH_dot};
- MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause, dotClause);
- assertEquals(Fac.MT_fac, loop.type());
- assertEquals(120, loop.invoke(5));
- }
-
- @Test
- public static void testLoopNegative() throws Throwable {
- MethodHandle mh_loop =
- LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class));
- MethodHandle i0 = MethodHandles.constant(int.class, 0);
- MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class);
- MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class);
- MethodHandle i3 = MethodHandles.dropArguments(i0, 0, int.class, int.class, int.class);
- List<MethodHandle> inits = Arrays.asList(ii, id, i3);
- List<Class<?>> ints = Arrays.asList(int.class, int.class, int.class);
- List<MethodHandle> finis = Arrays.asList(Fac.MH_fin, Fac.MH_inc, Counted.MH_step);
- List<MethodHandle> preds1 = Arrays.asList(null, null, null);
- List<MethodHandle> preds2 = Arrays.asList(null, Fac.MH_fin, null);
- MethodHandle eek = MethodHandles.dropArguments(i0, 0, int.class, int.class, double.class);
- List<MethodHandle> nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot);
- List<MethodHandle> nepreds = Arrays.asList(null, Fac.MH_pred, null);
- List<MethodHandle> nefinis = Arrays.asList(null, Fac.MH_fin, null);
- MethodHandle[][][] cases = {
- null,
- {},
- {{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
- {{null, Fac.MH_inc}, null},
- {{Fac.MH_zero, Fac.MH_dot}},
- {{ii}, {id}, {i3}},
- {{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
- {null, Counted.MH_start, null, Counted.MH_step}},
- {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, {null, Fac.MH_dot}},
- {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, {null, Fac.MH_dot}},
- {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, {null, Fac.MH_dot}}
- };
- String[] messages = {
- "null or no clauses passed",
- "null or no clauses passed",
- "All loop clauses must be represented as MethodHandle arrays with at most 4 elements.",
- "null clauses are not allowed",
- "clause 0: init and step return types must match: int != void",
- "found non-effectively identical init parameter type lists: " + inits + " (common suffix: " + ints + ")",
- "found non-identical finalizer return types: " + finis + " (return type: int)",
- "no predicate found: " + preds1,
- "predicates must have boolean return type: " + preds2,
- "found non-effectively identical parameter type lists:\nstep: " + nesteps + "\npred: " + nepreds +
- "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")"
- };
- for (int i = 0; i < cases.length; ++i) {
- boolean caught = false;
- try {
- mh_loop.invokeWithArguments(cases[i]);
- } catch (IllegalArgumentException iae) {
- assertEquals(messages[i], iae.getMessage());
- caught = true;
- }
- assertTrue(caught);
- }
- }
-
- @Test
- public static void testWhileLoop() throws Throwable {
- // int i = 0; while (i < limit) { ++i; } return i; => limit
- MethodHandle loop = MethodHandles.whileLoop(While.MH_zero, While.MH_pred, While.MH_step);
- assertEquals(While.MT_while, loop.type());
- assertEquals(23, loop.invoke(23));
- }
-
- @Test
- public static void testWhileLoopNoIteration() throws Throwable {
- // a while loop that never executes its body because the predicate evaluates to false immediately
- MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString);
- assertEquals(While.MT_string, loop.type());
- assertEquals("a", loop.invoke());
- }
-
- @Test
- public static void testDoWhileLoop() throws Throwable {
- // int i = 0; do { ++i; } while (i < limit); return i; => limit
- MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zero, While.MH_step, While.MH_pred);
- assertEquals(While.MT_while, loop.type());
- assertEquals(23, loop.invoke(23));
- }
-
- @Test
- public static void testWhileZip() throws Throwable {
- MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred);
- assertEquals(While.MT_zip, loop.type());
- List<String> a = Arrays.asList("a", "b", "c", "d");
- List<String> b = Arrays.asList("e", "f", "g", "h");
- List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
- assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
- }
-
- @Test
- public static void testCountedLoop() throws Throwable {
- // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
- MethodHandle fit13 = MethodHandles.constant(int.class, 13);
- MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step);
- assertEquals(Counted.MT_counted, loop.type());
- assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
- }
-
- @Test
- public static void testCountedArrayLoop() throws Throwable {
- // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
- MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
- MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray);
- assertEquals(Counted.MT_arrayCounted, loop.type());
- int[] a = new int[]{0};
- loop.invoke(a);
- assertEquals(13, a[0]);
- }
-
- @Test
- public static void testCountedPrintingLoop() throws Throwable {
- MethodHandle fit5 = MethodHandles.constant(int.class, 5);
- MethodHandle loop = MethodHandles.countedLoop(fit5, null, Counted.MH_printHello);
- assertEquals(Counted.MT_countedPrinting, loop.type());
- loop.invoke();
- }
-
- @Test
- public static void testCountedRangeLoop() throws Throwable {
- // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme
- MethodHandle fitm5 = MethodHandles.dropArguments(Counted.MH_m5, 0, String.class);
- MethodHandle fit8 = MethodHandles.dropArguments(Counted.MH_8, 0, String.class);
- MethodHandle loop = MethodHandles.countedLoop(fitm5, fit8, Counted.MH_start, Counted.MH_step);
- assertEquals(Counted.MT_counted, loop.type());
- assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
- }
-
- @Test
- public static void testIterateSum() throws Throwable {
- // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21
- MethodHandle loop = MethodHandles.iteratedLoop(Iterate.MH_sumIterator, Iterate.MH_sumInit, Iterate.MH_sumStep);
- assertEquals(Iterate.MT_sum, loop.type());
- assertEquals(21, loop.invoke(new Integer[]{1, 2, 3, 4, 5, 6}));
- }
-
- @Test
- public static void testIterateReverse() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_reverseInit, Iterate.MH_reverseStep);
- assertEquals(Iterate.MT_reverse, loop.type());
- List<String> list = Arrays.asList("a", "b", "c", "d", "e");
- List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
- assertEquals(reversedList, (List<String>) loop.invoke(list));
- }
-
- @Test
- public static void testIterateLength() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_lengthInit, Iterate.MH_lengthStep);
- assertEquals(Iterate.MT_length, loop.type());
- List<Double> list = Arrays.asList(23.0, 148.0, 42.0);
- assertEquals(list.size(), (int) loop.invoke(list));
- }
-
- @Test
- public static void testIterateMap() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_mapInit, Iterate.MH_mapStep);
- assertEquals(Iterate.MT_map, loop.type());
- List<String> list = Arrays.asList("Hello", "world", "!");
- List<String> upList = Arrays.asList("HELLO", "WORLD", "!");
- assertEquals(upList, (List<String>) loop.invoke(list));
- }
-
- @Test
- public static void testIteratePrint() throws Throwable {
- MethodHandle loop = MethodHandles.iteratedLoop(null, null, Iterate.MH_printStep);
- assertEquals(Iterate.MT_print, loop.type());
- loop.invoke(Arrays.asList("hello", "world"));
- }
-
- @Test
- public static void testIterateNullBody() {
- boolean caught = false;
- try {
- MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null);
- } catch (IllegalArgumentException iae) {
- assertEquals("iterated loop body must not be null", iae.getMessage());
- caught = true;
- }
- assertTrue(caught);
- }
-
- @Test
- public static void testTryFinally() throws Throwable {
- MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
- assertEquals(TryFinally.MT_hello, hello.type());
- assertEquals("Hello, world!", hello.invoke("world"));
- }
-
- @Test
- public static void testTryFinallyVoid() throws Throwable {
- MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
- assertEquals(TryFinally.MT_printHello, tfVoid.type());
- tfVoid.invoke("world");
- }
-
- @Test
- public static void testTryFinallySublist() throws Throwable {
- MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
- assertEquals(TryFinally.MT_moreHello, helloMore.type());
- assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
- }
-
- @Test
- public static void testTryFinallyNegative() {
- MethodHandle intid = MethodHandles.identity(int.class);
- MethodHandle intco = MethodHandles.constant(int.class, 0);
- MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
- MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
- int.class, double.class, Object.class);
- MethodHandle[][] cases = {
- {intid, MethodHandles.identity(double.class)},
- {intid, MethodHandles.dropArguments(intid, 0, String.class)},
- {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class)},
- {errTarget, errCleanup}
- };
- String[] messages = {
- "target and return types must match: double != int",
- "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable",
- "cleanup second argument and target return type must match: (Throwable,double,int)int != int",
- "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
- errCleanup.type() + " != " + errTarget.type()
- };
- for (int i = 0; i < cases.length; ++i) {
- boolean caught = false;
- try {
- MethodHandles.tryFinally(cases[i][0], cases[i][1]);
- } catch (IllegalArgumentException iae) {
- assertEquals(messages[i], iae.getMessage());
- caught = true;
- }
- assertTrue(caught);
- }
- }
-
- @Test
- public static void testFold0a() throws Throwable {
- // equivalence to foldArguments(MethodHandle,MethodHandle)
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder);
- assertEquals(Fold.MT_folded1, fold.type());
- assertEquals(720, (int) fold.invoke(3, 4, 5));
- }
-
- @Test
- public static void testFold1a() throws Throwable {
- // test foldArguments for folding position 1
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1);
- assertEquals(Fold.MT_folded1, fold.type());
- assertEquals(540, (int) fold.invoke(3, 4, 5));
- }
-
- @Test
- public static void testFold0b() throws Throwable {
- // test foldArguments equivalence with multiple types
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb);
- assertEquals(Fold.MT_folded2, fold.type());
- assertEquals(23, (int) fold.invoke("true", true, 23));
- }
-
- @Test
- public static void testFold1b() throws Throwable {
- // test folgArguments for folding position 1, with multiple types
- MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2);
- assertEquals(Fold.MT_folded3, fold.type());
- assertEquals(1, (int) fold.invoke(true, true, 1));
- assertEquals(-1, (int) fold.invoke(true, false, -1));
- }
-
- @Test
- public static void testFoldArgumentsExample() throws Throwable {
- // test the JavaDoc foldArguments-with-pos example
- StringWriter swr = new StringWriter();
- MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr);
- MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class));
- assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
- MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace);
- assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
- assertEquals("jum", swr.toString());
- }
-
- @Test
- public static void testAsSpreader() throws Throwable {
- MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3);
- assertEquals(SpreadCollect.MT_spreader, spreader.type());
- assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B"));
- }
-
- @Test
- public static void testAsSpreaderExample() throws Throwable {
- // test the JavaDoc asSpreader-with-pos example
- MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
- MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
- Object[] ints = new Object[]{3, 9, 7, 7};
- Comparator<Integer> cmp = (a, b) -> a - b;
- assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
- assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
- assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
- }
-
- @Test
- public static void testAsSpreaderIllegalPos() throws Throwable {
- int[] illegalPos = {-7, 3, 19};
- int caught = 0;
- for (int p : illegalPos) {
- try {
- SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3);
- } catch (IllegalArgumentException iae) {
- assertEquals("bad spread position", iae.getMessage());
- ++caught;
- }
- }
- assertEquals(illegalPos.length, caught);
- }
-
- @Test
- public static void testAsSpreaderIllegalMethodType() throws Throwable {
- MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class);
- boolean caught = false;
- try {
- MethodHandle s = h.asSpreader(String[].class, 1);
- } catch (WrongMethodTypeException wmte) {
- caught = true;
- }
- assertTrue(caught);
- }
-
- @Test
- public static void testAsCollector() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
- assertEquals(SpreadCollect.MT_collector1, collector.type());
- assertEquals("A4B", (String) collector.invoke("A", 4, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
- assertEquals(SpreadCollect.MT_collector2, collector.type());
- assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
- assertEquals(SpreadCollect.MT_collector3, collector.type());
- assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B"));
- }
-
- @Test
- public static void testAsCollectorInvokeWithArguments() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
- assertEquals(SpreadCollect.MT_collector1, collector.type());
- assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
- assertEquals(SpreadCollect.MT_collector2, collector.type());
- assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B"));
- collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
- assertEquals(SpreadCollect.MT_collector3, collector.type());
- assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B"));
- }
-
- @Test
- public static void testAsCollectorLeading() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
- assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
- assertEquals("7Q", (String) collector.invoke(7, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
- assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
- assertEquals("78Q", (String) collector.invoke(7, 8, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
- assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
- assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q"));
- }
-
- @Test
- public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
- assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
- assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
- assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
- assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q"));
- collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
- assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
- assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q"));
- }
-
- @Test
- public static void testAsCollectorNone() throws Throwable {
- MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0);
- assertEquals(SpreadCollect.MT_collector0, collector.type());
- assertEquals("AB", (String) collector.invoke("A", "B"));
- }
-
- @Test
- public static void testAsCollectorIllegalPos() throws Throwable {
- int[] illegalPos = {-1, 17};
- int caught = 0;
- for (int p : illegalPos) {
- try {
- SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0);
- } catch (IllegalArgumentException iae) {
- assertEquals("bad collect position", iae.getMessage());
- ++caught;
- }
- }
- assertEquals(illegalPos.length, caught);
- }
-
- @Test
- public static void testAsCollectorExample() throws Throwable {
- // test the JavaDoc asCollector-with-pos example
- StringWriter swr = new StringWriter();
- MethodHandle swWrite = LOOKUP.
- findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).
- bindTo(swr);
- MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
- swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
- assertEquals("BC", swr.toString());
- swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
- assertEquals("BCPQRS", swr.toString());
- swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
- assertEquals("BCPQRSZ", swr.toString());
- }
-
- @Test
- public static void testFindSpecial() throws Throwable {
- FindSpecial.C c = new FindSpecial.C();
- assertEquals("I1.m", c.m());
- MethodType t = MethodType.methodType(String.class);
- MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class);
- assertEquals("I1.m", (String) ci1m.invoke(c));
- }
-
- @Test
- public static void testFindSpecialAbstract() throws Throwable {
- FindSpecial.C c = new FindSpecial.C();
- assertEquals("q", c.q());
- MethodType t = MethodType.methodType(String.class);
- boolean caught = false;
- try {
- MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class);
- } catch (Throwable thrown) {
- if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) {
- throw new AssertionError(thrown.getMessage(), thrown);
- }
- caught = true;
- }
- assertTrue(caught);
- }
-
- @Test
- public static void testFindClassCNFE() throws Throwable {
- boolean caught = false;
- try {
- LOOKUP.findClass("does.not.Exist");
- } catch (ClassNotFoundException cnfe) {
- caught = true;
- }
- assertTrue(caught);
- }
-
- //
- // Methods used to assemble tests.
- //
-
- static class Empty {
-
- static void f() { }
-
- static boolean pred() {
- return false;
- }
-
- static final Class<Empty> EMPTY = Empty.class;
-
- static final MethodType MT_f = methodType(void.class);
- static final MethodType MT_pred = methodType(boolean.class);
-
- static final MethodHandle MH_f;
- static final MethodHandle MH_pred;
-
- static {
- try {
- MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f);
- MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
- }
-
- static class Fac {
-
- static int zero(int k) {
- return 0;
- }
-
- static int one(int k) {
- return 1;
- }
-
- static boolean pred(int i, int acc, int k) {
- return i < k;
- }
-
- static int inc(int i, int acc, int k) {
- return i + 1;
- }
-
- static int mult(int i, int acc, int k) {
- return i * acc;
- }
-
- static void dot(int i, int acc, int k) {
- System.out.print('.');
- }
-
- static int fin(int i, int acc, int k) {
- return acc;
- }
-
- static final Class<Fac> FAC = Fac.class;
-
- static final MethodType MT_init = methodType(int.class, int.class);
- static final MethodType MT_fn = methodType(int.class, int.class, int.class, int.class);
- static final MethodType MT_dot = methodType(void.class, int.class, int.class, int.class);
- static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
-
- static final MethodHandle MH_zero;
- static final MethodHandle MH_one;
- static final MethodHandle MH_pred;
- static final MethodHandle MH_inc;
- static final MethodHandle MH_mult;
- static final MethodHandle MH_dot;
- static final MethodHandle MH_fin;
-
- static final MethodType MT_fac = methodType(int.class, int.class);
-
- static {
- try {
- MH_zero = LOOKUP.findStatic(FAC, "zero", MT_init);
- MH_one = LOOKUP.findStatic(FAC, "one", MT_init);
- MH_pred = LOOKUP.findStatic(FAC, "pred", MT_pred);
- MH_inc = LOOKUP.findStatic(FAC, "inc", MT_fn);
- MH_mult = LOOKUP.findStatic(FAC, "mult", MT_fn);
- MH_dot = LOOKUP.findStatic(FAC, "dot", MT_dot);
- MH_fin = LOOKUP.findStatic(FAC, "fin", MT_fn);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class While {
-
- static int zero(int limit) {
- return 0;
- }
-
- static boolean pred(int i, int limit) {
- return i < limit;
- }
-
- static int step(int i, int limit) {
- return i + 1;
- }
-
- static String initString() {
- return "a";
- }
-
- static boolean predString(String s) {
- return s.length() != 1;
- }
-
- static String stepString(String s) {
- return s + "a";
- }
-
- static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) {
- return new ArrayList<>();
- }
-
- static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) {
- return a.hasNext() && b.hasNext();
- }
-
- static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
- zip.add(a.next());
- zip.add(b.next());
- return zip;
- }
-
- static final Class<While> WHILE = While.class;
-
- static final MethodType MT_zero = methodType(int.class, int.class);
- static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
- static final MethodType MT_fn = methodType(int.class, int.class, int.class);
- static final MethodType MT_initString = methodType(String.class);
- static final MethodType MT_predString = methodType(boolean.class, String.class);
- static final MethodType MT_stepString = methodType(String.class, String.class);
- static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
- static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
- static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
-
- static final MethodHandle MH_zero;
- static final MethodHandle MH_pred;
- static final MethodHandle MH_step;
- static final MethodHandle MH_initString;
- static final MethodHandle MH_predString;
- static final MethodHandle MH_stepString;
- static final MethodHandle MH_zipInitZip;
- static final MethodHandle MH_zipPred;
- static final MethodHandle MH_zipStep;
-
- static final MethodType MT_while = methodType(int.class, int.class);
- static final MethodType MT_string = methodType(String.class);
- static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class);
-
- static {
- try {
- MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero);
- MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred);
- MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn);
- MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString);
- MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString);
- MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString);
- MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
- MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
- MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class Counted {
-
- static String start(String arg) {
- return arg;
- }
-
- static String step(int counter, String v, String arg) {
- return "na " + v;
- }
-
- static void stepUpdateArray(int counter, int[] a) {
- ++a[0];
- }
-
- static void printHello(int counter) {
- System.out.print("hello");
- }
-
- static final Class<Counted> COUNTED = Counted.class;
-
- static final MethodType MT_start = methodType(String.class, String.class);
- static final MethodType MT_step = methodType(String.class, int.class, String.class, String.class);
- static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class);
- static final MethodType MT_printHello = methodType(void.class, int.class);
-
- static final MethodHandle MH_13;
- static final MethodHandle MH_m5;
- static final MethodHandle MH_8;
- static final MethodHandle MH_start;
- static final MethodHandle MH_step;
- static final MethodHandle MH_stepUpdateArray;
- static final MethodHandle MH_printHello;
-
- static final MethodType MT_counted = methodType(String.class, String.class);
- static final MethodType MT_arrayCounted = methodType(void.class, int[].class);
- static final MethodType MT_countedPrinting = methodType(void.class);
-
- static {
- try {
- MH_13 = MethodHandles.constant(int.class, 13);
- MH_m5 = MethodHandles.constant(int.class, -5);
- MH_8 = MethodHandles.constant(int.class, 8);
- MH_start = LOOKUP.findStatic(COUNTED, "start", MT_start);
- MH_step = LOOKUP.findStatic(COUNTED, "step", MT_step);
- MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray);
- MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class Iterate {
-
- static Iterator<Integer> sumIterator(Integer[] a) {
- return Arrays.asList(a).iterator();
- }
-
- static int sumInit(Integer[] a) {
- return 0;
- }
-
- static int sumStep(int s, int e, Integer[] a) {
- return s + e;
- }
-
- static List<String> reverseInit(List<String> l) {
- return new ArrayList<>();
- }
-
- static List<String> reverseStep(String e, List<String> r, List<String> l) {
- r.add(0, e);
- return r;
- }
-
- static int lengthInit(List<Double> l) {
- return 0;
- }
-
- static int lengthStep(Object o, int len, List<Double> l) {
- return len + 1;
- }
-
- static List<String> mapInit(List<String> l) {
- return new ArrayList<>();
- }
-
- static List<String> mapStep(String e, List<String> r, List<String> l) {
- r.add(e.toUpperCase());
- return r;
- }
-
- static void printStep(String s, List<String> l) {
- System.out.print(s);
- }
-
- static final Class<Iterate> ITERATE = Iterate.class;
-
- static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class);
-
- static final MethodType MT_sumInit = methodType(int.class, Integer[].class);
- static final MethodType MT_reverseInit = methodType(List.class, List.class);
- static final MethodType MT_lenghInit = methodType(int.class, List.class);
- static final MethodType MT_mapInit = methodType(List.class, List.class);
-
- static final MethodType MT_sumStep = methodType(int.class, int.class, int.class, Integer[].class);
- static final MethodType MT_reverseStep = methodType(List.class, String.class, List.class, List.class);
- static final MethodType MT_lengthStep = methodType(int.class, Object.class, int.class, List.class);
- static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class);
- static final MethodType MT_printStep = methodType(void.class, String.class, List.class);
-
- static final MethodHandle MH_sumIterator;
- static final MethodHandle MH_sumInit;
- static final MethodHandle MH_sumStep;
- static final MethodHandle MH_printStep;
-
- static final MethodHandle MH_reverseInit;
- static final MethodHandle MH_reverseStep;
-
- static final MethodHandle MH_lengthInit;
- static final MethodHandle MH_lengthStep;
-
- static final MethodHandle MH_mapInit;
- static final MethodHandle MH_mapStep;
-
- static final MethodType MT_sum = methodType(int.class, Integer[].class);
- static final MethodType MT_reverse = methodType(List.class, List.class);
- static final MethodType MT_length = methodType(int.class, List.class);
- static final MethodType MT_map = methodType(List.class, List.class);
- static final MethodType MT_print = methodType(void.class, List.class);
-
- static {
- try {
- MH_sumIterator = LOOKUP.findStatic(ITERATE, "sumIterator", MT_sumIterator);
- MH_sumInit = LOOKUP.findStatic(ITERATE, "sumInit", MT_sumInit);
- MH_sumStep = LOOKUP.findStatic(ITERATE, "sumStep", MT_sumStep);
- MH_reverseInit = LOOKUP.findStatic(ITERATE, "reverseInit", MT_reverseInit);
- MH_reverseStep = LOOKUP.findStatic(ITERATE, "reverseStep", MT_reverseStep);
- MH_lengthInit = LOOKUP.findStatic(ITERATE, "lengthInit", MT_lenghInit);
- MH_lengthStep = LOOKUP.findStatic(ITERATE, "lengthStep", MT_lengthStep);
- MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit);
- MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep);
- MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class TryFinally {
-
- static String greet(String whom) {
- return "Hello, " + whom;
- }
-
- static String exclaim(Throwable t, String r, String whom) {
- return r + "!";
- }
-
- static void print(String what) {
- System.out.print("Hello, " + what);
- }
-
- static void printMore(Throwable t, String what) {
- System.out.println("!");
- }
-
- static String greetMore(String first, String second) {
- return "Hello, " + first + " and " + second;
- }
-
- static String exclaimMore(Throwable t, String r, String first) {
- return r + " (but " + first + " first)!";
- }
-
- static final Class<TryFinally> TRY_FINALLY = TryFinally.class;
-
- static final MethodType MT_greet = methodType(String.class, String.class);
- static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
- static final MethodType MT_print = methodType(void.class, String.class);
- static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
- static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
- static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
-
- static final MethodHandle MH_greet;
- static final MethodHandle MH_exclaim;
- static final MethodHandle MH_print;
- static final MethodHandle MH_printMore;
- static final MethodHandle MH_greetMore;
- static final MethodHandle MH_exclaimMore;
-
- static final MethodType MT_hello = methodType(String.class, String.class);
- static final MethodType MT_printHello = methodType(void.class, String.class);
- static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
-
- static {
- try {
- MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
- MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
- MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
- MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
- MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
- MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class Fold {
-
- static int adder(int a, int b, int c) {
- return a + b + c;
- }
-
- static int adder1(int a, int b) {
- return a + b;
- }
-
- static int multer(int x, int q, int r, int s) {
- return x * q * r * s;
- }
-
- static int str(boolean b1, String s, boolean b2, int x) {
- return b1 && s.equals(String.valueOf(b2)) ? x : -x;
- }
-
- static boolean comb(String s, boolean b2) {
- return !s.equals(b2);
- }
-
- static String comb2(boolean b2, int x) {
- int ib = b2 ? 1 : 0;
- return ib == x ? "true" : "false";
- }
-
- static final Class<Fold> FOLD = Fold.class;
-
- static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class);
- static final MethodType MT_adder1 = methodType(int.class, int.class, int.class);
- static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class);
- static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class);
- static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class);
- static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class);
-
- static final MethodHandle MH_adder;
- static final MethodHandle MH_adder1;
- static final MethodHandle MH_multer;
- static final MethodHandle MH_str;
- static final MethodHandle MH_comb;
- static final MethodHandle MH_comb2;
-
- static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class);
- static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class);
- static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class);
-
- static {
- try {
- MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder);
- MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1);
- MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer);
- MH_str = LOOKUP.findStatic(FOLD, "str", MT_str);
- MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb);
- MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
- }
-
- static class SpreadCollect {
-
- static String forSpreading(String s1, int i1, int i2, int i3, String s2) {
- return s1 + i1 + i2 + i3 + s2;
- }
-
- static String forCollecting(String s1, int[] is, String s2) {
- StringBuilder sb = new StringBuilder(s1);
- for (int i : is) {
- sb.append(i);
- }
- return sb.append(s2).toString();
- }
-
- static String forCollectingLeading(int[] is, String s) {
- return forCollecting("", is, s);
- }
-
- static final Class<SpreadCollect> SPREAD_COLLECT = SpreadCollect.class;
-
- static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
- static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class);
- static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class);
-
- static final MethodHandle MH_forSpreading;
- static final MethodHandle MH_forCollecting;
- static final MethodHandle MH_forCollectingLeading;
-
- static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class);
- static final MethodType MT_collector0 = methodType(String.class, String.class, String.class);
- static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class);
- static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class);
- static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
- static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class);
- static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class);
- static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class);
-
- static final String NONE_ERROR = "zero array length in MethodHandle.asCollector";
-
- static {
- try {
- MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading);
- MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting);
- MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading);
- } catch (Exception e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
- }
-
- static class FindSpecial {
-
- interface I1 {
- default String m() {
- return "I1.m";
- }
- }
-
- interface I2 {
- default String m() {
- return "I2.m";
- }
- }
-
- interface I3 {
- String q();
- }
-
- static class C implements I1, I2, I3 {
- public String m() {
- return I1.super.m();
- }
- public String q() {
- return "q";
- }
- }
-
- static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.T8139885$FindSpecial$I3.q()String/invokeSpecial";
-
- }
-
- //
- // Auxiliary methods.
- //
-
- static MethodHandle[] mha(MethodHandle... mhs) {
- return mhs;
- }
-
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/TryFinallyTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015, 2016, 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
+ * @bug 8139885
+ * @bug 8150825
+ * @run testng/othervm -ea -esa test.java.lang.invoke.TryFinallyTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the tryFinally method handle combinator introduced in JEP 274.
+ */
+public class TryFinallyTest {
+
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ @Test
+ public static void testTryFinally() throws Throwable {
+ MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
+ assertEquals(TryFinally.MT_hello, hello.type());
+ assertEquals("Hello, world!", hello.invoke("world"));
+ }
+
+ @Test
+ public static void testTryFinallyVoid() throws Throwable {
+ MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
+ assertEquals(TryFinally.MT_printHello, tfVoid.type());
+ tfVoid.invoke("world");
+ }
+
+ @Test
+ public static void testTryFinallySublist() throws Throwable {
+ MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
+ assertEquals(TryFinally.MT_moreHello, helloMore.type());
+ assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
+ }
+
+ @DataProvider
+ static Object[][] negativeTestData() {
+ MethodHandle intid = MethodHandles.identity(int.class);
+ MethodHandle intco = MethodHandles.constant(int.class, 0);
+ MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
+ MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
+ int.class, double.class, Object.class);
+ return new Object[][]{
+ {intid, MethodHandles.identity(double.class),
+ "target and return types must match: double != int"},
+ {intid, MethodHandles.dropArguments(intid, 0, String.class),
+ "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable"},
+ {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class),
+ "cleanup second argument and target return type must match: (Throwable,double,int)int != int"},
+ {errTarget, errCleanup,
+ "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+ errCleanup.type() + " != " + errTarget.type()},
+ {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup,
+ "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+ TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type()}
+ };
+ }
+
+ @Test(dataProvider = "negativeTestData")
+ public static void testTryFinallyNegative(MethodHandle target, MethodHandle cleanup, String expectedMessage) {
+ boolean caught = false;
+ try {
+ MethodHandles.tryFinally(target, cleanup);
+ } catch (IllegalArgumentException iae) {
+ assertEquals(expectedMessage, iae.getMessage());
+ caught = true;
+ }
+ assertTrue(caught);
+ }
+
+ static class TryFinally {
+
+ static String greet(String whom) {
+ return "Hello, " + whom;
+ }
+
+ static String exclaim(Throwable t, String r, String whom) {
+ return r + "!";
+ }
+
+ static void print(String what) {
+ System.out.print("Hello, " + what);
+ }
+
+ static void printMore(Throwable t, String what) {
+ System.out.println("!");
+ }
+
+ static String greetMore(String first, String second) {
+ return "Hello, " + first + " and " + second;
+ }
+
+ static String exclaimMore(Throwable t, String r, String first) {
+ return r + " (but " + first + " first)!";
+ }
+
+ static void voidTarget() {}
+
+ static void voidCleanup(Throwable t, int a) {}
+
+ static final Class<TryFinally> TRY_FINALLY = TryFinally.class;
+
+ static final MethodType MT_greet = methodType(String.class, String.class);
+ static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
+ static final MethodType MT_print = methodType(void.class, String.class);
+ static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
+ static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
+ static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
+ static final MethodType MT_voidTarget = methodType(void.class);
+ static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class);
+
+ static final MethodHandle MH_greet;
+ static final MethodHandle MH_exclaim;
+ static final MethodHandle MH_print;
+ static final MethodHandle MH_printMore;
+ static final MethodHandle MH_greetMore;
+ static final MethodHandle MH_exclaimMore;
+ static final MethodHandle MH_voidTarget;
+ static final MethodHandle MH_voidCleanup;
+
+ static final MethodType MT_hello = methodType(String.class, String.class);
+ static final MethodType MT_printHello = methodType(void.class, String.class);
+ static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
+
+ static {
+ try {
+ MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
+ MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
+ MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
+ MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
+ MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
+ MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
+ MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget);
+ MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ }
+
+}
--- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -27,6 +27,7 @@
* @summary tests DoPrivileged action (implemented as lambda expressions) by
* inserting them into the BootClassPath.
* @modules jdk.compiler
+ * jdk.zipfs
* @compile -XDignore.symbol.file LambdaAccessControlDoPrivilegedTest.java LUtils.java
* @run main/othervm LambdaAccessControlDoPrivilegedTest
*/
--- a/jdk/test/java/lang/invoke/lambda/LambdaAsm.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/invoke/lambda/LambdaAsm.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
* generate bytecodes with correct constant pool references
* @modules java.base/jdk.internal.org.objectweb.asm
* jdk.jdeps/com.sun.tools.classfile
+ * jdk.zipfs
* @compile -XDignore.symbol.file LambdaAsm.java LUtils.java
* @run main/othervm LambdaAsm
*/
--- a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,8 @@
* @bug 8023524
* @summary tests logging generated classes for lambda
* @library /java/nio/file
+ * @modules jdk.compiler
+ * jdk.zipfs
* @run testng LogGeneratedClassesTest
*/
import java.io.File;
--- a/jdk/test/java/lang/ref/CleanerTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/lang/ref/CleanerTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -52,7 +52,10 @@
* @library /test/lib/share/classes /lib/testlibrary /test/lib
* @build sun.hotspot.WhiteBox
* @build jdk.test.lib.Utils
- * @modules java.base/jdk.internal.misc java.base/jdk.internal.ref
+ * @modules java.base/jdk.internal
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.ref
+ * java.management
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run testng/othervm
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/SocketOption/ImmutableOptions.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016, 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 8148609
+ * @run testng/othervm ImmutableOptions
+ * @summary Assert that the set of socket options are immutable
+ */
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.*;
+import java.util.Set;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+public class ImmutableOptions {
+
+ @BeforeTest
+ void setupServerSocketFactory() throws IOException {
+ ServerSocket.setSocketFactory(new ServerSocketImplFactory());
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void socketThrows() throws IOException {
+ CustomSocketImpl impl = new CustomSocketImpl();
+ Socket socket = new CustomSocket(impl);
+ socket.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void socketImplThrows() throws IOException {
+ CustomSocketImpl impl = new CustomSocketImpl();
+ impl.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void serverSocketThrows() throws IOException {
+ ServerSocket ss = new ServerSocket();
+ ss.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void serverSocketImplThrows() throws IOException {
+ ServerSocket ss = new ServerSocket();
+ ServerSocketImplFactory.mostRecentlyCreated.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void datagramSocketThrows() throws IOException {
+ CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl();
+ DatagramSocket socket = new CustomDatagramSocket(impl);
+ socket.supportedOptions().clear();
+ }
+
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void datagramSocketImplThrows() throws IOException {
+ CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl();
+ impl.supportedOptions().clear();
+ }
+
+
+ // Socket descendants
+ static class CustomSocket extends Socket {
+ public CustomSocket(SocketImpl impl) throws IOException {
+ super(impl);
+ }
+ }
+
+ static class CustomDatagramSocket extends DatagramSocket {
+ public CustomDatagramSocket(DatagramSocketImpl impl) {
+ super(impl);
+ }
+ }
+
+ static class ServerSocketImplFactory implements SocketImplFactory {
+ static volatile CustomSocketImpl mostRecentlyCreated;
+
+ @Override public SocketImpl createSocketImpl() {
+ return mostRecentlyCreated = new CustomSocketImpl();
+ }
+ }
+
+ // Custom impl's
+ static class CustomSocketImpl extends SocketImpl {
+ // The only method interesting to this test.
+ @Override public Set<SocketOption<?>> supportedOptions() {
+ return super.supportedOptions();
+ }
+
+ public void create(boolean stream) throws IOException { }
+
+ public void connect(String host, int port) throws IOException { }
+
+ public void connect(InetAddress addr, int port) throws IOException { }
+
+ public void connect(SocketAddress addr, int timeout) throws IOException { }
+
+ public void bind(InetAddress host, int port) throws IOException { }
+
+ public void listen(int backlog) throws IOException { }
+
+ public void accept(SocketImpl s) throws IOException { }
+
+ public InputStream getInputStream() throws IOException { return null; }
+
+ public OutputStream getOutputStream() throws IOException { return null; }
+
+ public int available() throws IOException { return 0; }
+
+ public void close() throws IOException { }
+
+ public void sendUrgentData(int data) throws IOException { }
+
+ public Object getOption(int i) throws SocketException { return null; }
+
+ public void setOption(int i, Object o) throws SocketException { }
+ }
+
+ static class CustomDatagramSocketImpl extends DatagramSocketImpl {
+ // The only method interesting to this test.
+ @Override public Set<SocketOption<?>> supportedOptions() {
+ return super.supportedOptions();
+ }
+
+ protected void create() throws SocketException { }
+
+ protected void bind(int lport, InetAddress laddr) throws SocketException { }
+
+ protected void send(DatagramPacket p) throws IOException { }
+
+ protected int peek(InetAddress i) throws IOException { return 0; }
+
+ protected int peekData(DatagramPacket p) throws IOException { return 0; }
+
+ protected void receive(DatagramPacket p) throws IOException { }
+
+ protected void setTTL(byte ttl) throws IOException { }
+
+ protected byte getTTL() throws IOException { return 0; }
+
+ protected void setTimeToLive(int ttl) throws IOException { }
+
+ protected int getTimeToLive() throws IOException { return 0; }
+
+ protected void join(InetAddress inetaddr) throws IOException { }
+
+ protected void leave(InetAddress inetaddr) throws IOException { }
+
+ protected void joinGroup(SocketAddress x, NetworkInterface y)
+ throws IOException { }
+
+ protected void leaveGroup(SocketAddress x, NetworkInterface y)
+ throws IOException { }
+
+ protected void close() { }
+
+ public void setOption(int optID, Object value) throws SocketException { }
+
+ public Object getOption(int optID) throws SocketException { return null; }
+ }
+}
--- a/jdk/test/java/net/ipv6tests/UdpTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/net/ipv6tests/UdpTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -24,6 +24,7 @@
/*
* @test
* @bug 4868820
+ * @key intermittent
* @summary IPv6 support for Windows XP and 2003 server
*/
--- a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@
* java.rmi/sun.rmi.transport.tcp
* @build TestLibrary JavaVM LeaseCheckInterval_Stub SelfTerminator
* @run main/othervm LeaseCheckInterval
+ * @key intermittent
*/
import java.rmi.Remote;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/DFSConstructorCloneTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, 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 8087104
+ * @summary Make sure that clone() method is not called from DateFormatSymbols constructor.
+ */
+import java.text.DateFormatSymbols;
+
+public class DFSymbolsCloneTest extends DateFormatSymbols {
+
+ private Foo foo;
+
+ public DFSymbolsCloneTest(Foo fooObj) {
+ if (fooObj == null) {
+ this.foo = new Foo();
+ } else {
+ this.foo = fooObj;
+ }
+ }
+
+ @Override
+ public Object clone() {
+ DFSymbolsCloneTest dfsclone = (DFSymbolsCloneTest) super.clone();
+ if (this.foo == null) {
+ throw new RuntimeException("Clone method should not be called from "
+ + " Superclass(DateFormatSymbols) Constructor...");
+ } else {
+ dfsclone.foo = (Foo) this.foo.clone();
+ }
+ return dfsclone;
+ }
+
+ public static void main(String[] args) {
+ DFSymbolsCloneTest dfsctest = new DFSymbolsCloneTest(new Foo());
+ }
+}
+
+class Foo {
+
+ public Foo() {
+ }
+
+ @Override
+ protected Object clone() {
+ return new Foo();
+ }
+
+}
--- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Sat Mar 05 20:46:44 2016 -0800
@@ -29,26 +29,50 @@
* @run main GCDuringIteration
* @summary Check that iterators work properly in the presence of
* concurrent finalization and removal of elements.
- * @key randomness intermittent
+ * @key randomness
*/
-import java.util.*;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Random;
+import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
+import java.util.function.BooleanSupplier;
import jdk.testlibrary.RandomFactory;
public class GCDuringIteration {
- private static void waitForFinalizersToRun() {
- for (int i = 0; i < 2; i++)
- tryWaitForFinalizersToRun();
+
+ /** No guarantees, but effective in practice. */
+ static void forceFullGc() {
+ CountDownLatch finalizeDone = new CountDownLatch(1);
+ WeakReference<?> ref = new WeakReference<Object>(new Object() {
+ protected void finalize() { finalizeDone.countDown(); }});
+ try {
+ for (int i = 0; i < 10; i++) {
+ System.gc();
+ if (finalizeDone.await(1L, SECONDS) && ref.get() == null) {
+ System.runFinalization(); // try to pick up stragglers
+ return;
+ }
+ }
+ } catch (InterruptedException unexpected) {
+ throw new AssertionError("unexpected InterruptedException");
+ }
+ throw new AssertionError("failed to do a \"full\" gc");
}
- private static void tryWaitForFinalizersToRun() {
- System.gc();
- final CountDownLatch fin = new CountDownLatch(1);
- new Object() { protected void finalize() { fin.countDown(); }};
- System.gc();
- try { fin.await(); }
- catch (InterruptedException ie) { throw new Error(ie); }
+ static void gcAwait(BooleanSupplier s) {
+ for (int i = 0; i < 10; i++) {
+ if (s.getAsBoolean())
+ return;
+ forceFullGc();
+ }
+ throw new AssertionError("failed to satisfy condition");
}
// A class with the traditional pessimal hashCode implementation,
@@ -76,9 +100,13 @@
if (rnd.nextBoolean()) check(it.hasNext());
equal(it.next().getValue(), i);
}
- if (rnd.nextBoolean())
- THROWS(NoSuchElementException.class,
- new F(){void f(){it.next();}});
+ if (rnd.nextBoolean()) {
+ try {
+ it.next();
+ throw new AssertionError("should throw");
+ } catch (NoSuchElementException success) {}
+ }
+
if (rnd.nextBoolean())
check(! it.hasNext());
}
@@ -106,9 +134,7 @@
int first = firstValue(map);
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
foos[first] = null;
- for (int i = 0; i < 10 && map.size() != first; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first);
+ gcAwait(() -> map.size() == first);
checkIterator(it, first-1);
equal(map.size(), first);
equal(firstValue(map), first-1);
@@ -119,15 +145,14 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.next(); // protects first entry
System.out.println(map.values());
+ int oldSize = map.size();
foos[first] = null;
- tryWaitForFinalizersToRun();
- equal(map.size(), first+1);
+ forceFullGc();
+ equal(map.size(), oldSize);
System.out.println(map.values());
checkIterator(it, first-1);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first);
+ gcAwait(() -> map.size() == first);
equal(firstValue(map), first-1);
}
@@ -137,15 +162,12 @@
it.next(); // protects first entry
System.out.println(map.values());
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
- equal(map.size(), first);
+ gcAwait(() -> map.size() == first);
equal(firstValue(map), first);
System.out.println(map.values());
checkIterator(it, first-2);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -155,16 +177,15 @@
it.next(); // protects first entry
it.hasNext(); // protects second entry
System.out.println(map.values());
+ int oldSize = map.size();
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
+ forceFullGc();
+ equal(map.size(), oldSize);
equal(firstValue(map), first);
- equal(map.size(), first+1);
System.out.println(map.values());
checkIterator(it, first-1);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -173,17 +194,16 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.next(); // protects first entry
System.out.println(map.values());
+ equal(map.size(), first+1);
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
+ gcAwait(() -> map.size() == first);
it.remove();
equal(firstValue(map), first-2);
equal(map.size(), first-1);
System.out.println(map.values());
checkIterator(it, first-2);
// first entry no longer protected
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -194,15 +214,14 @@
it.remove();
it.hasNext(); // protects second entry
System.out.println(map.values());
+ equal(map.size(), first);
foos[first] = foos[first-1] = null;
- tryWaitForFinalizersToRun();
+ forceFullGc();
equal(firstValue(map), first-1);
equal(map.size(), first);
System.out.println(map.values());
checkIterator(it, first-1);
- for (int i = 0; i < 10 && map.size() != first-1; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), first-1);
+ gcAwait(() -> map.size() == first-1);
equal(firstValue(map), first-2);
}
@@ -211,14 +230,11 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.hasNext(); // protects first entry
Arrays.fill(foos, null);
- tryWaitForFinalizersToRun();
- equal(map.size(), 1);
+ gcAwait(() -> map.size() == 1);
System.out.println(map.values());
equal(it.next().getValue(), first);
check(! it.hasNext());
- for (int i = 0; i < 10 && map.size() != 0; i++)
- tryWaitForFinalizersToRun();
- equal(map.size(), 0);
+ gcAwait(() -> map.size() == 0);
check(map.isEmpty());
}
}
@@ -239,11 +255,4 @@
try {test(args);} catch (Throwable t) {unexpected(t);}
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new AssertionError("Some tests failed");}
- abstract class F {abstract void f() throws Throwable;}
- void THROWS(Class<? extends Throwable> k, F... fs) {
- for (F f : fs)
- try {f.f(); fail("Expected " + k.getName() + " not thrown");}
- catch (Throwable t) {
- if (k.isAssignableFrom(t.getClass())) pass();
- else unexpected(t);}}
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,8 +35,11 @@
* @test
* @bug 4486658
* @summary Checks for responsiveness of blocking queues to cancellation.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.ArrayList;
import java.util.List;
import java.util.SplittableRandom;
@@ -53,8 +56,10 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class CancelledProducerConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -73,7 +78,7 @@
new CancelledProducerConsumerLoops(i, queue).run();
}
pool.shutdown();
- if (! pool.awaitTermination(10L, TimeUnit.SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
pool = null;
}
@@ -117,18 +122,18 @@
assertCancelled(cons[i]);
}
- if (!producersInterrupted.await(10L, TimeUnit.SECONDS))
+ if (!producersInterrupted.await(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
- if (!consumersInterrupted.await(10L, TimeUnit.SECONDS))
+ if (!consumersInterrupted.await(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
if (prods[0].isDone() || prods[0].isCancelled())
throw new AssertionError("completed too early");
done = true;
- if (! (prods[0].get(10L, TimeUnit.SECONDS) instanceof Integer))
+ if (! (prods[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer))
throw new AssertionError("expected Integer");
- if (! (cons[0].get(10L, TimeUnit.SECONDS) instanceof Integer))
+ if (! (cons[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer))
throw new AssertionError("expected Integer");
}
@@ -138,7 +143,7 @@
if (!future.isCancelled())
throw new AssertionError("not cancelled");
try {
- future.get(10L, TimeUnit.SECONDS);
+ future.get(LONG_DELAY_MS, MILLISECONDS);
throw new AssertionError("should throw CancellationException");
} catch (CancellationException success) {}
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,10 +26,10 @@
* @bug 6384064
* @summary Check proper handling of interrupts
* @author Martin Buchholz
+ * @library /lib/testlibrary/
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
import java.util.List;
@@ -41,8 +41,10 @@
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
+import jdk.testlibrary.Utils;
public class Interrupt {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void checkInterrupted0(Iterable<Fun> fs, Executor ex) {
for (Fun f : fs) {
@@ -71,7 +73,7 @@
checkInterrupted0(fs, immediateExecutor);
checkInterrupted0(fs, delayedExecutor);
stpe.shutdown();
- check(stpe.awaitTermination(10L, SECONDS));
+ check(stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
static void testQueue(final BlockingQueue<Object> q) {
@@ -82,12 +84,12 @@
q.clear();
List<Fun> fs = new ArrayList<Fun>();
fs.add(() -> q.take());
- fs.add(() -> q.poll(60, SECONDS));
+ fs.add(() -> q.poll(LONG_DELAY_MS, MILLISECONDS));
if (deq != null) {
fs.add(() -> deq.takeFirst());
fs.add(() -> deq.takeLast());
- fs.add(() -> deq.pollFirst(7, SECONDS));
- fs.add(() -> deq.pollLast(7, SECONDS));
+ fs.add(() -> deq.pollFirst(LONG_DELAY_MS, MILLISECONDS));
+ fs.add(() -> deq.pollLast(LONG_DELAY_MS, MILLISECONDS));
}
checkInterrupted(fs);
@@ -99,12 +101,12 @@
fs.clear();
fs.add(() -> q.put(1));
- fs.add(() -> q.offer(1, 7, SECONDS));
+ fs.add(() -> q.offer(1, LONG_DELAY_MS, MILLISECONDS));
if (deq != null) {
fs.add(() -> deq.putFirst(1));
fs.add(() -> deq.putLast(1));
- fs.add(() -> deq.offerFirst(1, 7, SECONDS));
- fs.add(() -> deq.offerLast(1, 7, SECONDS));
+ fs.add(() -> deq.offerFirst(1, LONG_DELAY_MS, MILLISECONDS));
+ fs.add(() -> deq.offerLast(1, LONG_DELAY_MS, MILLISECONDS));
}
checkInterrupted(fs);
} catch (Throwable t) {
--- a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,10 +35,11 @@
* @test
* @bug 4486658
* @summary multiple producers and single consumer using blocking queues
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -51,8 +52,10 @@
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class MultipleProducersSingleConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -77,7 +80,7 @@
}
pool.shutdown();
- if (! pool.awaitTermination(10L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,10 +35,11 @@
* @test
* @bug 4486658
* @summary multiple producers and consumers using blocking queues
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -51,8 +52,10 @@
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class ProducerConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -77,7 +80,7 @@
run(new ArrayBlockingQueue<Integer>(100, true), i, 100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,10 +35,11 @@
* @test
* @bug 4486658
* @summary check ordering for blocking queues with 1 producer and multiple consumers
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -50,8 +51,10 @@
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
+import jdk.testlibrary.Utils;
public class SingleProducerMultipleConsumerLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
public static void main(String[] args) throws Exception {
@@ -75,7 +78,7 @@
run(new ArrayBlockingQueue<Integer>(100, true), i, 100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,15 +34,17 @@
/*
* @test
* @bug 8005696
+ * @summary Basic tests for CompletableFuture
+ * @library /lib/testlibrary/
* @run main Basic
* @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 Basic
- * @summary Basic tests for CompletableFuture
* @author Chris Hegarty
*/
import static java.util.concurrent.CompletableFuture.runAsync;
import static java.util.concurrent.CompletableFuture.supplyAsync;
import static java.util.concurrent.ForkJoinPool.commonPool;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.lang.reflect.Array;
@@ -54,8 +56,10 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class Basic {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void checkCompletedNormally(CompletableFuture<?> cf, Object value) {
checkCompletedNormally(cf, value == null ? null : new Object[] { value });
@@ -109,12 +113,13 @@
}
private static void realMain(String[] args) throws Throwable {
- ExecutorService executor = Executors.newFixedThreadPool(2);
+ ExecutorService pool = Executors.newFixedThreadPool(2);
try {
- test(executor);
+ test(pool);
} finally {
- executor.shutdown();
- executor.awaitTermination(30L, SECONDS);
+ pool.shutdown();
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
+ throw new Error();
}
}
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,7 +34,6 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=1600 MapLoops
* @summary Exercise multithreaded maps, by default ConcurrentHashMap.
* Multithreaded hash table test. Each thread does a random walk
* though elements of "key" array. On each iteration, it checks if
@@ -42,9 +41,11 @@
* inserts it, and if present, with probability premove it removes
* it. (pinsert and premove are expressed as percentages to simplify
* parsing from command line.)
+ * @library /lib/testlibrary/
+ * @run main/timeout=1600 MapLoops
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.List;
import java.util.Map;
@@ -53,8 +54,10 @@
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class MapLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static int nkeys = 1000; // 10_000
static int pinsert = 60;
static int premove = 2;
@@ -126,7 +129,7 @@
i = k;
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
if (! throwables.isEmpty())
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,11 +34,12 @@
/*
* @test
* @bug 4486658 6785442
+ * @summary Checks that a set of threads can repeatedly get and modify items
+ * @library /lib/testlibrary/
* @run main ConcurrentQueueLoops 8 123456
- * @summary Checks that a set of threads can repeatedly get and modify items
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.ArrayList;
import java.util.Collection;
@@ -57,8 +58,10 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class ConcurrentQueueLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
ExecutorService pool;
AtomicInteger totalItems;
boolean print;
@@ -106,16 +109,14 @@
print = false;
System.out.println("Warmup...");
oneRun(1, items, q);
- //Thread.sleep(100);
oneRun(3, items, q);
- Thread.sleep(100);
print = true;
for (int i = 1; i <= maxStages; i += (i+1) >>> 1) {
oneRun(i, items, q);
}
pool.shutdown();
- check(pool.awaitTermination(60L, SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
class Stage implements Callable<Integer> {
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Sat Mar 05 20:46:44 2016 -0800
@@ -38,10 +38,14 @@
* @run main GCRetention 12345
*/
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.lang.ref.WeakReference;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.LinkedTransferQueue;
@@ -59,6 +63,25 @@
// Suitable for benchmarking. Overridden by args[0] for testing.
int count = 1024 * 1024;
+ /** No guarantees, but effective in practice. */
+ static void forceFullGc() {
+ CountDownLatch finalizeDone = new CountDownLatch(1);
+ WeakReference<?> ref = new WeakReference<Object>(new Object() {
+ protected void finalize() { finalizeDone.countDown(); }});
+ try {
+ for (int i = 0; i < 10; i++) {
+ System.gc();
+ if (finalizeDone.await(1L, SECONDS) && ref.get() == null) {
+ System.runFinalization(); // try to pick up stragglers
+ return;
+ }
+ }
+ } catch (InterruptedException unexpected) {
+ throw new AssertionError("unexpected InterruptedException");
+ }
+ throw new AssertionError("failed to do a \"full\" gc");
+ }
+
final Map<String,String> results = new ConcurrentHashMap<String,String>();
Collection<Queue<Boolean>> queues() {
@@ -117,8 +140,8 @@
long t0 = System.nanoTime();
for (int i = 0; i < count; i++)
check(q.add(Boolean.TRUE));
- System.gc();
- System.gc();
+ forceFullGc();
+ // forceFullGc();
Boolean x;
while ((x = q.poll()) != null)
equal(x, Boolean.TRUE);
--- a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,11 +25,11 @@
* @test
* @bug 6253848 6366811
* @summary Basic tests for CyclicBarrier
+ * @library /lib/testlibrary/
* @author Martin Buchholz, David Holmes
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
import java.util.Iterator;
@@ -39,8 +39,10 @@
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
+import jdk.testlibrary.Utils;
public class Basic {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
private static void checkBroken(final CyclicBarrier barrier) {
check(barrier.isBroken());
@@ -77,7 +79,7 @@
private static final CyclicBarrier atTheStartingGate = new CyclicBarrier(3);
private static void toTheStartingGate() {
- try { atTheStartingGate.await(10, SECONDS); pass(); }
+ try { atTheStartingGate.await(LONG_DELAY_MS, MILLISECONDS); pass(); }
catch (Throwable t) {
unexpected(t);
reset(atTheStartingGate);
@@ -314,13 +316,13 @@
Throwable throwable() { return this.throwable; }
boolean interruptBit() { return this.interrupted; }
void realRun() throws Throwable {
- startingGate.await(10, SECONDS);
+ startingGate.await(LONG_DELAY_MS, MILLISECONDS);
try {
- if (timed) barrier.await(10, SECONDS);
+ if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS);
else barrier.await(); }
catch (Throwable throwable) { this.throwable = throwable; }
- try { doneSignal.await(10, SECONDS); }
+ try { doneSignal.await(LONG_DELAY_MS, MILLISECONDS); }
catch (InterruptedException e) { interrupted = true; }
}
}
@@ -354,7 +356,7 @@
waiter.start();
waiters.add(waiter);
}
- startingGate.await(10, SECONDS);
+ startingGate.await(LONG_DELAY_MS, MILLISECONDS);
while (barrier.getNumberWaiting() < N) Thread.yield();
barrier.await();
doneSignal.countDown();
@@ -383,7 +385,7 @@
waiter.start();
waiters.add(waiter);
}
- startingGate.await(10, SECONDS);
+ startingGate.await(LONG_DELAY_MS, MILLISECONDS);
while (barrier.getNumberWaiting() < N) Thread.yield();
for (int i = 0; i < N/2; i++)
waiters.get(i).interrupt();
--- a/jdk/test/java/util/concurrent/DelayQueue/Stress.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
+import java.util.concurrent.TimeUnit;
/**
* This is not a regression test, but a stress benchmark test for
--- a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,18 +34,20 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=720 ExchangeLoops
* @summary checks to make sure a pipeline of exchangers passes data.
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class ExchangeLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static boolean print = false;
@@ -56,14 +58,14 @@
public static void main(String[] args) throws Exception {
int maxStages = 5;
- int iters = 10000;
+ int iters = 2000;
if (args.length > 0)
maxStages = Integer.parseInt(args[0]);
print = false;
System.out.println("Warmup...");
- oneRun(2, 100000);
+ oneRun(2, iters);
print = true;
for (int i = 2; i <= maxStages; i += (i+1) >>> 1) {
@@ -71,7 +73,7 @@
oneRun(i, iters);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,19 +34,21 @@
/*
* @test
* @bug 4965960
- * @run main/timeout=3600 ExecutorCompletionServiceLoops
- * @summary Exercise ExecutorCompletionServiceLoops
+ * @summary Exercise ExecutorCompletionService
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class ExecutorCompletionServiceLoops {
- static final int POOLSIZE = 100;
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+ static final int POOLSIZE = 10;
static final ExecutorService pool =
Executors.newFixedThreadPool(POOLSIZE);
static final ExecutorCompletionService<Integer> ecs =
@@ -55,23 +57,21 @@
public static void main(String[] args) throws Exception {
int max = 8;
- int base = 10000;
+ int base = 2000;
if (args.length > 0)
max = Integer.parseInt(args[0]);
System.out.println("Warmup...");
oneTest(base);
- Thread.sleep(100);
print = true;
for (int i = 1; i <= max; i += (i+1) >>> 1) {
System.out.print("n: " + i * base);
oneTest(i * base);
- Thread.sleep(100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Sat Mar 05 20:46:44 2016 -0800
@@ -24,26 +24,32 @@
/*
* @test
* @bug 6399443
+ * @summary Check for auto-shutdown and gc of singleThreadExecutors
+ * @library /lib/testlibrary/
* @run main/othervm/timeout=1000 AutoShutdown
- * @summary Check for auto-shutdown and gc of singleThreadExecutors
* @author Martin Buchholz
*/
+import static java.util.concurrent.Executors.defaultThreadFactory;
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
-import static java.util.concurrent.Executors.defaultThreadFactory;
-import static java.util.concurrent.Executors.newFixedThreadPool;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import jdk.testlibrary.Utils;
public class AutoShutdown {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void await(CountDownLatch latch) throws InterruptedException {
- if (!latch.await(100L, TimeUnit.SECONDS))
+ if (!latch.await(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out waiting for latch");
}
--- a/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,13 +34,14 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=2000 CancelledFutureLoops
* @summary Checks for responsiveness of futures to cancellation.
* Runs under the assumption that ITERS computations require more than
* TIMEOUT msecs to complete.
+ * @library /lib/testlibrary/
+ * @run main/timeout=2000 CancelledFutureLoops
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.BrokenBarrierException;
@@ -51,8 +52,10 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class CancelledFutureLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
@@ -80,7 +83,7 @@
Thread.sleep(TIMEOUT);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(6 * LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java Sat Mar 05 20:46:44 2016 -0800
@@ -36,8 +36,11 @@
* @bug 8073704
* @summary Checks that once isDone() returns true,
* get() never throws InterruptedException or TimeoutException
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -49,8 +52,11 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
+import jdk.testlibrary.Utils;
public class DoneMeansDone {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
public static void main(String[] args) throws Throwable {
final int iters = 1000;
final int nThreads = 2;
@@ -92,7 +98,7 @@
}
done.set(true);
pool.shutdown();
- if (!pool.awaitTermination(10L, TimeUnit.SECONDS))
+ if (!pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError();
for (Future<?> future : futures)
future.get();
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,14 +35,21 @@
* @test
* @bug 6725789
* @summary Check for long overflow in task time comparison.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.DAYS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class DelayOverflow {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
static void waitForNanoTimeTick() {
for (long t0 = System.nanoTime(); t0 == System.nanoTime(); )
;
@@ -52,16 +59,16 @@
Runnable r, int how) {
switch (how) {
case 0:
- pool.schedule(r, 0, TimeUnit.MILLISECONDS);
+ pool.schedule(r, 0, MILLISECONDS);
break;
case 1:
- pool.schedule(Executors.callable(r), 0, TimeUnit.DAYS);
+ pool.schedule(Executors.callable(r), 0, DAYS);
break;
case 2:
- pool.scheduleWithFixedDelay(r, 0, 1000, TimeUnit.NANOSECONDS);
+ pool.scheduleWithFixedDelay(r, 0, 1000, NANOSECONDS);
break;
case 3:
- pool.scheduleAtFixedRate(r, 0, 1000, TimeUnit.MILLISECONDS);
+ pool.scheduleAtFixedRate(r, 0, 1000, MILLISECONDS);
break;
default:
fail(String.valueOf(how));
@@ -72,16 +79,16 @@
Runnable r, int how) {
switch (how) {
case 0:
- pool.schedule(r, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+ pool.schedule(r, Long.MAX_VALUE, MILLISECONDS);
break;
case 1:
- pool.schedule(Executors.callable(r), Long.MAX_VALUE, TimeUnit.DAYS);
+ pool.schedule(Executors.callable(r), Long.MAX_VALUE, DAYS);
break;
case 2:
- pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, TimeUnit.NANOSECONDS);
+ pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, NANOSECONDS);
break;
case 3:
- pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, TimeUnit.MILLISECONDS);
+ pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, MILLISECONDS);
break;
default:
fail(String.valueOf(how));
@@ -114,14 +121,14 @@
proceedLatch.await();
} catch (Throwable t) { unexpected(t); }
}};
- pool.schedule(keepPoolBusy, 0, TimeUnit.SECONDS);
+ pool.schedule(keepPoolBusy, 0, DAYS);
busyLatch.await();
scheduleNow(pool, notifier, nowHow);
waitForNanoTimeTick();
scheduleAtTheEndOfTime(pool, neverRuns, thenHow);
proceedLatch.countDown();
- check(runLatch.await(10L, TimeUnit.SECONDS));
+ check(runLatch.await(LONG_DELAY_MS, MILLISECONDS));
equal(runLatch.getCount(), 0L);
pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
@@ -142,10 +149,9 @@
} catch (Throwable t) { unexpected(t); }
}};
pool.scheduleWithFixedDelay(scheduleNowScheduler,
- 0, Long.MAX_VALUE,
- TimeUnit.NANOSECONDS);
+ 0, Long.MAX_VALUE, NANOSECONDS);
- check(runLatch.await(10L, TimeUnit.SECONDS));
+ check(runLatch.await(LONG_DELAY_MS, MILLISECONDS));
equal(runLatch.getCount(), 0L);
pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,8 +34,11 @@
/*
* @test
* @summary Ensure that waiting pool threads don't retain refs to tasks.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.lang.ref.WeakReference;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
@@ -44,8 +47,11 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import jdk.testlibrary.Utils;
public class GCRetention {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
/**
* A custom thread pool with a custom RunnableScheduledFuture, for the
* sole purpose of ensuring that the task retains a strong reference to
@@ -116,7 +122,7 @@
Thread.sleep(10);
}
pool.shutdown();
- pool.awaitTermination(10L, TimeUnit.SECONDS);
+ pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
if (cleared < size)
throw new Error(String.format
("references to %d/%d tasks retained (\"leaked\")",
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,16 +26,21 @@
* @bug 7091003
* @summary ScheduledExecutorService never executes Runnable
* with corePoolSize of zero
+ * @library /lib/testlibrary/
* @author Chris Hegarty
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
/**
* Verify that tasks can be run even with a core pool size of 0.
*/
public class ZeroCorePoolSize {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
volatile boolean taskRun;
@@ -49,10 +54,10 @@
};
check(pool.getCorePoolSize() == 0);
- pool.schedule(task, 1, TimeUnit.SECONDS);
+ pool.schedule(task, 12L, MILLISECONDS);
pool.shutdown();
- check(pool.awaitTermination(20L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
check(pool.getCorePoolSize() == 0);
check(taskRun);
}
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,9 +35,11 @@
* @test
* @bug 8022642 8065320 8129861
* @summary Ensure relative sanity when zero core threads
+ * @library /lib/testlibrary/
*/
import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.lang.reflect.Field;
@@ -45,8 +47,28 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.BooleanSupplier;
+import jdk.testlibrary.Utils;
public class ZeroCoreThreads {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
+ static long millisElapsedSince(long startTime) {
+ return (System.nanoTime() - startTime) / (1000L * 1000L);
+ }
+
+ static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) {
+ long startTime = -1L;
+ while (!predicate.getAsBoolean()) {
+ if (startTime == -1L)
+ startTime = System.nanoTime();
+ else if (millisElapsedSince(startTime) > timeoutMillis)
+ throw new AssertionError(
+ String.format("timed out after %s ms", timeoutMillis));
+ Thread.yield();
+ }
+ }
+
static boolean hasWaiters(ReentrantLock lock, Condition condition) {
lock.lock();
try {
@@ -56,6 +78,11 @@
}
}
+ static void awaitHasWaiters(ReentrantLock lock, Condition condition,
+ long timeoutMillis) {
+ spinWaitUntil(() -> hasWaiters(lock, condition), timeoutMillis);
+ }
+
static <T> T getField(Object x, String fieldName) {
try {
Field field = x.getClass().getDeclaredField(fieldName);
@@ -72,7 +99,7 @@
test(p);
} finally {
p.shutdownNow();
- check(p.awaitTermination(10L, SECONDS));
+ check(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
}
@@ -89,13 +116,7 @@
equal(0L, p.getCompletedTaskCount());
p.schedule(dummy, 1L, HOURS);
// Ensure one pool thread actually waits in timed queue poll
- long t0 = System.nanoTime();
- while (!hasWaiters(lock, available)) {
- if (System.nanoTime() - t0 > SECONDS.toNanos(10L))
- throw new AssertionError
- ("timed out waiting for a waiter to show up");
- Thread.yield();
- }
+ awaitHasWaiters(lock, available, LONG_DELAY_MS);
equal(1, p.getPoolSize());
equal(1, p.getLargestPoolSize());
equal(1L, p.getTaskCount());
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,17 +25,22 @@
* @test
* @bug 6233235 6268386
* @summary Test allowsCoreThreadTimeOut
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class CoreThreadTimeOut {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static class IdentifiableThreadFactory implements ThreadFactory {
static ThreadFactory defaultThreadFactory
@@ -60,8 +65,8 @@
return count;
}
- static long millisElapsedSince(long t0) {
- return (System.nanoTime() - t0) / (1000L * 1000L);
+ static long millisElapsedSince(long startTime) {
+ return (System.nanoTime() - startTime) / (1000L * 1000L);
}
void test(String[] args) throws Throwable {
@@ -89,7 +94,7 @@
equal(countExecutorThreads(), 0);
tpe.shutdown();
check(tpe.allowsCoreThreadTimeOut());
- check(tpe.awaitTermination(10L, TimeUnit.SECONDS));
+ check(tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new Exception("Some tests failed");
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,9 +25,12 @@
* @test
* @bug 6277663
* @summary Test TPE extensibility framework
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
@@ -37,8 +40,11 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BooleanSupplier;
+import jdk.testlibrary.Utils;
public class Custom {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static volatile int passed = 0, failed = 0;
static void pass() { passed++; }
static void fail() { failed++; Thread.dumpStack(); }
@@ -97,6 +103,22 @@
private static final int threadCount = 10;
+ static long millisElapsedSince(long startTime) {
+ return (System.nanoTime() - startTime) / (1000L * 1000L);
+ }
+
+ static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) {
+ long startTime = -1L;
+ while (!predicate.getAsBoolean()) {
+ if (startTime == -1L)
+ startTime = System.nanoTime();
+ else if (millisElapsedSince(startTime) > timeoutMillis)
+ throw new AssertionError(
+ String.format("timed out after %s ms", timeoutMillis));
+ Thread.yield();
+ }
+ }
+
public static void main(String[] args) throws Throwable {
CustomTPE tpe = new CustomTPE();
equal(tpe.getCorePoolSize(), threadCount);
@@ -106,9 +128,8 @@
equal(countExecutorThreads(), threadCount);
equal(CustomTask.births.get(), threadCount);
tpe.shutdown();
- tpe.awaitTermination(120L, TimeUnit.SECONDS);
- Thread.sleep(1000);
- equal(countExecutorThreads(), 0);
+ tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
+ spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS);
CustomSTPE stpe = new CustomSTPE();
for (int i = 0; i < threadCount; i++)
@@ -116,9 +137,8 @@
equal(CustomSTPE.decorations.get(), threadCount);
equal(countExecutorThreads(), threadCount);
stpe.shutdown();
- stpe.awaitTermination(120L, TimeUnit.SECONDS);
- Thread.sleep(1000);
- equal(countExecutorThreads(), 0);
+ stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
+ spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS);
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new Exception("Some tests failed");
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,14 +35,20 @@
/*
* @test
* @summary Should be able to shutdown a pool when worker creation failed.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class FlakyThreadFactory {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
void test(String[] args) throws Throwable {
test(NullPointerException.class,
new ThreadFactory() {
@@ -89,7 +95,7 @@
check(exceptionClass.isInstance(t));
}
pool.shutdown();
- check(pool.awaitTermination(10L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
//--------------------- Infrastructure ---------------------------
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,14 +25,20 @@
* @test
* @bug 6576792
* @summary non-idle worker threads should not be interrupted
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class SelfInterrupt {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
void test(String[] args) throws Throwable {
final int n = 100;
final ThreadPoolExecutor pool =
@@ -58,7 +64,7 @@
} catch (Throwable t) { unexpected(t); }}});
finishLine.await();
pool.shutdown();
- check(pool.awaitTermination(1000L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
//--------------------- Infrastructure ---------------------------
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java Sat Mar 05 20:46:44 2016 -0800
@@ -36,6 +36,7 @@
* @test
* @summary Only one thread should be created when a thread needs to
* be kept alive to service a delayed task waiting in the queue.
+ * @library /lib/testlibrary/
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -44,8 +45,12 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
+import jdk.testlibrary.Utils;
public class ThreadRestarts {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+ static final long FAR_FUTURE_MS = 10 * LONG_DELAY_MS;
+
public static void main(String[] args) throws Exception {
test(false);
test(true);
@@ -56,14 +61,15 @@
ScheduledThreadPoolExecutor stpe
= new ScheduledThreadPoolExecutor(10, ctf);
try {
+ // schedule a dummy task in the "far future"
Runnable nop = new Runnable() { public void run() {}};
- stpe.schedule(nop, 10*1000L, MILLISECONDS);
+ stpe.schedule(nop, FAR_FUTURE_MS, MILLISECONDS);
stpe.setKeepAliveTime(1L, MILLISECONDS);
stpe.allowCoreThreadTimeOut(allowTimeout);
- MILLISECONDS.sleep(100L);
+ MILLISECONDS.sleep(12L);
} finally {
stpe.shutdownNow();
- if (!stpe.awaitTermination(60L, SECONDS))
+ if (!stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new AssertionError("timed out");
}
if (ctf.count.get() > 1)
@@ -76,8 +82,9 @@
final AtomicLong count = new AtomicLong(0L);
public Thread newThread(Runnable r) {
+ count.getAndIncrement();
Thread t = new Thread(r);
- count.getAndIncrement();
+ t.setDaemon(true);
return t;
}
}
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,15 +25,22 @@
* @test
* @bug 6458662
* @summary poolSize might shrink below corePoolSize after timeout
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.Utils;
public class TimeOutShrink {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+ static final long KEEPALIVE_MS = 12L;
+
static void checkPoolSizes(ThreadPoolExecutor pool,
int size, int core, int max) {
equal(pool.getPoolSize(), size);
@@ -45,7 +52,8 @@
final int n = 4;
final CyclicBarrier barrier = new CyclicBarrier(2*n+1);
final ThreadPoolExecutor pool
- = new ThreadPoolExecutor(n, 2*n, 1L, TimeUnit.SECONDS,
+ = new ThreadPoolExecutor(n, 2*n,
+ KEEPALIVE_MS, MILLISECONDS,
new SynchronousQueue<Runnable>());
final Runnable r = new Runnable() { public void run() {
try {
@@ -58,12 +66,16 @@
barrier.await();
checkPoolSizes(pool, 2*n, n, 2*n);
barrier.await();
- while (pool.getPoolSize() > n)
- Thread.sleep(100);
- Thread.sleep(100);
+ long nap = KEEPALIVE_MS + (KEEPALIVE_MS >> 2);
+ for (long sleepyTime = 0L; pool.getPoolSize() > n; ) {
+ check((sleepyTime += nap) <= LONG_DELAY_MS);
+ Thread.sleep(nap);
+ }
+ checkPoolSizes(pool, n, n, 2*n);
+ Thread.sleep(nap);
checkPoolSizes(pool, n, n, 2*n);
pool.shutdown();
- check(pool.awaitTermination(60L, TimeUnit.SECONDS));
+ check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
//--------------------- Infrastructure ---------------------------
--- a/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,9 +35,10 @@
* @test
* @bug 4486658
* @summary basic safety and liveness of ReentrantLocks, and other locks based on them
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
@@ -47,8 +48,10 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import jdk.testlibrary.Utils;
public final class CheckedLockLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
static final SplittableRandom rnd = new SplittableRandom();
@@ -63,7 +66,7 @@
oneTest(i, iters / i);
}
pool.shutdown();
- if (! pool.awaitTermination(10L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
pool = null;
}
--- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,9 +25,12 @@
* @test
* @bug 6503247 6574123
* @summary Test resilience to tryAcquire methods that throw
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
@@ -36,6 +39,7 @@
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
+import jdk.testlibrary.Utils;
/**
* This uses a variant of the standard Mutex demo, except with a
@@ -44,6 +48,7 @@
*/
@SuppressWarnings("serial")
public class FlakyMutex implements Lock {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static class MyError extends Error {}
static class MyException extends Exception {}
static class MyRuntimeException extends RuntimeException {}
@@ -91,7 +96,7 @@
} catch (Throwable t) { unexpected(t); }}});}
barrier.await();
es.shutdown();
- check(es.awaitTermination(30L, TimeUnit.SECONDS));
+ check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
private static class FlakySync extends AbstractQueuedLongSynchronizer {
--- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,9 +25,11 @@
* @test
* @bug 6460501 6236036 6500694 6490770
* @summary Repeated failed timed waits shouldn't leak memory
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -54,8 +56,11 @@
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import jdk.testlibrary.Utils;
public class TimedAcquireLeak {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
+
static String javahome() {
String jh = System.getProperty("java.home");
return (jh.endsWith("jre")) ? jh.substring(0, jh.length() - 4) : jh;
@@ -191,7 +196,7 @@
final String[] jobCmd = {
java, "-Xmx8m", "-XX:+UsePerfData",
- "-classpath", System.getProperty("test.classes", "."),
+ "-classpath", System.getProperty("test.class.path"),
childClassName, uniqueID
};
final Process p = new ProcessBuilder(jobCmd).start();
@@ -219,7 +224,7 @@
check(Math.abs(n1 - n0) < 10);
check(n1 < 25);
drainers.shutdown();
- if (!drainers.awaitTermination(10L, SECONDS)) {
+ if (!drainers.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) {
drainers.shutdownNow(); // last resort
throw new AssertionError("thread pool did not terminate");
}
--- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,11 +35,12 @@
* @test
* @bug 8074773
* @summary Stress test looks for lost unparks
+ * @library /lib/testlibrary/
* @modules java.management
- * @run main/timeout=1200 ParkLoops
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.util.SplittableRandom;
@@ -49,13 +50,12 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.locks.LockSupport;
+import jdk.testlibrary.Utils;
public final class ParkLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final int THREADS = 4;
- // static final int ITERS = 2_000_000;
- // static final int TIMEOUT = 3500; // in seconds
- static final int ITERS = 100_000;
- static final int TIMEOUT = 1000; // in seconds
+ static final int ITERS = 30_000;
static class Parker implements Runnable {
static {
@@ -130,13 +130,13 @@
pool.submit(unparker);
}
try {
- if (!done.await(TIMEOUT, SECONDS)) {
+ if (!done.await(LONG_DELAY_MS, MILLISECONDS)) {
dumpAllStacks();
throw new AssertionError("lost unpark");
}
} finally {
pool.shutdown();
- pool.awaitTermination(10L, SECONDS);
+ pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS);
}
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,25 +34,27 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=15000 LockOncePerThreadLoops
* @summary Checks for missed signals by locking and unlocking each of an array of locks once per thread
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class LockOncePerThreadLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
- static int nlocks = 50000;
- static int nthreads = 100;
- static int replications = 5;
+ static int nlocks = 20_000;
+ static int nthreads = 20;
+ static int replications = 3;
public static void main(String[] args) throws Exception {
if (args.length > 0)
@@ -66,10 +68,9 @@
for (int i = 0; i < replications; ++i) {
System.out.print("Iteration: " + i);
new ReentrantLockLoop().test();
- Thread.sleep(100);
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,23 +34,25 @@
/*
* @test
* @bug 4486658
- * @run main/timeout=4500 SimpleReentrantLockLoops
* @summary multiple threads using a single lock
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class SimpleReentrantLockLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
- static int iters = 1000000;
+ static int iters = 100_000;
public static void main(String[] args) throws Exception {
int maxThreads = 5;
@@ -66,11 +68,10 @@
while (n-- > 0) {
System.out.print("Threads: " + i);
new ReentrantLockLoop(i).test();
- Thread.sleep(100);
}
}
pool.shutdown();
- if (! pool.awaitTermination(60L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,18 +34,22 @@
/*
* @test
* @bug 4486658 5031862 8140471
- * @run main TimeoutLockLoops
* @summary Checks for responsiveness of locks to timeouts.
+ * @library /lib/testlibrary/
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
+import jdk.testlibrary.Utils;
public final class TimeoutLockLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
@@ -63,7 +67,7 @@
new ReentrantLockLoop(i).test();
}
pool.shutdown();
- if (! pool.awaitTermination(60L, TimeUnit.SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java Sat Mar 05 20:46:44 2016 -0800
@@ -25,9 +25,12 @@
* @test
* @bug 6207928 6328220 6378321 6625723
* @summary Recursive lock invariant sanity checks
+ * @library /lib/testlibrary/
* @author Martin Buchholz
*/
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -42,9 +45,11 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import jdk.testlibrary.Utils;
// I am the Cownt, and I lahve to cownt.
public class Count {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
final Random rnd = new Random();
void lock(Lock lock) {
@@ -102,7 +107,7 @@
barrier.await();
} catch (Throwable t) { unexpected(t); }}});}
es.shutdown();
- check(es.awaitTermination(10L, TimeUnit.SECONDS));
+ check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
}
void testReentrantLocks(final boolean fair,
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java Sat Mar 05 20:46:44 2016 -0800
@@ -41,17 +41,20 @@
* inserts it, and if present, with probability premove it removes
* it. (pinsert and premove are expressed as percentages to simplify
* parsing from command line.)
+ * @library /lib/testlibrary/
*/
-import static java.util.concurrent.TimeUnit.SECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.Map;
import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import jdk.testlibrary.Utils;
public class MapLoops {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final int NKEYS = 100000;
static int pinsert = 60;
static int premove = 2;
@@ -125,7 +128,7 @@
map.clear();
}
pool.shutdown();
- if (! pool.awaitTermination(10L, SECONDS))
+ if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS))
throw new Error();
}
--- a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java Sat Mar 05 20:46:44 2016 -0800
@@ -35,6 +35,7 @@
* @test
* @bug 8005697
* @summary Basic tests for StampedLock
+ * @library /lib/testlibrary/
* @author Chris Hegarty
*/
@@ -49,8 +50,10 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.StampedLock;
+import jdk.testlibrary.Utils;
public class Basic {
+ static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static void checkResult(Locker l, Class<? extends Throwable> c) {
Throwable t = l.thrown();
@@ -268,7 +271,7 @@
case 2: case 5:
return interruptibleReader(sl, -1, SECONDS, gate, view ^= true);
default:
- return interruptibleReader(sl, 30, SECONDS, gate, view ^= true); }}
+ return interruptibleReader(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
public void remove() {throw new UnsupportedOperationException();}};
}
@@ -286,7 +289,7 @@
case 2: case 5:
return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true);
default:
- return interruptibleWriter(sl, 30, SECONDS, gate, view ^= true); }}
+ return interruptibleWriter(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }}
public void remove() {throw new UnsupportedOperationException();}};
}
@@ -454,13 +457,13 @@
// We test interrupting both before and after trying to acquire
boolean view = false;
StampedLock sl = new StampedLock();
- for (long timeout : new long[] { -1L, 30L, -1L, 30L }) {
+ for (long timeout : new long[] { -1L, LONG_DELAY_MS, -1L, LONG_DELAY_MS }) {
long stamp;
Thread.State state;
stamp = sl.writeLock();
try {
- Reader r = interruptibleReader(sl, timeout, SECONDS, null, view);
+ Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
r.start();
r.interrupt();
r.join();
@@ -471,7 +474,7 @@
stamp = sl.writeLock();
try {
- Reader r = interruptibleReader(sl, timeout, SECONDS, null, view);
+ Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view);
r.start();
waitForThreadToBlock(r);
r.interrupt();
@@ -483,7 +486,7 @@
stamp = sl.readLock();
try {
- Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view);
+ Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
w.start();
w.interrupt();
w.join();
@@ -494,7 +497,7 @@
stamp = sl.readLock();
try {
- Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view);
+ Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view);
w.start();
waitForThreadToBlock(w);
w.interrupt();
@@ -509,7 +512,7 @@
check(!sl.tryUnlockRead());
check(!sl.tryUnlockWrite());
check(sl.tryOptimisticRead() != 0L);
- if (timeout == 30L)
+ if (timeout == LONG_DELAY_MS)
view = true;
}
} catch (Throwable t) { unexpected(t); }
--- a/jdk/test/java/util/concurrent/tck/Collection8Test.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java Sat Mar 05 20:46:44 2016 -0800
@@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@@ -98,26 +99,29 @@
public void testForEachConcurrentStressTest() throws Throwable {
if (!impl.isConcurrent()) return;
final Collection c = impl.emptyCollection();
- final long testDurationMillis = SHORT_DELAY_MS;
+ final long testDurationMillis = timeoutMillis();
final AtomicBoolean done = new AtomicBoolean(false);
final Object elt = impl.makeElement(1);
- ExecutorService pool = Executors.newCachedThreadPool();
- Runnable checkElt = () -> {
- while (!done.get())
- c.stream().forEach((x) -> { assertSame(x, elt); }); };
- Runnable addRemove = () -> {
- while (!done.get()) {
- assertTrue(c.add(elt));
- assertTrue(c.remove(elt));
- }};
- Future<?> f1 = pool.submit(checkElt);
- Future<?> f2 = pool.submit(addRemove);
- Thread.sleep(testDurationMillis);
- done.set(true);
- pool.shutdown();
- assertTrue(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
- assertNull(f1.get(LONG_DELAY_MS, MILLISECONDS));
- assertNull(f2.get(LONG_DELAY_MS, MILLISECONDS));
+ final Future<?> f1, f2;
+ final ExecutorService pool = Executors.newCachedThreadPool();
+ try (PoolCleaner cleaner = cleaner(pool, done)) {
+ final CountDownLatch threadsStarted = new CountDownLatch(2);
+ Runnable checkElt = () -> {
+ threadsStarted.countDown();
+ while (!done.get())
+ c.stream().forEach((x) -> { assertSame(x, elt); }); };
+ Runnable addRemove = () -> {
+ threadsStarted.countDown();
+ while (!done.get()) {
+ assertTrue(c.add(elt));
+ assertTrue(c.remove(elt));
+ }};
+ f1 = pool.submit(checkElt);
+ f2 = pool.submit(addRemove);
+ Thread.sleep(testDurationMillis);
+ }
+ assertNull(f1.get(0L, MILLISECONDS));
+ assertNull(f2.get(0L, MILLISECONDS));
}
// public void testCollection8DebugFail() { fail(); }
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Sat Mar 05 20:46:44 2016 -0800
@@ -88,6 +88,7 @@
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -210,11 +211,31 @@
private static final int suiteRuns =
Integer.getInteger("jsr166.suiteRuns", 1);
+ private static float systemPropertyValue(String name, float defaultValue) {
+ String floatString = System.getProperty(name);
+ if (floatString == null)
+ return defaultValue;
+ try {
+ return Float.parseFloat(floatString);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException(
+ String.format("Bad float value in system property %s=%s",
+ name, floatString));
+ }
+ }
+
/**
* The scaling factor to apply to standard delays used in tests.
*/
- private static final int delayFactor =
- Integer.getInteger("jsr166.delay.factor", 1);
+ private static final float delayFactor =
+ systemPropertyValue("jsr166.delay.factor", 1.0f);
+
+ /**
+ * The timeout factor as used in the jtreg test harness.
+ * See: http://openjdk.java.net/jtreg/tag-spec.html
+ */
+ private static final float jtregTestTimeoutFactor
+ = systemPropertyValue("test.timeout.factor", 1.0f);
public JSR166TestCase() { super(); }
public JSR166TestCase(String name) { super(name); }
@@ -590,10 +611,12 @@
/**
* Returns the shortest timed delay. This can be scaled up for
- * slow machines using the jsr166.delay.factor system property.
+ * slow machines using the jsr166.delay.factor system property,
+ * or via jtreg's -timeoutFactor: flag.
+ * http://openjdk.java.net/jtreg/command-help.html
*/
protected long getShortDelay() {
- return 50 * delayFactor;
+ return (long) (50 * delayFactor * jtregTestTimeoutFactor);
}
/**
@@ -906,6 +929,14 @@
}};
}
+ PoolCleaner cleaner(ExecutorService pool, AtomicBoolean flag) {
+ return new PoolCleanerWithReleaser(pool, releaser(flag));
+ }
+
+ Runnable releaser(final AtomicBoolean flag) {
+ return new Runnable() { public void run() { flag.set(true); }};
+ }
+
/**
* Waits out termination of a thread pool or fails doing so.
*/
@@ -1462,16 +1493,20 @@
return new LatchAwaiter(latch);
}
- public void await(CountDownLatch latch) {
+ public void await(CountDownLatch latch, long timeoutMillis) {
try {
- if (!latch.await(LONG_DELAY_MS, MILLISECONDS))
+ if (!latch.await(timeoutMillis, MILLISECONDS))
fail("timed out waiting for CountDownLatch for "
- + (LONG_DELAY_MS/1000) + " sec");
+ + (timeoutMillis/1000) + " sec");
} catch (Throwable fail) {
threadUnexpectedException(fail);
}
}
+ public void await(CountDownLatch latch) {
+ await(latch, LONG_DELAY_MS);
+ }
+
public void await(Semaphore semaphore) {
try {
if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS))
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -32,6 +32,7 @@
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
@@ -55,7 +56,9 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -226,52 +229,75 @@
}
/**
- * scheduleAtFixedRate executes series of tasks at given rate
+ * scheduleAtFixedRate executes series of tasks at given rate.
+ * Eventually, it must hold that:
+ * cycles - 1 <= elapsedMillis/delay < cycles
*/
public void testFixedRateSequence() throws InterruptedException {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
+ final Runnable task = new CheckedRunnable() {
public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final ScheduledFuture periodicTask =
p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (elapsedMillis <= cycles * delay)
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
}
/**
- * scheduleWithFixedDelay executes series of tasks with given period
+ * scheduleWithFixedDelay executes series of tasks with given period.
+ * Eventually, it must hold that each task starts at least delay and at
+ * most 2 * delay after the termination of the previous task.
*/
public void testFixedDelaySequence() throws InterruptedException {
final CustomExecutor p = new CustomExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final AtomicLong previous = new AtomicLong(startTime);
+ final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
- public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final int d = delay;
+ final Runnable task = new CheckedRunnable() {
+ public void realRun() {
+ long now = System.nanoTime();
+ long elapsedMillis
+ = NANOSECONDS.toMillis(now - previous.get());
+ if (done.getCount() == cycles) { // first execution
+ if (elapsedMillis >= d)
+ tryLongerDelay.set(true);
+ } else {
+ assertTrue(elapsedMillis >= d);
+ if (elapsedMillis >= 2 * d)
+ tryLongerDelay.set(true);
+ }
+ previous.set(now);
+ done.countDown();
+ }};
+ final ScheduledFuture periodicTask =
p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (!tryLongerDelay.get())
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -34,6 +34,7 @@
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.ArrayList;
@@ -52,7 +53,9 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -170,52 +173,75 @@
}
/**
- * scheduleAtFixedRate executes series of tasks at given rate
+ * scheduleAtFixedRate executes series of tasks at given rate.
+ * Eventually, it must hold that:
+ * cycles - 1 <= elapsedMillis/delay < cycles
*/
public void testFixedRateSequence() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
+ final Runnable task = new CheckedRunnable() {
public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final ScheduledFuture periodicTask =
p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (elapsedMillis <= cycles * delay)
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
}
/**
- * scheduleWithFixedDelay executes series of tasks with given period
+ * scheduleWithFixedDelay executes series of tasks with given period.
+ * Eventually, it must hold that each task starts at least delay and at
+ * most 2 * delay after the termination of the previous task.
*/
public void testFixedDelaySequence() throws InterruptedException {
final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try (PoolCleaner cleaner = cleaner(p)) {
for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) {
- long startTime = System.nanoTime();
- int cycles = 10;
+ final long startTime = System.nanoTime();
+ final AtomicLong previous = new AtomicLong(startTime);
+ final AtomicBoolean tryLongerDelay = new AtomicBoolean(false);
+ final int cycles = 8;
final CountDownLatch done = new CountDownLatch(cycles);
- Runnable task = new CheckedRunnable() {
- public void realRun() { done.countDown(); }};
- ScheduledFuture h =
+ final int d = delay;
+ final Runnable task = new CheckedRunnable() {
+ public void realRun() {
+ long now = System.nanoTime();
+ long elapsedMillis
+ = NANOSECONDS.toMillis(now - previous.get());
+ if (done.getCount() == cycles) { // first execution
+ if (elapsedMillis >= d)
+ tryLongerDelay.set(true);
+ } else {
+ assertTrue(elapsedMillis >= d);
+ if (elapsedMillis >= 2 * d)
+ tryLongerDelay.set(true);
+ }
+ previous.set(now);
+ done.countDown();
+ }};
+ final ScheduledFuture periodicTask =
p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS);
- await(done);
- h.cancel(true);
- double normalizedTime =
- (double) millisElapsedSince(startTime) / delay;
- if (normalizedTime >= cycles - 1 &&
- normalizedTime <= cycles)
+ final int totalDelayMillis = (cycles - 1) * delay;
+ await(done, totalDelayMillis + cycles * LONG_DELAY_MS);
+ periodicTask.cancel(true);
+ final long elapsedMillis = millisElapsedSince(startTime);
+ assertTrue(elapsedMillis >= totalDelayMillis);
+ if (!tryLongerDelay.get())
return;
+ // else retry with longer delay
}
fail("unexpected execution rate");
}
--- a/jdk/test/java/util/concurrent/tck/ThreadTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/concurrent/tck/ThreadTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -77,7 +77,7 @@
*/
public void testGetAndSetDefaultUncaughtExceptionHandler() {
assertEquals(null, Thread.getDefaultUncaughtExceptionHandler());
- // failure due to securityException is OK.
+ // failure due to SecurityException is OK.
// Would be nice to explicitly test both ways, but cannot yet.
Thread.UncaughtExceptionHandler defaultHandler
= Thread.getDefaultUncaughtExceptionHandler();
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java Sat Mar 05 20:46:44 2016 -0800
@@ -39,9 +39,9 @@
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import jdk.Version;
import static java.util.jar.JarFile.Release;
-import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -50,6 +50,9 @@
public class MultiReleaseJarAPI {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
String userdir = System.getProperty("user.dir",".");
File unversioned = new File(userdir, "unversioned.jar");
File multirelease = new File(userdir, "multi-release.jar");
@@ -106,7 +109,7 @@
}
// assure that we have a Release object corresponding to the actual runtime version
- String version = "VERSION_" + jdkMajorVersion();
+ String version = "VERSION_" + MAJOR_VERSION;
boolean runtimeVersionExists = false;
for (Release value : values) {
if (version.equals(value.name())) runtimeVersionExists = true;
@@ -123,7 +126,7 @@
if (name.equals("BASE")) {
prefix = "";
} else if (name.equals("RUNTIME")) {
- prefix = "META-INF/versions/" + jdkMajorVersion() + "/";
+ prefix = "META-INF/versions/" + MAJOR_VERSION + "/";
} else {
prefix = "META-INF/versions/" + name.substring(8) + "/";
}
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java Sat Mar 05 20:46:44 2016 -0800
@@ -42,9 +42,9 @@
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.zip.ZipFile;
+import jdk.Version;
import static java.util.jar.JarFile.Release;
-import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -53,6 +53,9 @@
public class MultiReleaseJarIterators {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
String userdir = System.getProperty("user.dir", ".");
File unversioned = new File(userdir, "unversioned.jar");
File multirelease = new File(userdir, "multi-release.jar");
@@ -121,7 +124,7 @@
try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
Map<String,JarEntry> expectedEntries;
- switch (jdkMajorVersion()) {
+ switch (MAJOR_VERSION) {
case 9:
expectedEntries = v9Entries;
break;
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java Sat Mar 05 20:46:44 2016 -0800
@@ -54,8 +54,7 @@
import java.nio.file.Files;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-
-import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
+import jdk.Version;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -63,6 +62,9 @@
import org.testng.annotations.Test;
public class MultiReleaseJarProperties {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
final static int ROOTVERSION = 8; // magic number from knowledge of internals
final static String userdir = System.getProperty("user.dir", ".");
final static File multirelease = new File(userdir, "multi-release.jar");
@@ -77,14 +79,14 @@
creator.compileEntries();
creator.buildMultiReleaseJar();
- rtVersion = Integer.getInteger("jdk.util.jar.version", jdkMajorVersion());
+ rtVersion = Integer.getInteger("jdk.util.jar.version", MAJOR_VERSION);
String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", "");
if (mrprop.equals("false")) {
rtVersion = ROOTVERSION;
} else if (rtVersion < ROOTVERSION) {
rtVersion = ROOTVERSION;
- } else if (rtVersion > jdkMajorVersion()) {
- rtVersion = jdkMajorVersion();
+ } else if (rtVersion > MAJOR_VERSION) {
+ rtVersion = MAJOR_VERSION;
}
force = mrprop.equals("force");
--- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java Sat Mar 05 20:46:44 2016 -0800
@@ -40,6 +40,7 @@
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;
+import jdk.Version;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -47,6 +48,9 @@
import org.testng.annotations.Test;
public class MultiReleaseJarSecurity {
+
+ static final int MAJOR_VERSION = Version.current().major();
+
String userdir = System.getProperty("user.dir",".");
File multirelease = new File(userdir, "multi-release.jar");
File signedmultirelease = new File(userdir, "signed-multi-release.jar");
@@ -68,9 +72,8 @@
@Test
public void testCertsAndSigners() throws IOException {
try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) {
- int version = sun.misc.Version.jdkMajorVersion(); // fixme JEP 223 Version
CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class"));
- CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + version + "/version/Version.class"));
+ CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + MAJOR_VERSION + "/version/Version.class"));
Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates()));
Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners()));
}
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java Sat Mar 05 20:46:44 2016 -0800
@@ -126,6 +126,9 @@
() -> Spliterators.spliterator(isl.iterator(), doubles.length, 0)));
spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0)));
+ spliterators.add(splitDescr("DoubleStream.iterate(0,x->x<l;x->x+1):" + name,
+ () -> DoubleStream.iterate(0.0, x -> x < doubles.length, x -> x + 1.0)
+ .spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java Sat Mar 05 20:46:44 2016 -0800
@@ -136,6 +136,8 @@
() -> IntStream.range(0, ints.length).spliterator()));
spliterators.add(splitDescr("IntStream.intRangeClosed(0,l):" + name,
() -> IntStream.rangeClosed(0, ints.length).spliterator()));
+ spliterators.add(splitDescr("IntStream.iterate(0,x->x<l,x->x+1): " + name,
+ () -> IntStream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java Sat Mar 05 20:46:44 2016 -0800
@@ -136,6 +136,9 @@
() -> LongStream.range(0, longs.length).spliterator()));
spliterators.add(splitDescr("LongStream.longRangeClosed(0,l):" + name,
() -> LongStream.rangeClosed(0, longs.length).spliterator()));
+ spliterators.add(splitDescr("LongStream.iterate(0,x->x<l;x->x+1):" + name,
+ () -> LongStream.iterate(0L, x -> x < longs.length, x -> x + 1L)
+ .spliterator()));
// Need more!
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java Sat Mar 05 20:46:44 2016 -0800
@@ -171,6 +171,8 @@
() -> Spliterators.spliterator(Arrays.asList(ints).iterator(), ints.length, 0)));
spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator()):" + name,
() -> Spliterators.spliteratorUnknownSize(Arrays.asList(ints).iterator(), 0)));
+ spliterators.add(splitDescr("Stream.iterate(0,x->x<l,x->x+1): " + name,
+ () -> Stream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator()));
// @@@ Add map and collection spliterators when spliterator() is exposed on Collection or Iterable
}
spliteratorTestData = spliterators.toArray(new Object[0][]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, 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 8072727
+ */
+
+package org.openjdk.tests.java.util.stream;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.OpTestCase;
+import java.util.stream.Stream;
+import java.util.stream.TestData;
+import java.util.stream.TestData.Factory;
+
+import static java.util.stream.ThowableHelper.checkNPE;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+@Test
+public class IterateTest extends OpTestCase {
+
+ @DataProvider(name = "IterateStreamsData")
+ public static Object[][] makeIterateStreamsTestData() {
+ Object[][] data = {
+ {List.of(),
+ Factory.ofSupplier("ref.empty", () -> Stream.iterate(1, x -> x < 0, x -> x * 2))},
+ {List.of(1),
+ Factory.ofSupplier("ref.one", () -> Stream.iterate(1, x -> x < 2, x -> x * 2))},
+ {List.of(1, 2, 4, 8, 16, 32, 64, 128, 256, 512),
+ Factory.ofSupplier("ref.ten", () -> Stream.iterate(1, x -> x < 1000, x -> x * 2))},
+ {List.of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0),
+ Factory.ofSupplier("ref.nullCheck", () -> Stream.iterate(10, Objects::nonNull, x -> x > 0 ? x - 1 : null))},
+ {List.of(),
+ Factory.ofIntSupplier("int.empty", () -> IntStream.iterate(1, x -> x < 0, x -> x + 1))},
+ {List.of(1),
+ Factory.ofIntSupplier("int.one", () -> IntStream.iterate(1, x -> x < 2, x -> x + 1))},
+ {List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+ Factory.ofIntSupplier("int.ten", () -> IntStream.iterate(1, x -> x <= 10, x -> x + 1))},
+ {List.of(5, 4, 3, 2, 1),
+ Factory.ofIntSupplier("int.divZero", () -> IntStream.iterate(5, x -> x != 0, x -> x - 1/x/2 - 1))},
+ {List.of(),
+ Factory.ofLongSupplier("long.empty", () -> LongStream.iterate(1L, x -> x < 0, x -> x + 1))},
+ {List.of(1L),
+ Factory.ofLongSupplier("long.one", () -> LongStream.iterate(1L, x -> x < 2, x -> x + 1))},
+ {List.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L),
+ Factory.ofLongSupplier("long.ten", () -> LongStream.iterate(1L, x -> x <= 10, x -> x + 1))},
+ {List.of(),
+ Factory.ofDoubleSupplier("double.empty", () -> DoubleStream.iterate(1.0, x -> x < 0, x -> x + 1))},
+ {List.of(1.0),
+ Factory.ofDoubleSupplier("double.one", () -> DoubleStream.iterate(1.0, x -> x < 2, x -> x + 1))},
+ {List.of(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0),
+ Factory.ofDoubleSupplier("double.ten", () -> DoubleStream.iterate(1.0, x -> x <= 10, x -> x + 1))}
+ };
+ return data;
+ }
+
+ @Test(dataProvider = "IterateStreamsData")
+ public <T> void testIterate(List<T> expected, TestData<T, ?> data) {
+ withData(data).stream(s -> s).expectedResult(expected).exercise();
+ }
+
+ @Test
+ public void testNPE() {
+ checkNPE(() -> Stream.iterate("", null, x -> x + "a"));
+ checkNPE(() -> Stream.iterate("", String::isEmpty, null));
+ checkNPE(() -> IntStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> IntStream.iterate(0, x -> x < 10, null));
+ checkNPE(() -> LongStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> LongStream.iterate(0, x -> x < 10, null));
+ checkNPE(() -> DoubleStream.iterate(0, null, x -> x + 1));
+ checkNPE(() -> DoubleStream.iterate(0, x -> x < 10, null));
+ }
+}
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -24,7 +24,7 @@
/*
* @test
* @summary close handlers and closing streams
- * @bug 8044047
+ * @bug 8044047 8147505
*/
package org.openjdk.tests.java.util.stream;
@@ -37,6 +37,7 @@
import static java.util.stream.LambdaTestHelpers.countTo;
import static java.util.stream.ThowableHelper.checkNPE;
+import static java.util.stream.ThowableHelper.checkISE;
@Test(groups = { "serialization-hostile" })
public class StreamCloseTest extends OpTestCase {
@@ -170,4 +171,21 @@
for (int i=0; i<n-1; i++)
assertTrue(e.getSuppressed()[i].getMessage().equals(String.valueOf(i + 2)));
}
+
+ public void testConsumed() {
+ try(Stream<Integer> s = countTo(100).stream()) {
+ s.forEach(i -> {});
+ // Adding onClose handler when stream is consumed is illegal
+ // handler must not be registered
+ checkISE(() -> s.onClose(() -> fail("1")));
+ }
+
+ // close() must be idempotent:
+ // second close() invoked at the end of try-with-resources must have no effect
+ try(Stream<Integer> s = countTo(100).stream()) {
+ s.close();
+ // Adding onClose handler when stream is closed is also illegal
+ checkISE(() -> s.onClose(() -> fail("3")));
+ }
+ }
}
--- a/jdk/test/java/util/zip/TestLocalTime.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/java/util/zip/TestLocalTime.java Sat Mar 05 20:46:44 2016 -0800
@@ -24,7 +24,6 @@
/*
* @test
* @bug 8075526 8135108
- * @key intermittent
* @summary Test timestamp via ZipEntry.get/setTimeLocal()
*/
--- a/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,6 @@
import java.lang.ref.WeakReference;
import java.net.URL;
-import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Map;
import javax.management.Attribute;
@@ -70,16 +69,16 @@
+ " some little extra check of Descriptors, MBean*Info.");
ClassLoader myClassLoader = MXBeanLoadingTest1.class.getClassLoader();
+ if(myClassLoader == null)
+ throw new RuntimeException("Test Failed : Null Classloader for test");
+ URL url = myClassLoader.getResource(
+ MXBeanLoadingTest1.class.getCanonicalName()
+ .replace(".", "/") + ".class");
+ String clsLoadPath = url.toURI().toString().
+ replaceAll(MXBeanLoadingTest1.class.getSimpleName()
+ + ".class", "");
- if (!(myClassLoader instanceof URLClassLoader)) {
- String message = "(ERROR) Test's class loader is not " +
- "a URLClassLoader";
- System.out.println(message);
- throw new RuntimeException(message);
- }
-
- URLClassLoader myURLClassLoader = (URLClassLoader) myClassLoader;
- URL[] urls = myURLClassLoader.getURLs();
+ URL[] urls = new URL[]{new URL(clsLoadPath)};
PrivateMLet mlet = new PrivateMLet(urls, null, false);
Class<?> shadowClass = mlet.loadClass(TestMXBean.class.getName());
--- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -44,7 +44,7 @@
import org.testng.annotations.*;
public class MultiReleaseJarTest {
- final private int MAJOR_VERSION= Version.current().major();
+ final private int MAJOR_VERSION = Version.current().major();
final private String userdir = System.getProperty("user.dir",".");
final private Map<String,String> stringEnv = new HashMap<>();
--- a/jdk/test/sun/misc/Version/Version.java Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2010, 2015, 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 6994413 8134365
- * @summary Check the JDK and JVM version returned by sun.misc.Version
- * matches the versions defined in the system properties.
- * Should use the API described in JDK-8136651 when available
- * @modules java.base/sun.misc
- * @compile -XDignore.symbol.file Version.java
- * @run main Version
- */
-
-import static sun.misc.Version.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class Version {
-
- public static void main(String[] args) throws Exception {
- VersionInfo jdk = newVersionInfo(System.getProperty("java.runtime.version"));
- VersionInfo v1 = new VersionInfo(jdkMajorVersion(),
- jdkMinorVersion(),
- jdkSecurityVersion(),
- jdkPatchVersion(),
- jdkBuildNumber());
- System.out.println("JDK version = " + jdk + " " + v1);
- if (!jdk.equals(v1)) {
- throw new RuntimeException("Unmatched version: " + jdk + " vs " + v1);
- }
- VersionInfo jvm = newVersionInfo(System.getProperty("java.vm.version"));
- VersionInfo v2 = new VersionInfo(jvmMajorVersion(),
- jvmMinorVersion(),
- jvmSecurityVersion(),
- jvmPatchVersion(),
- jvmBuildNumber());
- System.out.println("JVM version = " + jvm + " " + v2);
- if (!jvm.equals(v2)) {
- throw new RuntimeException("Unmatched version: " + jvm + " vs " + v2);
- }
- }
-
- static class VersionInfo {
- final int major;
- final int minor;
- final int security;
- final int patch;
- final int build;
- VersionInfo(int major, int minor, int security,
- int patch, int build) {
- this.major = major;
- this.minor = minor;
- this.security = security;
- this.patch = patch;
- this.build = build;
- }
-
- VersionInfo(int[] fields) {
- this.major = fields[0];
- this.minor = fields[1];
- this.security = fields[2];
- this.patch = fields[3];
- this.build = fields[4];
- }
-
- public boolean equals(VersionInfo v) {
- return (this.major == v.major && this.minor == v.minor &&
- this.security == v.security && this.patch == v.patch &&
- this.build == v.build);
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- // Do not include trailing zeros
- if (patch > 0) {
- sb.insert(0, "." + patch);
- }
- if (security > 0 || sb.length() > 0) {
- sb.insert(0, "." + security);
- }
- if (minor > 0 || sb.length() > 0) {
- sb.insert(0, "." + minor);
- }
- sb.insert(0, major);
-
- if (build >= 0)
- sb.append("+" + build);
-
- return sb.toString();
- }
- }
-
- private static VersionInfo newVersionInfo(String version) throws Exception {
- // Version string fromat as defined by JEP-223
- String jep223Pattern =
- "^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?(\\.([0-9]+))?" + // $VNUM
- "(-([a-zA-Z]+))?(\\.([a-zA-Z]+))?" + // $PRE
- "(\\+([0-9]+))?" + // Build Number
- "(([-a-zA-Z0-9.]+))?$"; // $OPT
-
- // Pattern group index for: Major, Minor, Security, Patch, Build
- int[] groups = {1, 3, 5, 7, 13};
- // Default values for Major, Minor, Security, Patch, Build
- int[] versionFields = {0, 0, 0, 0, 0};
-
- Pattern pattern = Pattern.compile(jep223Pattern);
- Matcher matcher = pattern.matcher(version);
- if (matcher.matches()) {
- for (int i = 0; i < versionFields.length; i++) {
- String field = matcher.group(groups[i]);
- versionFields[i] = (field != null) ? Integer.parseInt(field) : 0;
- }
- }
-
- VersionInfo vi = new VersionInfo(versionFields);
- System.out.printf("newVersionInfo: input=%s output=%s\n", version, vi);
- return vi;
- }
-}
--- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java Sat Mar 05 20:46:44 2016 -0800
@@ -42,27 +42,40 @@
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class MultiReleaseJarURLConnection {
String userdir = System.getProperty("user.dir",".");
- String urlFile = "jar:file:" + userdir + "/multi-release.jar!/";
- String urlEntry = urlFile + "version/Version.java";
+ String file = userdir + "/signed-multi-release.jar";
@BeforeClass
public void initialize() throws Exception {
CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
creator.compileEntries();
creator.buildMultiReleaseJar();
+ creator.buildSignedMultiReleaseJar();
}
@AfterClass
public void close() throws IOException {
Files.delete(Paths.get(userdir, "multi-release.jar"));
+ Files.delete(Paths.get(userdir, "signed-multi-release.jar"));
}
- @Test
- public void testRuntimeVersioning() throws Exception {
+ @DataProvider(name = "data")
+ public Object[][] createData() {
+ return new Object[][]{
+ {"unsigned file", userdir + "/multi-release.jar"},
+ {"signed file", userdir + "/signed-multi-release.jar"},
+ };
+ }
+
+ @Test(dataProvider = "data")
+ public void testRuntimeVersioning(String ignore, String file) throws Exception {
+ String urlFile = "jar:file:" + file + "!/";
+ String urlEntry = urlFile + "version/Version.java";
+
Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
// #runtime is "magic"
Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9"));
@@ -72,8 +85,10 @@
Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
}
- @Test
- public void testCachedJars() throws Exception {
+ @Test(dataProvider = "data")
+ public void testCachedJars(String ignore, String file) throws Exception {
+ String urlFile = "jar:file:" + file + "!/";
+
URL rootUrl = new URL(urlFile);
JarURLConnection juc = (JarURLConnection)rootUrl.openConnection();
JarFile rootJar = juc.getJarFile();
--- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
/*
* @test
* @bug 8075286
+ * @key intermittent
* @summary Verify that DSAGenParameterSpec can and can only be used to generate
* DSA within some certain range of key sizes as described in the class
* specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and
--- a/jdk/test/sun/security/rsa/SpecTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/sun/security/rsa/SpecTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
/**
* @test
* @bug 8044199
+ * @key intermittent
* @summary Check same KeyPair's private key and public key have same modulus.
* also check public key's public exponent equals to given spec's public
* exponent.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8148108
+ * @summary Disable Diffie-Hellman keys less than 1024 bits
+ * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy LegacyDHEKeyExchange
+ */
+
+import java.io.*;
+import javax.net.ssl.*;
+
+public class LegacyDHEKeyExchange {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = false;
+
+ /*
+ * Where do we find the keystores?
+ */
+ static String pathToStores = "../../../../javax/net/ssl/etc";
+ static String keyStoreFile = "keystore";
+ static String trustStoreFile = "truststore";
+ static String passwd = "passphrase";
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * If the client or server is doing some kind of object creation
+ * that the other side depends on, and that thread prematurely
+ * exits, you may experience a hang. The test harness will
+ * terminate all hung threads after its timeout has expired,
+ * currently 3 minutes by default, but you might try to be
+ * smart about it....
+ */
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLServerSocketFactory sslssf =
+ (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+
+ throw new Exception(
+ "Leagcy DH keys (< 1024) should be restricted");
+ } catch (SSLHandshakeException she) {
+ // ignore, client should terminate the connection
+ } finally {
+ sslServerSocket.close();
+ }
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLSocketFactory sslsf =
+ (SSLSocketFactory) SSLSocketFactory.getDefault();
+ SSLSocket sslSocket = (SSLSocket)
+ sslsf.createSocket("localhost", serverPort);
+
+ String[] suites = new String [] {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"};
+ sslSocket.setEnabledCipherSuites(suites);
+
+ try {
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+
+ throw new Exception("Leagcy DH keys (< 1024) should be restricted");
+ } catch (SSLHandshakeException she) {
+ // ignore, should be caused by algorithm constraints
+ } finally {
+ sslSocket.close();
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+ String keyFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", ".") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ System.setProperty("javax.net.ssl.keyStore", keyFilename);
+ System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+ System.setProperty("javax.net.ssl.trustStore", trustFilename);
+ System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+ if (debug) {
+ System.setProperty("javax.net.debug", "all");
+ }
+
+ /*
+ * Start the tests.
+ */
+ new LegacyDHEKeyExchange();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ LegacyDHEKeyExchange() throws Exception {
+ Exception startException = null;
+ try {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+ } catch (Exception e) {
+ startException = e;
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ if (serverThread != null) {
+ serverThread.join();
+ }
+ } else {
+ if (clientThread != null) {
+ clientThread.join();
+ }
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ * Which side threw the error?
+ */
+ Exception local;
+ Exception remote;
+
+ if (separateServerThread) {
+ remote = serverException;
+ local = clientException;
+ } else {
+ remote = clientException;
+ local = serverException;
+ }
+
+ Exception exception = null;
+
+ /*
+ * Check various exception conditions.
+ */
+ if ((local != null) && (remote != null)) {
+ // If both failed, return the curthread's exception.
+ local.initCause(remote);
+ exception = local;
+ } else if (local != null) {
+ exception = local;
+ } else if (remote != null) {
+ exception = remote;
+ } else if (startException != null) {
+ exception = startException;
+ }
+
+ /*
+ * If there was an exception *AND* a startException,
+ * output it.
+ */
+ if (exception != null) {
+ if (exception != startException && startException != null) {
+ exception.addSuppressed(startException);
+ }
+ throw exception;
+ }
+
+ // Fall-through: no exception to throw!
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ serverException = e;
+ } finally {
+ serverReady = true;
+ }
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ clientException = e;
+ }
+ }
+ }
+}
--- a/jdk/test/tools/jar/JarEntryTime.java Sat Mar 05 10:10:20 2016 +0100
+++ b/jdk/test/tools/jar/JarEntryTime.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, 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
@@ -31,6 +31,8 @@
import java.io.File;
import java.io.PrintWriter;
import java.nio.file.attribute.FileTime;
+import java.util.Date;
+import java.util.TimeZone;
import sun.tools.jar.Main;
public class JarEntryTime {
@@ -39,6 +41,9 @@
// allow for e.g. rounding/truncation and networked/samba drives.
static final long PRECISION = 10000L;
+ static final TimeZone TZ = TimeZone.getDefault();
+ static final boolean DST = TZ.inDaylightTime(new Date());
+
static boolean cleanup(File dir) throws Throwable {
boolean rc = true;
File[] x = dir.listFiles();
@@ -75,11 +80,13 @@
File dirOuter = new File("outer");
File dirInner = new File(dirOuter, "inner");
File jarFile = new File("JarEntryTime.jar");
+ File testFile = new File("JarEntryTimeTest.txt");
// Remove any leftovers from prior run
cleanup(dirInner);
cleanup(dirOuter);
jarFile.delete();
+ testFile.delete();
/* Create a directory structure
* outer/
@@ -129,23 +136,39 @@
check(cleanup(dirInner));
check(cleanup(dirOuter));
+ try (PrintWriter pw = new PrintWriter(testFile)) {
+ pw.println("hello, world");
+ }
+ final long start = testFile.lastModified();
+
// Extract and check the last modified values are the current times.
// See sun.tools.jar.Main
extractJar(jarFile, true);
+
+ try (PrintWriter pw = new PrintWriter(testFile)) {
+ pw.println("hello, world");
+ }
+ final long end = testFile.lastModified();
+
check(dirOuter.exists());
check(dirInner.exists());
check(fileInner.exists());
- checkFileTime(dirOuter.lastModified(), now);
- checkFileTime(dirInner.lastModified(), now);
- checkFileTime(fileInner.lastModified(), now);
+ checkFileTime(start, dirOuter.lastModified(), end);
+ checkFileTime(start, dirInner.lastModified(), end);
+ checkFileTime(start, fileInner.lastModified(), end);
check(cleanup(dirInner));
check(cleanup(dirOuter));
check(jarFile.delete());
+ check(testFile.delete());
}
static void checkFileTime(long now, long original) {
+ if (isTimeSettingChanged()) {
+ return;
+ }
+
if (Math.abs(now - original) > PRECISION) {
System.out.format("Extracted to %s, expected to be close to %s%n",
FileTime.fromMillis(now), FileTime.fromMillis(original));
@@ -153,6 +176,27 @@
}
}
+ static void checkFileTime(long start, long now, long end) {
+ if (isTimeSettingChanged()) {
+ return;
+ }
+
+ if (now < start || now > end) {
+ System.out.format("Extracted to %s, "
+ + "expected to be after %s and before %s%n",
+ FileTime.fromMillis(now),
+ FileTime.fromMillis(start),
+ FileTime.fromMillis(end));
+ fail();
+ }
+ }
+
+ private static boolean isTimeSettingChanged() {
+ TimeZone currentTZ = TimeZone.getDefault();
+ boolean currentDST = currentTZ.inDaylightTime(new Date());
+ return (!currentTZ.equals(TZ) || currentDST != DST);
+ }
+
//--------------------- Infrastructure ---------------------------
static volatile int passed = 0, failed = 0;
static void pass() {passed++;}
--- a/langtools/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -349,3 +349,4 @@
3f60a4808377a276f6398ff19e61c1b9086f4d97 jdk-9+104
81bd82222f8a1f2b291a44a49e063973caa4e73b jdk-9+105
dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106
+7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107
--- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,7 @@
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.HashMap;
-import java.util.Locale;
import java.util.Map;
-import java.util.logging.Logger;
-import java.util.logging.Level;
-
-import static java.util.logging.Level.*;
/**
* Provides methods for locating tool providers, for example,
@@ -45,47 +40,6 @@
*/
public class ToolProvider {
- private static final String propertyName = "sun.tools.ToolProvider";
- private static final String loggerName = "javax.tools";
-
- /*
- * Define the system property "sun.tools.ToolProvider" to enable
- * debugging:
- *
- * java ... -Dsun.tools.ToolProvider ...
- */
- static <T> T trace(Level level, Object reason) {
- // NOTE: do not make this method private as it affects stack traces
- try {
- if (System.getProperty(propertyName) != null) {
- StackTraceElement[] st = Thread.currentThread().getStackTrace();
- String method = "???";
- String cls = ToolProvider.class.getName();
- if (st.length > 2) {
- StackTraceElement frame = st[2];
- method = String.format((Locale)null, "%s(%s:%s)",
- frame.getMethodName(),
- frame.getFileName(),
- frame.getLineNumber());
- cls = frame.getClassName();
- }
- Logger logger = Logger.getLogger(loggerName);
- if (reason instanceof Throwable) {
- logger.logp(level, cls, method,
- reason.getClass().getName(), (Throwable)reason);
- } else {
- logger.logp(level, cls, method, String.valueOf(reason));
- }
- }
- } catch (SecurityException ex) {
- System.err.format((Locale)null, "%s: %s; %s%n",
- ToolProvider.class.getName(),
- reason,
- ex.getLocalizedMessage());
- }
- return null;
- }
-
private static final String systemJavaCompilerName
= "com.sun.tools.javac.api.JavacTool";
@@ -153,7 +107,7 @@
try {
return c.asSubclass(clazz).newInstance();
} catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) {
- return trace(WARNING, e);
+ throw new Error(e);
}
}
@@ -164,7 +118,7 @@
try {
c = Class.forName(name, false, ClassLoader.getSystemClassLoader());
} catch (ClassNotFoundException | RuntimeException | Error e) {
- return trace(WARNING, e);
+ throw new Error(e);
}
toolClasses.put(name, new WeakReference<>(c));
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -155,8 +155,6 @@
allowDefaultMethods = source.allowDefaultMethods();
allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
sourceName = source.name;
- relax = (options.isSet("-retrofit") ||
- options.isSet("-relax"));
useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
@@ -168,10 +166,6 @@
recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
}
- /** Switch: relax some constraints for retrofit mode.
- */
- boolean relax;
-
/** Switch: support target-typing inference
*/
boolean allowPoly;
@@ -1025,8 +1019,7 @@
log.error(tree.pos(),
"default.allowed.in.intf.annotation.member");
}
- if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 &&
- !relax)
+ if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0)
log.error(tree.pos(), "missing.meth.body.or.decl.abstract");
} else if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) {
if ((owner.flags() & INTERFACE) != 0) {
@@ -4384,8 +4377,7 @@
// If this is a non-abstract class, check that it has no abstract
// methods or unimplemented methods of an implemented interface.
if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) {
- if (!relax)
- chk.checkAllDefined(tree.pos(), c);
+ chk.checkAllDefined(tree.pos(), c);
}
if ((c.flags() & ANNOTATION) != 0) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Sat Mar 05 20:46:44 2016 -0800
@@ -81,8 +81,6 @@
private final Types types;
private final TypeAnnotations typeAnnotations;
private final JCDiagnostic.Factory diags;
- private boolean warnOnSyntheticConflicts;
- private boolean suppressAbortOnBadClassFile;
private final JavaFileManager fileManager;
private final Source source;
private final Profile profile;
@@ -130,8 +128,6 @@
allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
allowPrivateSafeVarargs = source.allowPrivateSafeVarargs();
allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation();
- warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
- suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers");
Target target = Target.instance(context);
@@ -269,8 +265,7 @@
*/
public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, "cant.access", ex.sym, ex.getDetailValue());
- if (ex instanceof ClassFinder.BadClassFile
- && !suppressAbortOnBadClassFile) throw new Abort();
+ if (ex instanceof ClassFinder.BadClassFile) throw new Abort();
else return syms.errType;
}
@@ -2632,12 +2627,7 @@
*/
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
if (!sym.type.isErroneous()) {
- if (warnOnSyntheticConflicts) {
- log.warning(pos, "synthetic.name.conflict", sym, sym.location());
- }
- else {
- log.error(pos, "synthetic.name.conflict", sym, sym.location());
- }
+ log.error(pos, "synthetic.name.conflict", sym, sym.location());
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -44,9 +44,11 @@
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
-import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -353,9 +355,9 @@
rsContext.attrMode(),
rsContext.step,
round);
- File dotFile = new File(dependenciesFolder, filename);
- try (FileWriter fw = new FileWriter(dotFile)) {
- fw.append(graph);
+ Path dotFile = Paths.get(dependenciesFolder, filename);
+ try (Writer w = Files.newBufferedWriter(dotFile)) {
+ w.append(graph);
}
round++;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Sat Mar 05 20:46:44 2016 -0800
@@ -267,7 +267,14 @@
* @return true if successful, and false otherwise
*/
public boolean handleOption(Option option, String value) {
- return locations.handleOption(option, value);
+ switch (option) {
+ case ENCODING:
+ encodingName = value;
+ return true;
+
+ default:
+ return locations.handleOption(option, value);
+ }
}
/**
@@ -285,6 +292,7 @@
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Encoding">
+ private String encodingName;
private String defaultEncodingName;
private String getDefaultEncodingName() {
if (defaultEncodingName == null) {
@@ -295,11 +303,7 @@
}
public String getEncodingName() {
- String encName = options.get(Option.ENCODING);
- if (encName == null)
- return getDefaultEncodingName();
- else
- return encName;
+ return (encodingName != null) ? encodingName : getDefaultEncodingName();
}
@SuppressWarnings("cast")
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Sat Mar 05 20:46:44 2016 -0800
@@ -425,7 +425,7 @@
if (container.endsWith("bootmodules.jimage")) {
System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:");
container = Locations.JRT_MARKER_FILE;
- } else if (container.getFileName().toString().endsWith(".jimage")) {
+ } else if (container.getNameCount() > 0 && container.getFileName().toString().endsWith(".jimage")) {
System.err.println("Warning: reference to " + container + " ignored");
return;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -72,18 +72,6 @@
*/
private boolean verbose;
- /** Switch: scramble private field names.
- */
- private boolean scramble;
-
- /** Switch: scramble all field names.
- */
- private boolean scrambleAll;
-
- /** Switch: retrofit mode.
- */
- private boolean retrofit;
-
/** Switch: emit source file attribute.
*/
private boolean emitSourceFile;
@@ -184,9 +172,6 @@
signatureGen = new CWSignatureGenerator(types);
verbose = options.isSet(VERBOSE);
- scramble = options.isSet("-scramble");
- scrambleAll = options.isSet("-scrambleAll");
- retrofit = options.isSet("-retrofit");
genCrt = options.isSet(XJCOV);
debugstackmap = options.isSet("debugstackmap");
@@ -491,26 +476,11 @@
putChar(poolbuf, poolCountIdx, pool.pp);
}
- /** Given a field, return its name.
- */
- Name fieldName(Symbol sym) {
- if (scramble && (sym.flags() & PRIVATE) != 0 ||
- scrambleAll && (sym.flags() & (PROTECTED | PUBLIC)) == 0)
- return names.fromString("_$" + sym.name.getIndex());
- else
- return sym.name;
- }
-
/** Given a symbol, return its name-and-type.
*/
NameAndType nameType(Symbol sym) {
- return new NameAndType(fieldName(sym),
- retrofit
- ? sym.erasure(types)
- : sym.externalType(types), types);
- // if we retrofit, then the NameAndType has been read in as is
- // and no change is necessary. If we compile normally, the
- // NameAndType is generated from a symbol reference, and the
+ return new NameAndType(sym.name, sym.externalType(types), types);
+ // the NameAndType is generated from a symbol reference, and the
// adjustment of adding an additional this$n parameter needs to be made.
}
@@ -1055,10 +1025,10 @@
databuf.appendChar(flags);
if (dumpFieldModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
- pw.println("FIELD " + fieldName(v));
+ pw.println("FIELD " + v.name);
pw.println("---" + flagNames(v.flags()));
}
- databuf.appendChar(pool.put(fieldName(v)));
+ databuf.appendChar(pool.put(v.name));
databuf.appendChar(pool.put(typeSig(v.erasure(types))));
int acountIdx = beginAttrs();
int acount = 0;
@@ -1079,10 +1049,10 @@
databuf.appendChar(flags);
if (dumpMethodModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
- pw.println("METHOD " + fieldName(m));
+ pw.println("METHOD " + m.name);
pw.println("---" + flagNames(m.flags()));
}
- databuf.appendChar(pool.put(fieldName(m)));
+ databuf.appendChar(pool.put(m.name));
databuf.appendChar(pool.put(typeSig(m.externalType(types))));
int acountIdx = beginAttrs();
int acount = 0;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -120,25 +120,11 @@
: options.isSet(G_CUSTOM, "vars");
genCrt = options.isSet(XJCOV);
debugCode = options.isSet("debugcode");
- allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
allowBetterNullChecks = target.hasObjects();
pool = new Pool(types);
// ignore cldc because we cannot have both stackmap formats
this.stackMap = StackMapFormat.JSR202;
-
- // by default, avoid jsr's for simple finalizers
- int setjsrlimit = 50;
- String jsrlimitString = options.get("jsrlimit");
- if (jsrlimitString != null) {
- try {
- setjsrlimit = Integer.parseInt(jsrlimitString);
- } catch (NumberFormatException ex) {
- // ignore ill-formed numbers for jsrlimit
- }
- }
- this.jsrlimit = setjsrlimit;
- this.useJsrLocally = false; // reset in visitTry
annotate = Annotate.instance(context);
}
@@ -148,19 +134,8 @@
private final boolean varDebugInfo;
private final boolean genCrt;
private final boolean debugCode;
- private final boolean allowInvokedynamic;
private final boolean allowBetterNullChecks;
- /** Default limit of (approximate) size of finalizer to inline.
- * Zero means always use jsr. 100 or greater means never use
- * jsr.
- */
- private final int jsrlimit;
-
- /** True if jsr is used.
- */
- private boolean useJsrLocally;
-
/** Code buffer, set by genMethod.
*/
private Code code;
@@ -1339,31 +1314,11 @@
// in a new environment which calls the finally block if there is one.
final Env<GenContext> tryEnv = env.dup(tree, new GenContext());
final Env<GenContext> oldEnv = env;
- if (!useJsrLocally) {
- useJsrLocally =
- (stackMap == StackMapFormat.NONE) &&
- (jsrlimit <= 0 ||
- jsrlimit < 100 &&
- estimateCodeComplexity(tree.finalizer)>jsrlimit);
- }
tryEnv.info.finalize = new GenFinalizer() {
void gen() {
- if (useJsrLocally) {
- if (tree.finalizer != null) {
- Code.State jsrState = code.state.dup();
- jsrState.push(Code.jsrReturnValue);
- tryEnv.info.cont =
- new Chain(code.emitJump(jsr),
- tryEnv.info.cont,
- jsrState);
- }
- Assert.check(tryEnv.info.gaps.length() % 2 == 0);
- tryEnv.info.gaps.append(code.curCP());
- } else {
- Assert.check(tryEnv.info.gaps.length() % 2 == 0);
- tryEnv.info.gaps.append(code.curCP());
- genLast();
- }
+ Assert.check(tryEnv.info.gaps.length() % 2 == 0);
+ tryEnv.info.gaps.append(code.curCP());
+ genLast();
}
void genLast() {
if (tree.finalizer != null)
@@ -1568,93 +1523,6 @@
}
}
- /** Very roughly estimate the number of instructions needed for
- * the given tree.
- */
- int estimateCodeComplexity(JCTree tree) {
- if (tree == null) return 0;
- class ComplexityScanner extends TreeScanner {
- int complexity = 0;
- public void scan(JCTree tree) {
- if (complexity > jsrlimit) return;
- super.scan(tree);
- }
- public void visitClassDef(JCClassDecl tree) {}
- public void visitDoLoop(JCDoWhileLoop tree)
- { super.visitDoLoop(tree); complexity++; }
- public void visitWhileLoop(JCWhileLoop tree)
- { super.visitWhileLoop(tree); complexity++; }
- public void visitForLoop(JCForLoop tree)
- { super.visitForLoop(tree); complexity++; }
- public void visitSwitch(JCSwitch tree)
- { super.visitSwitch(tree); complexity+=5; }
- public void visitCase(JCCase tree)
- { super.visitCase(tree); complexity++; }
- public void visitSynchronized(JCSynchronized tree)
- { super.visitSynchronized(tree); complexity+=6; }
- public void visitTry(JCTry tree)
- { super.visitTry(tree);
- if (tree.finalizer != null) complexity+=6; }
- public void visitCatch(JCCatch tree)
- { super.visitCatch(tree); complexity+=2; }
- public void visitConditional(JCConditional tree)
- { super.visitConditional(tree); complexity+=2; }
- public void visitIf(JCIf tree)
- { super.visitIf(tree); complexity+=2; }
- // note: for break, continue, and return we don't take unwind() into account.
- public void visitBreak(JCBreak tree)
- { super.visitBreak(tree); complexity+=1; }
- public void visitContinue(JCContinue tree)
- { super.visitContinue(tree); complexity+=1; }
- public void visitReturn(JCReturn tree)
- { super.visitReturn(tree); complexity+=1; }
- public void visitThrow(JCThrow tree)
- { super.visitThrow(tree); complexity+=1; }
- public void visitAssert(JCAssert tree)
- { super.visitAssert(tree); complexity+=5; }
- public void visitApply(JCMethodInvocation tree)
- { super.visitApply(tree); complexity+=2; }
- public void visitNewClass(JCNewClass tree)
- { scan(tree.encl); scan(tree.args); complexity+=2; }
- public void visitNewArray(JCNewArray tree)
- { super.visitNewArray(tree); complexity+=5; }
- public void visitAssign(JCAssign tree)
- { super.visitAssign(tree); complexity+=1; }
- public void visitAssignop(JCAssignOp tree)
- { super.visitAssignop(tree); complexity+=2; }
- public void visitUnary(JCUnary tree)
- { complexity+=1;
- if (tree.type.constValue() == null) super.visitUnary(tree); }
- public void visitBinary(JCBinary tree)
- { complexity+=1;
- if (tree.type.constValue() == null) super.visitBinary(tree); }
- public void visitTypeTest(JCInstanceOf tree)
- { super.visitTypeTest(tree); complexity+=1; }
- public void visitIndexed(JCArrayAccess tree)
- { super.visitIndexed(tree); complexity+=1; }
- public void visitSelect(JCFieldAccess tree)
- { super.visitSelect(tree);
- if (tree.sym.kind == VAR) complexity+=1; }
- public void visitIdent(JCIdent tree) {
- if (tree.sym.kind == VAR) {
- complexity+=1;
- if (tree.type.constValue() == null &&
- tree.sym.owner.kind == TYP)
- complexity+=1;
- }
- }
- public void visitLiteral(JCLiteral tree)
- { complexity+=1; }
- public void visitTree(JCTree tree) {}
- public void visitWildcard(JCWildcard tree) {
- throw new AssertionError(this.getClass().getName());
- }
- }
- ComplexityScanner scanner = new ComplexityScanner();
- tree.accept(scanner);
- return scanner.complexity;
- }
-
public void visitIf(JCIf tree) {
int limit = code.nextreg;
Chain thenExit = null;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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,9 +25,10 @@
package com.sun.tools.javac.main;
-import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
@@ -73,7 +74,7 @@
private String ownName;
private Set<String> classNames;
- private Set<File> files;
+ private Set<Path> files;
private Map<Option, String> deferredFileManagerOptions;
private Set<JavaFileObject> fileObjects;
private final Options options;
@@ -153,8 +154,8 @@
}
@Override
- public void addFile(File f) {
- files.add(f);
+ public void addFile(Path p) {
+ files.add(p);
}
@Override
@@ -252,7 +253,7 @@
} else {
fileObjects = new LinkedHashSet<>();
JavacFileManager jfm = (JavacFileManager) getFileManager();
- for (JavaFileObject fo: jfm.getJavaFileObjectsFromFiles(files))
+ for (JavaFileObject fo: jfm.getJavaFileObjectsFromPaths(files))
fileObjects.add(fo);
}
}
@@ -583,8 +584,8 @@
if (value == null) {
return true;
}
- File file = new File(value);
- if (file.exists() && !file.isDirectory()) {
+ Path file = Paths.get(value);
+ if (Files.exists(file) && !Files.isDirectory(file)) {
error("err.file.not.directory", value);
return false;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -27,9 +27,10 @@
import java.io.IOException;
import java.io.Reader;
-import java.io.FileReader;
-import java.io.BufferedReader;
import java.io.StreamTokenizer;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
import com.sun.tools.javac.util.ListBuffer;
/**
@@ -73,7 +74,7 @@
private static void loadCmdFile(String name, ListBuffer<String> args)
throws IOException
{
- try (Reader r = new BufferedReader(new FileReader(name))) {
+ try (Reader r = Files.newBufferedReader(Paths.get(name))) {
StreamTokenizer st = new StreamTokenizer(r);
st.resetSyntax();
st.wordChars(' ', 255);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Sat Mar 05 20:46:44 2016 -0800
@@ -389,10 +389,6 @@
verbose = options.isSet(VERBOSE);
sourceOutput = options.isSet(PRINTSOURCE); // used to be -s
- stubOutput = options.isSet("-stubs");
- relax = options.isSet("-relax");
- printFlat = options.isSet("-printflat");
- encoding = options.get(ENCODING);
lineDebugInfo = options.isUnset(G_CUSTOM) ||
options.isSet(G_CUSTOM, "lines");
genEndPos = options.isSet(XJCOV) ||
@@ -447,21 +443,6 @@
*/
public boolean sourceOutput;
- /** Emit stub source files rather than class files.
- */
- public boolean stubOutput;
-
- /** Switch: relax some constraints for producing the jsr14 prototype.
- */
- boolean relax;
-
- /** Debug switch: Emit Java sources after inner class flattening.
- */
- public boolean printFlat;
-
- /** The encoding to be used for source input.
- */
- public String encoding;
/** Generate code with the LineNumberTable attribute for debugging
*/
@@ -611,7 +592,7 @@
// where
public boolean keepComments = false;
protected boolean keepComments() {
- return keepComments || sourceOutput || stubOutput;
+ return keepComments || sourceOutput;
}
@@ -676,30 +657,6 @@
}
}
- /** Emit plain Java source for a class.
- * @param env The attribution environment of the outermost class
- * containing this class.
- * @param cdef The class definition to be printed.
- */
- JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
- JavaFileObject outFile
- = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
- cdef.sym.flatname.toString(),
- JavaFileObject.Kind.SOURCE,
- null);
- if (inputFiles.contains(outFile)) {
- log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile);
- return null;
- } else {
- try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) {
- new Pretty(out, true).printUnit(env.toplevel, cdef);
- if (verbose)
- log.printVerbose("wrote.file", outFile);
- }
- return outFile;
- }
- }
-
/** Generate code and emit a class file for a given class
* @param env The attribution environment of the outermost class
* containing this class.
@@ -720,6 +677,30 @@
return null;
}
+ /** Emit plain Java source for a class.
+ * @param env The attribution environment of the outermost class
+ * containing this class.
+ * @param cdef The class definition to be printed.
+ */
+ JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
+ JavaFileObject outFile
+ = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
+ cdef.sym.flatname.toString(),
+ JavaFileObject.Kind.SOURCE,
+ null);
+ if (inputFiles.contains(outFile)) {
+ log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile);
+ return null;
+ } else {
+ try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) {
+ new Pretty(out, true).printUnit(env.toplevel, cdef);
+ if (verbose)
+ log.printVerbose("wrote.file", outFile);
+ }
+ return outFile;
+ }
+ }
+
/** Compile a source file that has been accessed by the class finder.
* @param c The class the source file of which needs to be compiled.
*/
@@ -898,12 +879,6 @@
}
/**
- * Set needRootClasses to true, in JavaCompiler subclass constructor
- * that want to collect public apis of classes supplied on the command line.
- */
- protected boolean needRootClasses = false;
-
- /**
* The list of classes explicitly supplied on the command line for compilation.
* Not always populated.
*/
@@ -966,7 +941,7 @@
// If generating source, or if tracking public apis,
// then remember the classes declared in
// the original compilation units listed on the command line.
- if (needRootClasses || sourceOutput || stubOutput) {
+ if (sourceOutput) {
ListBuffer<JCClassDecl> cdefs = new ListBuffer<>();
for (JCCompilationUnit unit : roots) {
for (List<JCTree> defs = unit.defs;
@@ -1275,11 +1250,6 @@
if (shouldStop(CompileState.FLOW))
return;
- if (relax) {
- results.add(env);
- return;
- }
-
if (verboseCompilePolicy)
printNote("[flow " + env.enclClass.sym + "]");
JavaFileObject prev = log.useSource(
@@ -1419,9 +1389,9 @@
TreeMaker localMake = make.forToplevel(env.toplevel);
if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) {
- if (!(stubOutput || sourceOutput || printFlat)) {
+ if (!(sourceOutput)) {
if (shouldStop(CompileState.LOWER))
- return;
+ return;
List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake);
if (pdef.head != null) {
Assert.check(pdef.tail.isEmpty());
@@ -1431,19 +1401,6 @@
return;
}
- if (stubOutput) {
- //emit stub Java source file, only for compilation
- //units enumerated explicitly on the command line
- JCClassDecl cdef = (JCClassDecl)env.tree;
- if (untranslated instanceof JCClassDecl &&
- rootClasses.contains((JCClassDecl)untranslated) &&
- ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
- cdef.sym.packge().getQualifiedName() == names.java_lang)) {
- results.add(new Pair<>(env, removeMethodBodies(cdef)));
- }
- return;
- }
-
if (shouldStop(CompileState.TRANSTYPES))
return;
@@ -1504,16 +1461,12 @@
if (shouldStop(CompileState.GENERATE))
return;
- boolean usePrintSource = (stubOutput || sourceOutput || printFlat);
-
for (Pair<Env<AttrContext>, JCClassDecl> x: queue) {
Env<AttrContext> env = x.fst;
JCClassDecl cdef = x.snd;
if (verboseCompilePolicy) {
- printNote("[generate "
- + (usePrintSource ? " source" : "code")
- + " " + cdef.sym + "]");
+ printNote("[generate " + (sourceOutput ? " source" : "code") + " " + cdef.sym + "]");
}
if (!taskListener.isEmpty()) {
@@ -1526,9 +1479,9 @@
env.toplevel.sourcefile);
try {
JavaFileObject file;
- if (usePrintSource)
+ if (sourceOutput) {
file = printSource(env, cdef);
- else {
+ } else {
if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT)
&& jniWriter.needsHeader(cdef.sym)) {
jniWriter.write(cdef.sym);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, 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,9 +25,11 @@
package com.sun.tools.javac.main;
-import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
@@ -238,13 +240,7 @@
IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"),
- ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) {
- @Override
- public boolean process(OptionHelper helper, String option, String operand) {
- return super.process(helper, option, operand);
- }
-
- },
+ ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER),
SOURCE("-source", "opt.arg.release", "opt.source", STANDARD, BASIC) {
@Override
@@ -537,16 +533,16 @@
@Override
public boolean process(OptionHelper helper, String option) {
if (option.endsWith(".java") ) {
- File f = new File(option);
- if (!f.exists()) {
- helper.error("err.file.not.found", f);
+ Path p = Paths.get(option);
+ if (!Files.exists(p)) {
+ helper.error("err.file.not.found", p);
return true;
}
- if (!f.isFile()) {
- helper.error("err.file.not.file", f);
+ if (!Files.isRegularFile(p)) {
+ helper.error("err.file.not.file", p);
return true;
}
- helper.addFile(f);
+ helper.addFile(p);
} else {
helper.addClassName(option);
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, 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,9 +25,10 @@
package com.sun.tools.javac.main;
+import java.nio.file.Path;
+
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.PrefixKind;
-import java.io.File;
/**
* Helper object to be used by {@link Option#process}, providing access to
@@ -63,7 +64,7 @@
abstract void error(String key, Object... args);
/** Record a file to be compiled. */
- abstract void addFile(File f);
+ abstract void addFile(Path p);
/** Record the name of a class for annotation processing. */
abstract void addClassName(String s);
@@ -112,8 +113,8 @@
}
@Override
- public void addFile(File f) {
- throw new IllegalArgumentException(f.getPath());
+ public void addFile(Path p) {
+ throw new IllegalArgumentException(p.toString());
}
@Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Sat Mar 05 20:46:44 2016 -0800
@@ -981,10 +981,6 @@
compiler.err.synthetic.name.conflict=\
the symbol {0} conflicts with a compiler-synthesized symbol in {1}
-# 0: symbol, 1: symbol
-compiler.warn.synthetic.name.conflict=\
- the symbol {0} conflicts with a compiler-synthesized symbol in {1}
-
compiler.err.throws.not.allowed.in.intf.annotation=\
throws clause not allowed in @interface members
@@ -1334,16 +1330,6 @@
compiler.misc.verbose.wrote.file=\
[wrote {0}]
-## extra output when using -verbose (Retro)
-compiler.misc.verbose.retro=\
- [retrofitting {0}]
-
-compiler.misc.verbose.retro.with=\
- \tretrofitting {0} with {1}
-
-compiler.misc.verbose.retro.with.list=\
- \tretrofitting {0} with type parameters {1}, supertype {2}, interfaces {3}
-
## extra output when using -verbose (code/ClassReader)
# 0: string
compiler.misc.verbose.loading=\
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Sat Mar 05 20:46:44 2016 -0800
@@ -124,20 +124,12 @@
Don't accept generics in the language
javac.opt.moreinfo=\
Print extended information for type variables
-javac.opt.printflat=\
- Print abstract syntax tree after inner class conversion
javac.opt.printsearch=\
Print information where classfiles are searched
javac.opt.prompt=\
Stop after each error
-javac.opt.retrofit=\
- Retrofit existing classfiles with generic types
javac.opt.s=\
Emit java sources instead of classfiles
-javac.opt.scramble=\
- Scramble private identifiers in bytecode
-javac.opt.scrambleall=\
- Scramble package visible identifiers in bytecode
javac.opt.version=\
Version information
javac.opt.arg.pathname=\
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -170,12 +170,6 @@
}
},
- new HiddenOption(false, "-stubs") {
- void process(JavahTask task, String opt, String arg) {
- // ignored; for backwards compatibility
- }
- },
-
new Option(false, "-v", "-verbose") {
void process(JavahTask task, String opt, String arg) {
task.verbose = true;
@@ -454,8 +448,6 @@
if (llni)
g = new LLNI(doubleAlign, util);
else {
-// if (stubs)
-// throw new BadArgs("jni.no.stubs");
g = new JNI(util);
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Sat Mar 05 20:46:44 2016 -0800
@@ -75,9 +75,7 @@
Map<String, PubApi> dependencyPublicApis,
int debugLevel,
boolean incremental,
- int numCores,
- Writer out,
- Writer err) {
+ int numCores) {
boolean rc = true;
for (String pkgName : pkgSrcs.keySet()) {
String pkgNameF = pkgName.replace('.',File.separatorChar);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Sat Mar 05 20:46:44 2016 -0800
@@ -42,6 +42,8 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
import com.sun.tools.sjavac.comp.CompilationService;
import com.sun.tools.sjavac.options.Options;
@@ -89,9 +91,7 @@
final Map<String, PubApi> dependencyPubapis,
int debugLevel,
boolean incremental,
- int numCores,
- final Writer out,
- final Writer err) {
+ int numCores) {
Log.debug("Performing CompileJavaPackages transform...");
@@ -219,7 +219,9 @@
}
String chunkId = id + "-" + String.valueOf(i);
+ Log log = Log.get();
compilationCalls.add(() -> {
+ Log.setLogForCurrentThread(log);
CompilationSubResult result = sjavac.compile("n/a",
chunkId,
args.prepJavacArgs(),
@@ -227,8 +229,8 @@
cc.srcs,
visibleSources);
synchronized (lock) {
- safeWrite(result.stdout, out);
- safeWrite(result.stderr, err);
+ Util.getLines(result.stdout).forEach(Log::info);
+ Util.getLines(result.stderr).forEach(Log::error);
}
return result;
});
@@ -246,8 +248,10 @@
subResults.add(fut.get());
} catch (ExecutionException ee) {
Log.error("Compilation failed: " + ee.getMessage());
- } catch (InterruptedException ee) {
- Log.error("Compilation interrupted: " + ee.getMessage());
+ Log.error(ee);
+ } catch (InterruptedException ie) {
+ Log.error("Compilation interrupted: " + ie.getMessage());
+ Log.error(ie);
Thread.currentThread().interrupt();
}
}
@@ -292,16 +296,6 @@
return rc;
}
- private void safeWrite(String str, Writer w) {
- if (str.length() > 0) {
- try {
- w.write(str);
- } catch (IOException e) {
- Log.error("Could not print compilation output.");
- }
- }
- }
-
/**
* Split up the sources into compile chunks. If old package dependents information
* is available, sort the order of the chunks into the most dependent first!
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Sat Mar 05 20:46:44 2016 -0800
@@ -83,9 +83,7 @@
Map<String, PubApi> dependencyPublicApis,
int debugLevel,
boolean incremental,
- int numCores,
- Writer out,
- Writer err) {
+ int numCores) {
boolean rc = true;
for (String pkgName : pkgSrcs.keySet()) {
String pkgNameF = Util.toFileSystemPath(pkgName);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Sat Mar 05 20:46:44 2016 -0800
@@ -70,9 +70,7 @@
Map<String, PubApi> dependencyPubapis,
int debugLevel,
boolean incremental,
- int numCores,
- Writer out,
- Writer err)
+ int numCores)
{
boolean rc = true;
String dest_filename;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Sat Mar 05 20:46:44 2016 -0800
@@ -123,16 +123,11 @@
// Setup transform that always exist.
private CompileJavaPackages compileJavaPackages = new CompileJavaPackages();
- // Where to send stdout and stderr.
- private Writer out, err;
-
// Command line options.
private Options options;
- JavacState(Options op, boolean removeJavacState, Writer o, Writer e) {
+ JavacState(Options op, boolean removeJavacState) {
options = op;
- out = o;
- err = e;
numCores = options.getNumCores();
theArgs = options.getStateArgsString();
binDir = Util.pathToFile(options.getDestDir());
@@ -294,8 +289,8 @@
/**
* Load a javac_state file.
*/
- public static JavacState load(Options options, Writer out, Writer err) {
- JavacState db = new JavacState(options, false, out, err);
+ public static JavacState load(Options options) {
+ JavacState db = new JavacState(options, false);
Module lastModule = null;
Package lastPackage = null;
Source lastSource = null;
@@ -367,22 +362,22 @@
noFileFound = true;
} catch (IOException e) {
Log.info("Dropping old javac_state because of errors when reading it.");
- db = new JavacState(options, true, out, err);
+ db = new JavacState(options, true);
foundCorrectVerNr = true;
newCommandLine = false;
syntaxError = false;
}
if (foundCorrectVerNr == false && !noFileFound) {
Log.info("Dropping old javac_state since it is of an old version.");
- db = new JavacState(options, true, out, err);
+ db = new JavacState(options, true);
} else
if (newCommandLine == true && !noFileFound) {
Log.info("Dropping old javac_state since a new command line is used!");
- db = new JavacState(options, true, out, err);
+ db = new JavacState(options, true);
} else
if (syntaxError == true) {
Log.info("Dropping old javac_state since it contains syntax errors.");
- db = new JavacState(options, true, out, err);
+ db = new JavacState(options, true);
}
db.prev.calculateDependents();
return db;
@@ -812,9 +807,7 @@
dependencyPublicApis,
0,
isIncremental(),
- numCores,
- out,
- err);
+ numCores);
if (!r)
rc = false;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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,24 @@
package com.sun.tools.sjavac;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.io.Writer;
+import java.util.Locale;
/**
* Utility class only for sjavac logging.
- * The log level can be set using for example --log=DEBUG on the sjavac command line.
+ *
+ * Logging in sjavac has special requirements when running in server/client
+ * mode. Most of the log messages is generated server-side, but the server
+ * is typically spawned by the client in the background, so the user usually
+ * does not see the server stdout/stderr. For this reason log messages needs
+ * to relayed back to the client that performed the request that generated the
+ * log message. To support this use case this class maintains a per-thread log
+ * instance so that each connected client can have its own instance that
+ * relays messages back to the requesting client.
+ *
+ * On the client-side (or when running sjavac without server-mode) there will
+ * typically just be one Log instance.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
@@ -38,61 +51,94 @@
* deletion without notice.</b>
*/
public class Log {
- private static PrintWriter out, err;
+
+ public enum Level {
+ ERROR,
+ WARN,
+ INFO,
+ DEBUG,
+ TRACE;
+ }
+
+ private static Log stdOutErr = new Log(new PrintWriter(System.out), new PrintWriter(System.err));
+ private static ThreadLocal<Log> loggers = new ThreadLocal<>();
+
+ protected PrintWriter err; // Used for error and warning messages
+ protected PrintWriter out; // Used for other messages
+ protected Level level = Level.INFO;
- public final static int WARN = 1;
- public final static int INFO = 2;
- public final static int DEBUG = 3;
- public final static int TRACE = 4;
- private static int level = WARN;
+ public Log(Writer out, Writer err) {
+ this.out = out == null ? null : new PrintWriter(out, true);
+ this.err = err == null ? null : new PrintWriter(err, true);
+ }
+
+ public static void setLogForCurrentThread(Log log) {
+ loggers.set(log);
+ }
+
+ public static void setLogLevel(String l) {
+ setLogLevel(Level.valueOf(l.toUpperCase(Locale.US)));
+ }
+
+ public static void setLogLevel(Level l) {
+ get().level = l;
+ }
static public void trace(String msg) {
- if (level >= TRACE) {
- out.println(msg);
- }
+ log(Level.TRACE, msg);
}
static public void debug(String msg) {
- if (level >= DEBUG) {
- out.println(msg);
- }
+ log(Level.DEBUG, msg);
}
static public void info(String msg) {
- if (level >= INFO) {
- out.println(msg);
- }
+ log(Level.INFO, msg);
}
static public void warn(String msg) {
- err.println(msg);
+ log(Level.WARN, msg);
}
static public void error(String msg) {
- err.println(msg);
+ log(Level.ERROR, msg);
}
- static public void initializeLog(Writer o, Writer e) {
- out = new PrintWriter(o);
- err = new PrintWriter(e);
+ static public void error(Throwable t) {
+ log(Level.ERROR, t);
}
- static public void setLogLevel(String l) {
- switch (l) {
- case "warn": level = WARN; break;
- case "info": level = INFO; break;
- case "debug": level = DEBUG; break;
- case "trace": level = TRACE; break;
- default:
- throw new IllegalArgumentException("No such log level \"" + l + "\"");
- }
+ static public void log(Level l, String msg) {
+ get().printLogMsg(l, msg);
}
- static public boolean isTracing() {
- return level >= TRACE;
+ public static void debug(Throwable t) {
+ log(Level.DEBUG, t);
+ }
+
+ public static void log(Level l, Throwable t) {
+ StringWriter sw = new StringWriter();
+ t.printStackTrace(new PrintWriter(sw, true));
+ log(l, sw.toString());
}
static public boolean isDebugging() {
- return level >= DEBUG;
+ return get().isLevelLogged(Level.DEBUG);
+ }
+
+ protected boolean isLevelLogged(Level l) {
+ return l.ordinal() <= level.ordinal();
+ }
+
+ public static Log get() {
+ Log log = loggers.get();
+ return log != null ? log : stdOutErr;
+ }
+
+ protected void printLogMsg(Level msgLevel, String msg) {
+ if (isLevelLogged(msgLevel)) {
+ PrintWriter pw = msgLevel.ordinal() <= Level.WARN.ordinal() ? err : out;
+ pw.println(msg);
+ }
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Sat Mar 05 20:46:44 2016 -0800
@@ -95,9 +95,7 @@
Map<String, PubApi> dependencyApis,
int debugLevel,
boolean incremental,
- int numCores,
- Writer out,
- Writer err);
+ int numCores);
void setExtra(String e);
void setExtra(Options args);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Sat Mar 05 20:46:44 2016 -0800
@@ -36,7 +36,9 @@
import java.util.Set;
import java.util.StringTokenizer;
import java.util.function.Function;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Utilities.
@@ -236,4 +238,10 @@
int dotIndex = fileNameStr.indexOf('.');
return dotIndex == -1 ? "" : fileNameStr.substring(dotIndex);
}
+
+ public static Stream<String> getLines(String str) {
+ return str.isEmpty()
+ ? Stream.empty()
+ : Stream.of(str.split(Pattern.quote(System.lineSeparator())));
+ }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Sat Mar 05 20:46:44 2016 -0800
@@ -51,7 +51,7 @@
public static int run(String[] args, Writer out, Writer err) {
- Log.initializeLog(out, err);
+ Log.setLogForCurrentThread(new Log(out, err));
Options options;
try {
@@ -61,6 +61,8 @@
return -1;
}
+ Log.setLogLevel(options.getLogLevel());
+
Log.debug("==========================================================");
Log.debug("Launching sjavac client with the following parameters:");
Log.debug(" " + options.getStateArgsString());
@@ -68,24 +70,15 @@
// Prepare sjavac object
boolean useServer = options.getServerConf() != null;
- Sjavac sjavac;
- // Create an sjavac implementation to be used for compilation
- if (useServer) {
- try {
- sjavac = new SjavacClient(options);
- } catch (PortFileInaccessibleException e) {
- Log.error("Port file inaccessible.");
- return -1;
- }
- } else {
- sjavac = new SjavacImpl();
- }
+ Sjavac sjavac = useServer ? new SjavacClient(options) : new SjavacImpl();
- int rc = sjavac.compile(args, out, err);
+ // Perform compilation
+ int rc = sjavac.compile(args);
// If sjavac is running in the foreground we should shut it down at this point
- if (!useServer)
+ if (!useServer) {
sjavac.shutdown();
+ }
return rc;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
+import java.io.Reader;
import java.io.Writer;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -40,6 +41,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
+import java.util.stream.Stream;
import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.Util;
@@ -50,6 +52,8 @@
import com.sun.tools.sjavac.server.Sjavac;
import com.sun.tools.sjavac.server.SjavacServer;
+import static java.util.stream.Collectors.joining;
+
/**
* Sjavac implementation that delegates requests to a SjavacServer.
*
@@ -64,8 +68,6 @@
// JavaCompiler instance for several compiles using the same id.
private final String id;
private final PortFile portFile;
- private final String logfile;
- private final String stdouterrfile;
// Default keepalive for server is 120 seconds.
// I.e. it will accept 120 seconds of inactivity before quitting.
@@ -86,7 +88,7 @@
// Store the server conf settings here.
private final String settings;
- public SjavacClient(Options options) throws PortFileInaccessibleException {
+ public SjavacClient(Options options) {
String tmpServerConf = options.getServerConf();
String serverConf = (tmpServerConf!=null)? tmpServerConf : "";
String tmpId = Util.extractStringOption("id", serverConf);
@@ -96,14 +98,7 @@
.toAbsolutePath()
.toString();
String portfileName = Util.extractStringOption("portfile", serverConf, defaultPortfile);
- try {
- portFile = SjavacServer.getPortFile(portfileName);
- } catch (PortFileInaccessibleException e) {
- Log.error("Port file inaccessable: " + e);
- throw e;
- }
- logfile = Util.extractStringOption("logfile", serverConf, portfileName + ".javaclog");
- stdouterrfile = Util.extractStringOption("stdouterrfile", serverConf, portfileName + ".stdouterr");
+ portFile = SjavacServer.getPortFile(portfileName);
sjavacForkCmd = Util.extractStringOption("sjavac", serverConf, "sjavac");
int poolsize = Util.extractIntOption("poolsize", serverConf);
keepalive = Util.extractIntOption("keepalive", serverConf, 120);
@@ -121,7 +116,7 @@
}
@Override
- public int compile(String[] args, Writer stdout, Writer stderr) {
+ public int compile(String[] args) {
int result = -1;
try (Socket socket = tryConnect()) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
@@ -136,32 +131,36 @@
// Read server response line by line
String line;
while (null != (line = in.readLine())) {
+ if (!line.contains(":")) {
+ throw new AssertionError("Could not parse protocol line: >>\"" + line + "\"<<");
+ }
String[] typeAndContent = line.split(":", 2);
String type = typeAndContent[0];
String content = typeAndContent[1];
- switch (type) {
- case SjavacServer.LINE_TYPE_STDOUT:
- stdout.write(content);
- stdout.write('\n');
- break;
- case SjavacServer.LINE_TYPE_STDERR:
- stderr.write(content);
- stderr.write('\n');
- break;
- case SjavacServer.LINE_TYPE_RC:
+
+ try {
+ Log.log(Log.Level.valueOf(type), "[server] " + content);
+ continue;
+ } catch (IllegalArgumentException e) {
+ // Parsing of 'type' as log level failed.
+ }
+
+ if (type.equals(SjavacServer.LINE_TYPE_RC)) {
result = Integer.parseInt(content);
- break;
}
}
+ } catch (PortFileInaccessibleException e) {
+ Log.error("Port file inaccessible.");
+ result = CompilationSubResult.ERROR_FATAL;
} catch (IOException ioe) {
- Log.error("[CLIENT] Exception caught: " + ioe);
+ Log.error("IOException caught during compilation: " + ioe.getMessage());
+ Log.debug(ioe);
result = CompilationSubResult.ERROR_FATAL;
- ioe.printStackTrace(new PrintWriter(stderr));
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // Restore interrupt
- Log.error("[CLIENT] compile interrupted.");
+ Log.error("Compilation interrupted.");
+ Log.debug(ie);
result = CompilationSubResult.ERROR_FATAL;
- ie.printStackTrace(new PrintWriter(stderr));
}
return result;
}
@@ -203,23 +202,22 @@
private void makeSureServerIsRunning(PortFile portFile)
throws IOException, InterruptedException {
- portFile.lock();
- portFile.getValues();
- portFile.unlock();
+ if (portFile.exists()) {
+ portFile.lock();
+ portFile.getValues();
+ portFile.unlock();
- if (portFile.containsPortInfo()) {
- // Server seems to already be running
- return;
+ if (portFile.containsPortInfo()) {
+ // Server seems to already be running
+ return;
+ }
}
// Fork a new server and wait for it to start
SjavacClient.fork(sjavacForkCmd,
portFile,
- logfile,
poolsize,
- keepalive,
- System.err,
- stdouterrfile);
+ keepalive);
}
@Override
@@ -230,51 +228,53 @@
/*
* Fork a server process process and wait for server to come around
*/
- public static void fork(String sjavacCmd,
- PortFile portFile,
- String logfile,
- int poolsize,
- int keepalive,
- final PrintStream err,
- String stdouterrfile)
- throws IOException, InterruptedException {
+ public static void fork(String sjavacCmd, PortFile portFile, int poolsize, int keepalive)
+ throws IOException, InterruptedException {
List<String> cmd = new ArrayList<>();
cmd.addAll(Arrays.asList(OptionHelper.unescapeCmdArg(sjavacCmd).split(" ")));
cmd.add("--startserver:"
+ "portfile=" + portFile.getFilename()
- + ",logfile=" + logfile
- + ",stdouterrfile=" + stdouterrfile
+ ",poolsize=" + poolsize
+ ",keepalive="+ keepalive);
- Process p = null;
+ Process serverProcess;
Log.info("Starting server. Command: " + String.join(" ", cmd));
try {
- // If the cmd for some reason can't be executed (file not found, or
- // is not executable) this will throw an IOException with a decent
- // error message.
- p = new ProcessBuilder(cmd)
- .redirectErrorStream(true)
- .redirectOutput(new File(stdouterrfile))
- .start();
+ // If the cmd for some reason can't be executed (file is not found,
+ // or is not executable for instance) this will throw an
+ // IOException and p == null.
+ serverProcess = new ProcessBuilder(cmd)
+ .redirectErrorStream(true)
+ .start();
+ } catch (IOException ex) {
+ // Message is typically something like:
+ // Cannot run program "xyz": error=2, No such file or directory
+ Log.error("Failed to create server process: " + ex.getMessage());
+ Log.debug(ex);
+ throw new IOException(ex);
+ }
+ // serverProcess != null at this point.
+ try {
// Throws an IOException if no valid values materialize
portFile.waitForValidValues();
-
} catch (IOException ex) {
- // Log and rethrow exception
- Log.error("Faild to launch server.");
- Log.error(" Message: " + ex.getMessage());
- String rc = p == null || p.isAlive() ? "n/a" : "" + p.exitValue();
- Log.error(" Server process exit code: " + rc);
- Log.error("Server log:");
- Log.error("------- Server log start -------");
- try (Scanner s = new Scanner(new File(stdouterrfile))) {
- while (s.hasNextLine())
- Log.error(s.nextLine());
+ // Process was started, but server failed to initialize. This could
+ // for instance be due to the JVM not finding the server class,
+ // or the server running in to some exception early on.
+ Log.error("Sjavac server failed to initialize: " + ex.getMessage());
+ Log.error("Process output:");
+ Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream());
+ try (BufferedReader br = new BufferedReader(serverStdoutStderr)) {
+ br.lines().forEach(Log::error);
}
- Log.error("------- Server log end ---------");
- throw ex;
+ Log.error("<End of process output>");
+ try {
+ Log.error("Process exit code: " + serverProcess.exitValue());
+ } catch (IllegalThreadStateException e) {
+ // Server is presumably still running.
+ }
+ throw new IOException("Server failed to initialize: " + ex.getMessage(), ex);
}
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -95,11 +95,8 @@
for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles))
explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH));
- // Create a new logger
- StringWriter stdoutLog = new StringWriter();
+ // Create a log to capture compiler output
StringWriter stderrLog = new StringWriter();
- PrintWriter stdout = new PrintWriter(stdoutLog);
- PrintWriter stderr = new PrintWriter(stderrLog);
com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK;
PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs);
PathAndPackageVerifier papVerifier = new PathAndPackageVerifier();
@@ -108,11 +105,10 @@
if (explicitJFOs.size() > 0) {
sfm.setVisibleSources(visibleSources);
sfm.cleanArtifacts();
- sfm.setLog(stdout);
// Do the compilation!
JavacTaskImpl task =
- (JavacTaskImpl) compiler.getTask(stderr,
+ (JavacTaskImpl) compiler.getTask(new PrintWriter(stderrLog),
sfm,
null,
Arrays.asList(args),
@@ -144,7 +140,6 @@
compilationResult.packagePubapis = pubApiCollector.getPubApis(true);
compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false);
- compilationResult.stdout = stdoutLog.toString();
compilationResult.stderr = stderrLog.toString();
compilationResult.returnCode = rc.exitCode;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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,15 +25,14 @@
package com.sun.tools.sjavac.comp;
-import java.io.Writer;
+import com.sun.tools.sjavac.Log;
+import com.sun.tools.sjavac.server.Sjavac;
+
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-import com.sun.tools.sjavac.Log;
-import com.sun.tools.sjavac.server.Sjavac;
-
/**
* An sjavac implementation that limits the number of concurrent calls by
* wrapping invocations in Callables and delegating them to a FixedThreadPool.
@@ -55,10 +54,12 @@
}
@Override
- public int compile(String[] args, Writer out, Writer err) {
+ public int compile(String[] args) {
+ Log log = Log.get();
try {
return pool.submit(() -> {
- return delegate.compile(args, out, err);
+ Log.setLogForCurrentThread(log);
+ return delegate.compile(args);
}).get();
} catch (Exception e) {
e.printStackTrace();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -27,6 +27,7 @@
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -68,7 +69,7 @@
public class SjavacImpl implements Sjavac {
@Override
- public int compile(String[] args, Writer out, Writer err) {
+ public int compile(String[] args) {
Options options;
try {
options = Options.parseArgs(args);
@@ -77,8 +78,6 @@
return RC_FATAL;
}
- Log.setLogLevel(options.getLogLevel());
-
if (!validateOptions(options))
return RC_FATAL;
@@ -100,18 +99,21 @@
if (stateDir == null) {
// Prepare context. Direct logging to our byte array stream.
Context context = new Context();
- PrintWriter writer = new PrintWriter(err);
- com.sun.tools.javac.util.Log.preRegister(context, writer);
+ StringWriter strWriter = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(strWriter);
+ com.sun.tools.javac.util.Log.preRegister(context, printWriter);
JavacFileManager.preRegister(context);
// Prepare arguments
String[] passThroughArgs = Stream.of(args)
.filter(arg -> !arg.startsWith(Option.SERVER.arg))
.toArray(String[]::new);
+ // Compile
+ Main.Result result = new Main("javac", printWriter).compile(passThroughArgs, context);
- // Compile
- com.sun.tools.javac.main.Main compiler = new com.sun.tools.javac.main.Main("javac", writer);
- Main.Result result = compiler.compile(passThroughArgs, context);
+ // Process compiler output (which is always errors)
+ printWriter.flush();
+ Util.getLines(strWriter.toString()).forEach(Log::error);
// Clean up
JavaFileManager fileManager = context.get(JavaFileManager.class);
@@ -126,7 +128,7 @@
} else {
// Load the prev build state database.
- JavacState javac_state = JavacState.load(options, out, err);
+ JavacState javac_state = JavacState.load(options);
// Setup the suffix rules from the command line.
Map<String, Transformer> suffixRules = new HashMap<>();
@@ -288,10 +290,12 @@
return rc[0] ? RC_OK : RC_FATAL;
} catch (ProblemException e) {
+ // For instance make file list mismatch.
Log.error(e.getMessage());
+ Log.debug(e);
return RC_FATAL;
} catch (Exception e) {
- e.printStackTrace(new PrintWriter(err));
+ Log.error(e);
return RC_FATAL;
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -63,8 +63,6 @@
Set<URI> visibleSources = new HashSet<>();
// Map from modulename:packagename to artifacts.
Map<String,Set<URI>> packageArtifacts = new HashMap<>();
- // Where to print informational messages.
- PrintWriter stdout;
public SmartFileManager(JavaFileManager fileManager) {
super(fileManager);
@@ -78,10 +76,6 @@
packageArtifacts = new HashMap<>();
}
- public void setLog(PrintWriter pw) {
- stdout = pw;
- }
-
/**
* Set whether or not to use ct.sym as an alternate to rt.jar.
*/
@@ -188,7 +182,7 @@
if (file == null) return file;
if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && superFile instanceof JavaFileObject) {
- file = new SmartFileObject((JavaFileObject) file, stdout);
+ file = new SmartFileObject((JavaFileObject) file);
packageName = ":" + packageNameFromFileName(relativeName);
}
if (packageName.equals("")) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -49,11 +49,9 @@
public class SmartFileObject implements JavaFileObject {
JavaFileObject file;
- PrintWriter stdout;
- public SmartFileObject(JavaFileObject r, PrintWriter pw) {
+ public SmartFileObject(JavaFileObject r) {
file = r;
- stdout = pw;
}
@Override
@@ -113,7 +111,7 @@
} catch (FileNotFoundException | NoSuchFileException e) {
// Perfectly ok.
}
- return new SmartWriter(file, s.toString(), file.getName(), stdout);
+ return new SmartWriter(file, s.toString(), file.getName());
}
@DefinedBy(Api.COMPILER)
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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,8 @@
package com.sun.tools.sjavac.comp;
+import com.sun.tools.sjavac.Log;
+
import java.io.*;
import javax.tools.JavaFileObject;
@@ -45,19 +47,17 @@
JavaFileObject file;
String oldContent;
StringWriter newContent = new StringWriter();
- PrintWriter stdout;
boolean closed;
- public SmartWriter(JavaFileObject f, String s, String n, PrintWriter pw) {
+
+ public SmartWriter(JavaFileObject f, String s, String n) {
name = n;
file = f;
oldContent = s;
newContent = new StringWriter();
- stdout = pw;
closed = false;
}
- public void write(char[] chars, int i, int i1)
- {
+ public void write(char[] chars, int i, int i1) {
newContent.write(chars, i, i1);
}
@@ -70,7 +70,7 @@
try (Writer writer = file.openWriter()) {
writer.write(s);
}
- stdout.println("Writing "+file.getName().substring(p+1));
+ Log.debug("Writing " + file.getName().substring(p + 1));
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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,10 @@
package com.sun.tools.sjavac.server;
+import com.sun.tools.sjavac.Log;
+
+import java.io.FileWriter;
+import java.io.IOException;
import java.io.Writer;
import java.util.Timer;
import java.util.TimerTask;
@@ -53,8 +57,8 @@
private TimerTask idlenessTimerTask;
public IdleResetSjavac(Sjavac delegate,
- Terminable toShutdown,
- long idleTimeout) {
+ Terminable toShutdown,
+ long idleTimeout) {
this.delegate = delegate;
this.toShutdown = toShutdown;
this.idleTimeout = idleTimeout;
@@ -62,10 +66,10 @@
}
@Override
- public int compile(String[] args, Writer out, Writer err) {
+ public int compile(String[] args) {
startCall();
try {
- return delegate.compile(args, out, err);
+ return delegate.compile(args);
} finally {
endCall();
}
@@ -95,6 +99,7 @@
throw new IllegalStateException("Idle timeout already scheduled");
idlenessTimerTask = new TimerTask() {
public void run() {
+ Log.setLogForCurrentThread(ServerMain.getErrorLog());
toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds.");
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.sjavac.server;
-
-import java.io.FilterWriter;
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Inserts {@literal prefix} in front of each line written.
- *
- * A line is considered to be terminated by any one of a line feed, a carriage
- * return, or a carriage return followed immediately by a line feed.
- */
-public class LinePrefixFilterWriter extends FilterWriter {
-
- private final String prefix;
- private boolean atBeginningOfLine = true;
- private char lastChar = '\0';
-
- protected LinePrefixFilterWriter(Writer out, String prefix) {
- super(out);
- this.prefix = prefix;
- }
-
- @Override
- public void write(String str, int off, int len) throws IOException {
- for (int i = 0; i < len; i++) {
- write(str.charAt(off + i));
- }
- }
-
- @Override
- public void write(char[] cbuf, int off, int len) throws IOException {
- for (int i = 0; i < len; i++) {
- write(cbuf[off + i]);
- }
- }
-
- @Override
- public void write(int c) throws IOException {
- if (lastChar == '\r' && c == '\n') {
- // Second character of CR+LF sequence.
- // Do nothing. We already started a new line on last character.
- } else {
- if (atBeginningOfLine) {
- super.write(prefix, 0, prefix.length());
- }
- super.write(c);
- atBeginningOfLine = c == '\r' || c == '\n';
- }
- lastChar = (char) c;
- }
-}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Sat Mar 05 20:46:44 2016 -0800
@@ -81,10 +81,15 @@
* Create a new portfile.
* @param fn is the path to the file.
*/
- public PortFile(String fn) throws PortFileInaccessibleException {
+ public PortFile(String fn) {
filename = fn;
file = new File(filename);
stopFile = new File(filename+".stop");
+ containsPortInfo = false;
+ lock = null;
+ }
+
+ private void initializeChannel() throws PortFileInaccessibleException {
try {
rwfile = new RandomAccessFile(file, "rw");
} catch (FileNotFoundException e) {
@@ -94,14 +99,15 @@
// The rwfile should only be readable by the owner of the process
// and no other! How do we do that on a RandomAccessFile?
channel = rwfile.getChannel();
- containsPortInfo = false;
- lock = null;
}
/**
* Lock the port file.
*/
public void lock() throws IOException, InterruptedException {
+ if (channel == null) {
+ initializeChannel();
+ }
lockSem.acquire();
lock = channel.lock();
}
@@ -204,8 +210,8 @@
if (stopFile.exists()) {
try {
stopFile.delete();
- } catch (Exception e)
- {}
+ } catch (Exception e) {
+ }
return true;
}
return false;
@@ -215,7 +221,9 @@
* Unlock the port file.
*/
public void unlock() throws IOException {
- Assert.check(lock != null);
+ if (lock == null) {
+ return;
+ }
lock.release();
lock = null;
lockSem.release();
@@ -230,9 +238,11 @@
long timeout = startTime + getServerStartupTimeoutSeconds() * 1000;
while (true) {
Log.debug("Looking for valid port file values...");
- lock();
- getValues();
- unlock();
+ if (exists()) {
+ lock();
+ getValues();
+ unlock();
+ }
if (containsPortInfo) {
Log.debug("Valid port file values found after " + (System.currentTimeMillis() - startTime) + " ms");
return;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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,8 @@
package com.sun.tools.sjavac.server;
+import com.sun.tools.sjavac.Log;
+
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
@@ -56,8 +58,11 @@
}
public void start() {
+ Log log = Log.get();
TimerTask shutdownCheck = new TimerTask() {
public void run() {
+ Log.setLogForCurrentThread(log);
+ Log.debug("Checking port file status...");
try {
if (!portFile.exists()) {
// Time to quit because the portfile was deleted by another
@@ -74,12 +79,11 @@
server.shutdown("Quitting because portfile is now owned by another javac server!");
}
} catch (IOException e) {
- e.printStackTrace(server.theLog);
- server.flushLog();
+ Log.error("IOException caught in PortFileMonitor.");
+ Log.debug(e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
- e.printStackTrace(server.theLog);
- server.flushLog();
+ Log.error(e);
}
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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,19 +25,16 @@
package com.sun.tools.sjavac.server;
-import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC;
-import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDERR;
-import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDOUT;
+import com.sun.tools.sjavac.Log;
+import com.sun.tools.sjavac.Util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
import java.net.Socket;
+import java.nio.file.Path;
-import com.sun.tools.sjavac.AutoFlushWriter;
-import com.sun.tools.sjavac.Log;
+import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC;
/**
@@ -56,7 +53,7 @@
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
-public class RequestHandler implements Runnable {
+public class RequestHandler extends Thread {
private final Socket socket;
private final Sjavac sjavac;
@@ -68,9 +65,30 @@
@Override
public void run() {
+
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
+ // Set up logging for this thread. Stream back logging messages to
+ // client on the format format "level:msg".
+ Log.setLogForCurrentThread(new Log(out, out) {
+ @Override
+ protected boolean isLevelLogged(Level l) {
+ // Make sure it is up to the client to decide whether or
+ // not this message should be displayed.
+ return true;
+ }
+
+ @Override
+ protected void printLogMsg(Level msgLevel, String msg) {
+ // Follow sjavac server/client protocol: Send one line
+ // at a time and prefix with message with "level:".
+ Util.getLines(msg)
+ .map(line -> msgLevel + ":" + line)
+ .forEach(line -> super.printLogMsg(msgLevel, line));
+ }
+ });
+
// Read argument array
int n = Integer.parseInt(in.readLine());
String[] args = new String[n];
@@ -78,23 +96,32 @@
args[i] = in.readLine();
}
+ // If there has been any internal errors, notify client
+ checkInternalErrorLog();
+
// Perform compilation
- Writer stdout = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDOUT + ":");
- Writer stderr = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDERR + ":");
- int rc = sjavac.compile(args, stdout, stderr);
- stdout.flush();
- stderr.flush();
+ int rc = sjavac.compile(args);
// Send return code back to client
out.println(LINE_TYPE_RC + ":" + rc);
+ // Check for internal errors again.
+ checkInternalErrorLog();
} catch (Exception ex) {
// Not much to be done at this point. The client side request
// code will most likely throw an IOException and the
// compilation will fail.
- StringWriter sw = new StringWriter();
- ex.printStackTrace(new PrintWriter(sw));
- Log.error(sw.toString());
+ Log.error(ex);
+ } finally {
+ Log.setLogForCurrentThread(null);
+ }
+ }
+
+ private void checkInternalErrorLog() {
+ Path errorLog = ServerMain.getErrorLog().getLogDestination();
+ if (errorLog != null) {
+ Log.error("Server has encountered an internal error. See " + errorLog.toAbsolutePath()
+ + " for details.");
}
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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,10 +25,20 @@
package com.sun.tools.sjavac.server;
+import java.io.FileWriter;
+import java.io.FilterOutputStream;
+import java.io.FilterWriter;
import java.io.IOException;
-import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.lang.Thread.UncaughtExceptionHandler;
import com.sun.tools.sjavac.Log;
+import com.sun.tools.sjavac.Log.Level;
+import com.sun.tools.sjavac.server.log.LazyInitFileLog;
+import com.sun.tools.sjavac.server.log.LoggingOutputStream;
+
+import static com.sun.tools.sjavac.Log.Level.ERROR;
+import static com.sun.tools.sjavac.Log.Level.INFO;
/**
* <p><b>This is NOT part of any supported API.
@@ -37,20 +47,40 @@
* deletion without notice.</b>
*/
public class ServerMain {
+
+ // For logging server internal (non request specific) errors.
+ private static LazyInitFileLog errorLog;
+
public static int run(String[] args) {
- Log.initializeLog(new OutputStreamWriter(System.out),
- new OutputStreamWriter(System.err));
+ // Under normal operation, all logging messages generated server-side
+ // are due to compilation requests. These logging messages should
+ // be relayed back to the requesting client rather than written to the
+ // server log. The only messages that should be written to the server
+ // log (in production mode) should be errors,
+ Log.setLogForCurrentThread(errorLog = new LazyInitFileLog("server.log"));
+ Log.setLogLevel(ERROR); // should be set to ERROR.
+
+ // Make sure no exceptions go under the radar
+ Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
+ Log.setLogForCurrentThread(errorLog);
+ Log.error(e);
+ });
+
+ // Inevitably someone will try to print messages using System.{out,err}.
+ // Make sure this output also ends up in the log.
+ System.setOut(new PrintStream(new LoggingOutputStream(System.out, INFO, "[stdout] ")));
+ System.setErr(new PrintStream(new LoggingOutputStream(System.err, ERROR, "[stderr] ")));
// Any options other than --startserver?
if (args.length > 1) {
- System.err.println("When spawning a background server, only a single --startserver argument is allowed.");
+ Log.error("When spawning a background server, only a single --startserver argument is allowed.");
return 1;
}
int exitCode;
try {
- SjavacServer server = new SjavacServer(args[0], System.err);
+ SjavacServer server = new SjavacServer(args[0]);
exitCode = server.startServer();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
@@ -59,4 +89,8 @@
return exitCode;
}
+
+ public static LazyInitFileLog getErrorLog() {
+ return errorLog;
+ }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,6 @@
final static int RC_FATAL = -1;
final static int RC_OK = 0;
- int compile(String[] args, Writer stdout, Writer stderr);
+ int compile(String[] args);
void shutdown();
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
package com.sun.tools.sjavac.server;
import java.io.FileNotFoundException;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
@@ -39,6 +40,7 @@
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
+import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.Util;
import com.sun.tools.sjavac.client.PortFileInaccessibleException;
import com.sun.tools.sjavac.comp.PooledSjavac;
@@ -54,17 +56,12 @@
*/
public class SjavacServer implements Terminable {
- // Used in protocol to tell the content of each line
+ // Prefix of line containing return code.
public final static String LINE_TYPE_RC = "RC";
- public final static String LINE_TYPE_STDOUT = "STDOUT";
- public final static String LINE_TYPE_STDERR = "STDERR";
final private String portfilename;
- final private String logfile;
- final private String stdouterrfile;
final private int poolsize;
final private int keepalive;
- final private PrintStream err;
// The secret cookie shared between server and client through the port file.
// Used to prevent clients from believing that they are communicating with
@@ -75,9 +72,6 @@
// Accumulated build time, not counting idle time, used for logging purposes
private long totalBuildTime;
- // The javac server specific log file.
- PrintWriter theLog;
-
// The sjavac implementation to delegate requests to
Sjavac sjavac;
@@ -92,40 +86,28 @@
// For the client, all port files fetched, one per started javac server.
// Though usually only one javac server is started by a client.
private static Map<String, PortFile> allPortFiles;
- private static Map<String, Long> maxServerMemory;
- public SjavacServer(String settings, PrintStream err) throws FileNotFoundException {
+ public SjavacServer(String settings) throws FileNotFoundException {
this(Util.extractStringOption("portfile", settings),
- Util.extractStringOption("logfile", settings),
- Util.extractStringOption("stdouterrfile", settings),
Util.extractIntOption("poolsize", settings, Runtime.getRuntime().availableProcessors()),
- Util.extractIntOption("keepalive", settings, 120),
- err);
+ Util.extractIntOption("keepalive", settings, 120));
}
public SjavacServer(String portfilename,
- String logfile,
- String stdouterrfile,
int poolsize,
- int keepalive,
- PrintStream err)
+ int keepalive)
throws FileNotFoundException {
this.portfilename = portfilename;
- this.logfile = logfile;
- this.stdouterrfile = stdouterrfile;
this.poolsize = poolsize;
this.keepalive = keepalive;
- this.err = err;
-
- myCookie = new Random().nextLong();
- theLog = new PrintWriter(logfile);
+ this.myCookie = new Random().nextLong();
}
/**
* Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time.
*/
- public static synchronized PortFile getPortFile(String filename) throws PortFileInaccessibleException {
+ public static synchronized PortFile getPortFile(String filename) {
if (allPortFiles == null) {
allPortFiles = new HashMap<>();
}
@@ -170,26 +152,6 @@
}
/**
- * Log this message.
- */
- public void log(String msg) {
- if (theLog != null) {
- theLog.println(msg);
- } else {
- System.err.println(msg);
- }
- }
-
- /**
- * Make sure the log is flushed.
- */
- public void flushLog() {
- if (theLog != null) {
- theLog.flush();
- }
- }
-
- /**
* Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3"
* is sent as the settings parameter. Returns 0 on success, -1 on failure.
*/
@@ -203,7 +165,7 @@
portFile.lock();
portFile.getValues();
if (portFile.containsPortInfo()) {
- err.println("Javac server not started because portfile exists!");
+ Log.info("Javac server not started because portfile exists!");
portFile.unlock();
return -1;
}
@@ -230,23 +192,23 @@
portFileMonitor = new PortFileMonitor(portFile, this);
portFileMonitor.start();
- log("Sjavac server started. Accepting connections...");
- log(" port: " + getPort());
- log(" time: " + new java.util.Date());
- log(" poolsize: " + poolsize);
- flushLog();
+ Log.info("Sjavac server started. Accepting connections...");
+ Log.info(" port: " + getPort());
+ Log.info(" time: " + new java.util.Date());
+ Log.info(" poolsize: " + poolsize);
+
keepAcceptingRequests.set(true);
do {
try {
Socket socket = serverSocket.accept();
- new Thread(new RequestHandler(socket, sjavac)).start();
+ new RequestHandler(socket, sjavac).start();
} catch (SocketException se) {
// Caused by serverSocket.close() and indicates shutdown
}
} while (keepAcceptingRequests.get());
- log("Shutting down.");
+ Log.info("Shutting down.");
// No more connections accepted. If any client managed to connect after
// the accept() was interrupted but before the server socket is closed
@@ -254,8 +216,7 @@
// IOException on the client side.
long realTime = System.currentTimeMillis() - serverStart;
- log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms");
- flushLog();
+ Log.info("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms");
// Shut down
sjavac.shutdown();
@@ -270,8 +231,7 @@
return;
}
- log("Quitting: " + quitMsg);
- flushLog();
+ Log.info("Quitting: " + quitMsg);
portFileMonitor.shutdown(); // No longer any need to monitor port file
@@ -280,12 +240,12 @@
try {
portFile.delete();
} catch (IOException | InterruptedException e) {
- e.printStackTrace(theLog);
+ Log.error(e);
}
try {
serverSocket.close();
} catch (IOException e) {
- e.printStackTrace(theLog);
+ Log.error(e);
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.sjavac.server.log;
+
+import com.sun.tools.sjavac.Log;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class LazyInitFileLog extends Log {
+
+ String baseFilename;
+ Path destination = null;
+
+ public LazyInitFileLog(String baseFilename) {
+ super(null, null);
+ this.baseFilename = baseFilename;
+ }
+
+ protected void printLogMsg(Level msgLevel, String msg) {
+ try {
+ // Lazily initialize out/err
+ if (out == null && isLevelLogged(msgLevel)) {
+ destination = getAvailableDestination();
+ out = err = new PrintWriter(new FileWriter(destination.toFile()), true);
+ }
+ // Proceed to log the message
+ super.printLogMsg(msgLevel, msg);
+ } catch (IOException e) {
+ // This could be bad. We might have run into an error and we can't
+ // log it. Resort to printing on stdout.
+ System.out.println("IO error occurred: " + e.getMessage());
+ System.out.println("Original message: [" + msgLevel + "] " + msg);
+ }
+ }
+
+ /**
+ * @return The first available path of baseFilename, baseFilename.1,
+ * basefilename.2, ...
+ */
+ private Path getAvailableDestination() {
+ Path p = Paths.get(baseFilename);
+ int i = 1;
+ while (Files.exists(p)) {
+ p = Paths.get(baseFilename + "." + i++);
+ }
+ return p;
+ }
+
+ public Path getLogDestination() {
+ return destination;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.sjavac.server.log;
+
+import com.sun.tools.sjavac.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class LoggingOutputStream extends FilterOutputStream {
+
+ private static final byte[] LINE_SEP = System.lineSeparator().getBytes();
+
+ private final Log.Level level;
+ private final String linePrefix;
+ private EolTrackingByteArrayOutputStream buf = new EolTrackingByteArrayOutputStream();
+
+ public LoggingOutputStream(OutputStream out, Log.Level level, String linePrefix) {
+ super(out);
+ this.level = level;
+ this.linePrefix = linePrefix;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ super.write(b);
+ buf.write(b);
+ if (buf.isLineComplete()) {
+ String line = new String(buf.toByteArray(), 0, buf.size() - LINE_SEP.length);
+ Log.log(level, linePrefix + line);
+ buf = new EolTrackingByteArrayOutputStream();
+ }
+ }
+
+ private static class EolTrackingByteArrayOutputStream extends ByteArrayOutputStream {
+ private static final byte[] EOL = System.lineSeparator().getBytes();
+ private boolean isLineComplete() {
+ if (count < EOL.length) {
+ return false;
+ }
+ for (int i = 0; i < EOL.length; i++) {
+ if (buf[count - EOL.length + i] != EOL[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Sat Mar 05 20:46:44 2016 -0800
@@ -26,6 +26,7 @@
package jdk.internal.jshell.tool;
import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
+import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
import jdk.jshell.SourceCodeAnalysis.Suggestion;
import java.awt.event.ActionListener;
@@ -34,8 +35,12 @@
import java.io.PrintStream;
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
@@ -144,6 +149,11 @@
bind(DOCUMENTATION_SHORTCUT, (ActionListener) evt -> documentation(repl));
bind(CTRL_UP, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::previousSnippet));
bind(CTRL_DOWN, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::nextSnippet));
+ for (FixComputer computer : FIX_COMPUTERS) {
+ for (String shortcuts : SHORTCUT_FIXES) {
+ bind(shortcuts + computer.shortcut, (ActionListener) evt -> fixes(computer));
+ }
+ }
}
@Override
@@ -216,6 +226,11 @@
private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP
private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN
+ private static final String[] SHORTCUT_FIXES = {
+ "\033\015", //Alt-Enter (Linux)
+ "\033\133\061\067\176", //F6/Alt-F1 (Mac)
+ "\u001BO3P" //Alt-F1 (Linux)
+ };
private void documentation(JShellTool repl) {
String buffer = in.getCursorBuffer().buffer.toString();
@@ -290,6 +305,185 @@
history.fullHistoryReplace(source);
}
+ //compute possible options/Fixes based on the selected FixComputer, present them to the user,
+ //and perform the selected one:
+ private void fixes(FixComputer computer) {
+ String input = prefix + in.getCursorBuffer().toString();
+ int cursor = prefix.length() + in.getCursorBuffer().cursor;
+ FixResult candidates = computer.compute(repl, input, cursor);
+
+ try {
+ final boolean printError = candidates.error != null && !candidates.error.isEmpty();
+ if (printError) {
+ in.println(candidates.error);
+ }
+ if (candidates.fixes.isEmpty()) {
+ in.beep();
+ if (printError) {
+ in.redrawLine();
+ in.flush();
+ }
+ } else if (candidates.fixes.size() == 1 && !computer.showMenu) {
+ if (printError) {
+ in.redrawLine();
+ in.flush();
+ }
+ candidates.fixes.get(0).perform(in);
+ } else {
+ List<Fix> fixes = new ArrayList<>(candidates.fixes);
+ fixes.add(0, new Fix() {
+ @Override
+ public String displayName() {
+ return "Do nothing";
+ }
+
+ @Override
+ public void perform(ConsoleReader in) throws IOException {
+ in.redrawLine();
+ }
+ });
+
+ Map<Character, Fix> char2Fix = new HashMap<>();
+ in.println();
+ for (int i = 0; i < fixes.size(); i++) {
+ Fix fix = fixes.get(i);
+ char2Fix.put((char) ('0' + i), fix);
+ in.println("" + i + ": " + fixes.get(i).displayName());
+ }
+ in.print("Choice: ");
+ in.flush();
+ int read;
+
+ read = in.readCharacter();
+
+ Fix fix = char2Fix.get((char) read);
+
+ if (fix == null) {
+ in.beep();
+ fix = fixes.get(0);
+ }
+
+ in.println();
+
+ fix.perform(in);
+
+ in.flush();
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * A possible action which the user can choose to perform.
+ */
+ public interface Fix {
+ /**
+ * A name that should be shown to the user.
+ */
+ public String displayName();
+ /**
+ * Perform the given action.
+ */
+ public void perform(ConsoleReader in) throws IOException;
+ }
+
+ /**
+ * A factory for {@link Fix}es.
+ */
+ public abstract static class FixComputer {
+ private final char shortcut;
+ private final boolean showMenu;
+
+ /**
+ * Construct a new FixComputer. {@code shortcut} defines the key which should trigger this FixComputer.
+ * If {@code showMenu} is {@code false}, and this computer returns exactly one {@code Fix},
+ * no options will be show to the user, and the given {@code Fix} will be performed.
+ */
+ public FixComputer(char shortcut, boolean showMenu) {
+ this.shortcut = shortcut;
+ this.showMenu = showMenu;
+ }
+
+ /**
+ * Compute possible actions for the given code.
+ */
+ public abstract FixResult compute(JShellTool repl, String code, int cursor);
+ }
+
+ /**
+ * A list of {@code Fix}es with a possible error that should be shown to the user.
+ */
+ public static class FixResult {
+ public final List<Fix> fixes;
+ public final String error;
+
+ public FixResult(List<Fix> fixes, String error) {
+ this.fixes = fixes;
+ this.error = error;
+ }
+ }
+
+ private static final FixComputer[] FIX_COMPUTERS = new FixComputer[] {
+ new FixComputer('v', false) { //compute "Introduce variable" Fix:
+ @Override
+ public FixResult compute(JShellTool repl, String code, int cursor) {
+ String type = repl.analysis.analyzeType(code, cursor);
+ if (type == null) {
+ return new FixResult(Collections.emptyList(), null);
+ }
+ return new FixResult(Collections.singletonList(new Fix() {
+ @Override
+ public String displayName() {
+ return "Create variable";
+ }
+ @Override
+ public void perform(ConsoleReader in) throws IOException {
+ in.redrawLine();
+ in.setCursorPosition(0);
+ in.putString(type + " = ");
+ in.setCursorPosition(in.getCursorBuffer().cursor - 3);
+ in.flush();
+ }
+ }), null);
+ }
+ },
+ new FixComputer('i', true) { //compute "Add import" Fixes:
+ @Override
+ public FixResult compute(JShellTool repl, String code, int cursor) {
+ QualifiedNames res = repl.analysis.listQualifiedNames(code, cursor);
+ List<Fix> fixes = new ArrayList<>();
+ for (String fqn : res.getNames()) {
+ fixes.add(new Fix() {
+ @Override
+ public String displayName() {
+ return "import: " + fqn;
+ }
+ @Override
+ public void perform(ConsoleReader in) throws IOException {
+ repl.state.eval("import " + fqn + ";");
+ in.println("Imported: " + fqn);
+ in.redrawLine();
+ }
+ });
+ }
+ if (res.isResolvable()) {
+ return new FixResult(Collections.emptyList(),
+ "\nThe identifier is resolvable in this context.");
+ } else {
+ String error = "";
+ if (fixes.isEmpty()) {
+ error = "\nNo candidate fully qualified names found to import.";
+ }
+ if (!res.isUpToDate()) {
+ error += "\nResults may be incomplete; try again later for complete results.";
+ }
+ return new FixResult(fixes, error);
+ }
+ }
+ }
+ };
+
private static final class JShellUnixTerminal extends NoInterruptUnixTerminal {
private final StopDetectingInputStream input;
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Sat Mar 05 20:46:44 2016 -0800
@@ -988,13 +988,19 @@
CommandKind.HELP_SUBJECT));
registerCommand(new Command("shortcuts", "Describe shortcuts",
"Supported shortcuts include:\n\n" +
- "<tab> -- After entering the first few letters of a Java identifier,\n" +
- " a jshell command, or, in some cases, a jshell command argument,\n" +
- " press the <tab> key to complete the input.\n" +
- " If there is more than one completion, show possible completions.\n" +
- "Shift-<tab> -- After the name and open parenthesis of a method or constructor invocation,\n" +
- " hold the <shift> key and press the <tab> to see a synopsis of all\n" +
- " matching methods/constructors.\n",
+ "<tab> -- After entering the first few letters of a Java identifier,\n" +
+ " a jshell command, or, in some cases, a jshell command argument,\n" +
+ " press the <tab> key to complete the input.\n" +
+ " If there is more than one completion, show possible completions.\n" +
+ "Shift-<tab> -- After the name and open parenthesis of a method or constructor invocation,\n" +
+ " hold the <shift> key and press the <tab> to see a synopsis of all\n" +
+ " matching methods/constructors.\n" +
+ "<fix-shortcut> v -- After a complete expression, press \"<fix-shortcut> v\" to introduce a new variable\n" +
+ " whose type is based on the type of the expression.\n" +
+ " The \"<fix-shortcut>\" is either Alt-F1 or Alt-Enter, depending on the platform.\n" +
+ "<fix-shortcut> i -- After an unresolvable identifier, press \"<fix-shortcut> i\" and jshell will propose\n" +
+ " possible fully qualified names based on the content of the specified classpath.\n" +
+ " The \"<fix-shortcut>\" is either Alt-F1 or Alt-Enter, depending on the platform.\n",
CommandKind.HELP_SUBJECT));
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Sat Mar 05 20:46:44 2016 -0800
@@ -420,7 +420,7 @@
TaskFactory.AnalyzeTask at = trialCompile(guts);
if (!at.hasErrors() && at.firstCuTree() != null) {
return TreeDissector.createByFirstClass(at)
- .typeOfReturnStatement(at.messages(), state.maps::fullClassNameAndPackageToClass);
+ .typeOfReturnStatement(at, state);
}
return null;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Sat Mar 05 20:46:44 2016 -0800
@@ -346,10 +346,20 @@
* @see JShell#onShutdown(java.util.function.Consumer)
*/
public List<SnippetEvent> eval(String input) throws IllegalStateException {
- checkIfAlive();
- List<SnippetEvent> events = eval.eval(input);
- events.forEach(this::notifyKeyStatusEvent);
- return Collections.unmodifiableList(events);
+ SourceCodeAnalysisImpl a = sourceCodeAnalysis;
+ if (a != null) {
+ a.suspendIndexing();
+ }
+ try {
+ checkIfAlive();
+ List<SnippetEvent> events = eval.eval(input);
+ events.forEach(this::notifyKeyStatusEvent);
+ return Collections.unmodifiableList(events);
+ } finally {
+ if (a != null) {
+ a.resumeIndexing();
+ }
+ }
}
/**
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java Sat Mar 05 20:46:44 2016 -0800
@@ -70,6 +70,28 @@
public abstract String documentation(String input, int cursor);
/**
+ * Infer the type of the given expression. The expression spans from the beginning of {@code code}
+ * to the given {@code cursor} position. Returns null if the type of the expression cannot
+ * be inferred.
+ *
+ * @param code the expression for which the type should be inferred
+ * @param cursor current cursor position in the given code
+ * @return the inferred type, or null if it cannot be inferred
+ */
+ public abstract String analyzeType(String code, int cursor);
+
+ /**
+ * List qualified names known for the simple name in the given code immediately
+ * to the left of the given cursor position. The qualified names are gathered by inspecting the
+ * classpath used by eval (see {@link JShell#addToClasspath(java.lang.String)}).
+ *
+ * @param code the expression for which the candidate qualified names should be computed
+ * @param cursor current cursor position in the given code
+ * @return the known qualified names
+ */
+ public abstract QualifiedNames listQualifiedNames(String code, int cursor);
+
+ /**
* Internal only constructor
*/
SourceCodeAnalysis() {}
@@ -80,7 +102,7 @@
*/
public static class CompletionInfo {
- public CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) {
+ CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) {
this.completeness = completeness;
this.unitEndPos = unitEndPos;
this.source = source;
@@ -198,4 +220,65 @@
*/
public final boolean isSmart;
}
+
+ /**
+ * List of possible qualified names.
+ */
+ public static final class QualifiedNames {
+
+ private final List<String> names;
+ private final int simpleNameLength;
+ private final boolean upToDate;
+ private final boolean resolvable;
+
+ QualifiedNames(List<String> names, int simpleNameLength, boolean upToDate, boolean resolvable) {
+ this.names = names;
+ this.simpleNameLength = simpleNameLength;
+ this.upToDate = upToDate;
+ this.resolvable = resolvable;
+ }
+
+ /**
+ * Known qualified names for the given simple name in the original code.
+ *
+ * @return known qualified names
+ */
+ public List<String> getNames() {
+ return names;
+ }
+
+ /**
+ * The length of the simple name in the original code for which the
+ * qualified names where gathered.
+ *
+ * @return the length of the simple name; -1 if there is no name immediately left to the cursor for
+ * which the candidates could be computed
+ */
+ public int getSimpleNameLength() {
+ return simpleNameLength;
+ }
+
+ /**
+ * Whether the result is based on up to date data. The
+ * {@link SourceCodeAnalysis#listQualifiedNames(java.lang.String, int) listQualifiedNames}
+ * method may return before the classpath is fully inspected, in which case this method will
+ * return {@code false}. If the result is based on a fully inspected classpath, this method
+ * will return {@code true}.
+ *
+ * @return true iff the results is based on up-to-date data
+ */
+ public boolean isUpToDate() {
+ return upToDate;
+ }
+
+ /**
+ * Whether the given simple name in the original code refers to a resolvable element.
+ *
+ * @return true iff the given simple name in the original code refers to a resolvable element
+ */
+ public boolean isResolvable() {
+ return resolvable;
+ }
+
+ }
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Sat Mar 05 20:46:44 2016 -0800
@@ -79,13 +79,23 @@
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -99,6 +109,7 @@
import java.util.stream.StreamSupport;
import javax.lang.model.SourceVersion;
+
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.QualifiedNameable;
@@ -118,12 +129,30 @@
* @author Robert Field
*/
class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
+
+ private static final Map<Path, ClassIndex> PATH_TO_INDEX = new HashMap<>();
+ private static final ExecutorService INDEXER = Executors.newFixedThreadPool(1, r -> {
+ Thread t = new Thread(r);
+ t.setDaemon(true);
+ t.setUncaughtExceptionHandler((thread, ex) -> ex.printStackTrace());
+ return t;
+ });
+
private final JShell proc;
private final CompletenessAnalyzer ca;
+ private final Map<Path, ClassIndex> currentIndexes = new HashMap<>();
+ private int indexVersion;
+ private int classpathVersion;
+ private final Object suspendLock = new Object();
+ private int suspend;
SourceCodeAnalysisImpl(JShell proc) {
this.proc = proc;
this.ca = new CompletenessAnalyzer(proc);
+
+ int cpVersion = classpathVersion = 1;
+
+ INDEXER.submit(() -> refreshIndexes(cpVersion));
}
@Override
@@ -203,6 +232,15 @@
@Override
public List<Suggestion> completionSuggestions(String code, int cursor, int[] anchor) {
+ suspendIndexing();
+ try {
+ return completionSuggestionsImpl(code, cursor, anchor);
+ } finally {
+ resumeIndexing();
+ }
+ }
+
+ private List<Suggestion> completionSuggestionsImpl(String code, int cursor, int[] anchor) {
code = code.substring(0, cursor);
Matcher m = JAVA_IDENTIFIER.matcher(code);
String identifier = "";
@@ -390,8 +428,11 @@
long start = sp.getStartPosition(topLevel, tree);
long end = sp.getEndPosition(topLevel, tree);
+ long prevEnd = deepest[0] != null ? sp.getEndPosition(topLevel, deepest[0].getLeaf()) : -1;
- if (start <= pos && pos <= end) {
+ if (start <= pos && pos <= end &&
+ (start != end || prevEnd != end || deepest[0] == null ||
+ deepest[0].getParentPath().getLeaf() != getCurrentPath().getLeaf())) {
deepest[0] = new TreePath(getCurrentPath(), tree);
return super.scan(tree, p);
}
@@ -589,32 +630,28 @@
.collect(toList());
}
- private Set<String> emptyContextPackages = null;
+ void classpathChanged() {
+ synchronized (currentIndexes) {
+ int cpVersion = ++classpathVersion;
- void classpathChanged() {
- emptyContextPackages = null;
+ INDEXER.submit(() -> refreshIndexes(cpVersion));
+ }
}
private Set<PackageElement> listPackages(AnalyzeTask at, String enclosingPackage) {
- Set<String> packs;
-
- if (enclosingPackage.isEmpty() && emptyContextPackages != null) {
- packs = emptyContextPackages;
- } else {
- packs = new HashSet<>();
-
- listPackages(StandardLocation.PLATFORM_CLASS_PATH, enclosingPackage, packs);
- listPackages(StandardLocation.CLASS_PATH, enclosingPackage, packs);
- listPackages(StandardLocation.SOURCE_PATH, enclosingPackage, packs);
-
- if (enclosingPackage.isEmpty()) {
- emptyContextPackages = packs;
- }
+ synchronized (currentIndexes) {
+ return currentIndexes.values()
+ .stream()
+ .flatMap(idx -> idx.packages.stream())
+ .filter(p -> enclosingPackage.isEmpty() || p.startsWith(enclosingPackage + "."))
+ .map(p -> {
+ int dot = p.indexOf('.', enclosingPackage.length() + 1);
+ return dot == (-1) ? p : p.substring(0, dot);
+ })
+ .distinct()
+ .map(p -> createPackageElement(at, p))
+ .collect(Collectors.toSet());
}
-
- return packs.stream()
- .map(pkg -> createPackageElement(at, pkg))
- .collect(Collectors.toSet());
}
private PackageElement createPackageElement(AnalyzeTask at, String packageName) {
@@ -625,79 +662,6 @@
return existing;
}
- private void listPackages(Location loc, String enclosing, Set<String> packs) {
- Iterable<? extends Path> paths = proc.taskFactory.fileManager().getLocationAsPaths(loc);
-
- if (paths == null)
- return ;
-
- for (Path p : paths) {
- listPackages(p, enclosing, packs);
- }
- }
-
- private void listPackages(Path path, String enclosing, Set<String> packages) {
- try {
- if (path.equals(Paths.get("JRT_MARKER_FILE"))) {
- FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
- Path modules = jrtfs.getPath("modules");
- try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules)) {
- for (Path c : stream) {
- listDirectory(c, enclosing, packages);
- }
- }
- } else if (!Files.isDirectory(path)) {
- if (Files.exists(path)) {
- ClassLoader cl = SourceCodeAnalysisImpl.class.getClassLoader();
-
- try (FileSystem zip = FileSystems.newFileSystem(path, cl)) {
- listDirectory(zip.getRootDirectories().iterator().next(), enclosing, packages);
- }
- }
- } else {
- listDirectory(path, enclosing, packages);
- }
- } catch (IOException ex) {
- proc.debug(ex, "SourceCodeAnalysisImpl.listPackages(" + path.toString() + ", " + enclosing + ", " + packages + ")");
- }
- }
-
- private void listDirectory(Path path, String enclosing, Set<String> packages) throws IOException {
- String separator = path.getFileSystem().getSeparator();
- Path resolved = path.resolve(enclosing.replace(".", separator));
-
- if (Files.isDirectory(resolved)) {
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(resolved)) {
- for (Path entry : ds) {
- String name = pathName(entry);
-
- if (SourceVersion.isIdentifier(name) &&
- Files.isDirectory(entry) &&
- validPackageCandidate(entry)) {
- packages.add(enclosing + (enclosing.isEmpty() ? "" : ".") + name);
- }
- }
- }
- }
- }
-
- private boolean validPackageCandidate(Path p) throws IOException {
- try (Stream<Path> dir = Files.list(p)) {
- return dir.anyMatch(e -> Files.isDirectory(e) && SourceVersion.isIdentifier(pathName(e)) ||
- e.getFileName().toString().endsWith(".class"));
- }
- }
-
- private String pathName(Path p) {
- String separator = p.getFileSystem().getSeparator();
- String name = p.getFileName().toString();
-
- if (name.endsWith(separator)) //jars have '/' appended
- name = name.substring(0, name.length() - separator.length());
-
- return name;
- }
-
private Element createArrayLengthSymbol(AnalyzeTask at, TypeMirror site) {
Name length = Names.instance(at.getContext()).length;
Type intType = Symtab.instance(at.getContext()).intType;
@@ -965,6 +929,15 @@
@Override
public String documentation(String code, int cursor) {
+ suspendIndexing();
+ try {
+ return documentationImpl(code, cursor);
+ } finally {
+ resumeIndexing();
+ }
+ }
+
+ private String documentationImpl(String code, int cursor) {
code = code.substring(0, cursor);
if (code.trim().isEmpty()) { //TODO: comment handling
code += ";";
@@ -1074,4 +1047,347 @@
}
return arrayType;
}
+
+ @Override
+ public String analyzeType(String code, int cursor) {
+ code = code.substring(0, cursor);
+ CompletionInfo completionInfo = analyzeCompletion(code);
+ if (!completionInfo.completeness.isComplete)
+ return null;
+ if (completionInfo.completeness == Completeness.COMPLETE_WITH_SEMI) {
+ code += ";";
+ }
+
+ OuterWrap codeWrap;
+ switch (guessKind(code)) {
+ case IMPORT: case METHOD: case CLASS: case ENUM:
+ case INTERFACE: case ANNOTATION_TYPE: case VARIABLE:
+ return null;
+ default:
+ codeWrap = wrapInClass(Wrap.methodWrap(code));
+ break;
+ }
+ AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap);
+ SourcePositions sp = at.trees().getSourcePositions();
+ CompilationUnitTree topLevel = at.firstCuTree();
+ int pos = codeWrap.snippetIndexToWrapIndex(code.length());
+ TreePath tp = pathFor(topLevel, sp, pos);
+ while (ExpressionTree.class.isAssignableFrom(tp.getParentPath().getLeaf().getKind().asInterface()) &&
+ tp.getParentPath().getLeaf().getKind() != Kind.ERRONEOUS &&
+ tp.getParentPath().getParentPath() != null)
+ tp = tp.getParentPath();
+ TypeMirror type = at.trees().getTypeMirror(tp);
+
+ if (type == null)
+ return null;
+
+ switch (type.getKind()) {
+ case ERROR: case NONE: case OTHER:
+ case PACKAGE: case VOID:
+ return null; //not usable
+ case NULL:
+ type = at.getElements().getTypeElement("java.lang.Object").asType();
+ break;
+ }
+
+ return TreeDissector.printType(at, proc, type);
+ }
+
+ @Override
+ public QualifiedNames listQualifiedNames(String code, int cursor) {
+ code = code.substring(0, cursor);
+ if (code.trim().isEmpty()) {
+ return new QualifiedNames(Collections.emptyList(), -1, true, false);
+ }
+ OuterWrap codeWrap;
+ switch (guessKind(code)) {
+ case IMPORT:
+ return new QualifiedNames(Collections.emptyList(), -1, true, false);
+ case METHOD:
+ codeWrap = wrapInClass(Wrap.classMemberWrap(code));
+ break;
+ default:
+ codeWrap = wrapInClass(Wrap.methodWrap(code));
+ break;
+ }
+ AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap);
+ SourcePositions sp = at.trees().getSourcePositions();
+ CompilationUnitTree topLevel = at.firstCuTree();
+ TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(code.length()));
+ if (tp.getLeaf().getKind() != Kind.IDENTIFIER) {
+ return new QualifiedNames(Collections.emptyList(), -1, true, false);
+ }
+ Scope scope = at.trees().getScope(tp);
+ TypeMirror type = at.trees().getTypeMirror(tp);
+ Element el = at.trees().getElement(tp);
+
+ boolean erroneous = (type.getKind() == TypeKind.ERROR && el.getKind() == ElementKind.CLASS) ||
+ (el.getKind() == ElementKind.PACKAGE && el.getEnclosedElements().isEmpty());
+ String simpleName = ((IdentifierTree) tp.getLeaf()).getName().toString();
+ boolean upToDate;
+ List<String> result;
+
+ synchronized (currentIndexes) {
+ upToDate = classpathVersion == indexVersion;
+ result = currentIndexes.values()
+ .stream()
+ .flatMap(idx -> idx.classSimpleName2FQN.getOrDefault(simpleName,
+ Collections.emptyList()).stream())
+ .distinct()
+ .filter(fqn -> isAccessible(at, scope, fqn))
+ .sorted()
+ .collect(Collectors.toList());
+ }
+
+ return new QualifiedNames(result, simpleName.length(), upToDate, !erroneous);
+ }
+
+ private boolean isAccessible(AnalyzeTask at, Scope scope, String fqn) {
+ TypeElement type = at.getElements().getTypeElement(fqn);
+ if (type == null)
+ return false;
+ return at.trees().isAccessible(scope, type);
+ }
+
+ //--------------------
+ // classpath indexing:
+ //--------------------
+
+ //the indexing can be suspended when a more important task is running:
+ private void waitIndexingNotSuspended() {
+ boolean suspendedNotified = false;
+ synchronized (suspendLock) {
+ while (suspend > 0) {
+ if (!suspendedNotified) {
+ suspendedNotified = true;
+ }
+ try {
+ suspendLock.wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+ }
+
+ public void suspendIndexing() {
+ synchronized (suspendLock) {
+ suspend++;
+ }
+ }
+
+ public void resumeIndexing() {
+ synchronized (suspendLock) {
+ if (--suspend == 0) {
+ suspendLock.notifyAll();
+ }
+ }
+ }
+
+ //update indexes, either initially or after a classpath change:
+ private void refreshIndexes(int version) {
+ try {
+ Collection<Path> paths = new ArrayList<>();
+ MemoryFileManager fm = proc.taskFactory.fileManager();
+
+ appendPaths(fm, StandardLocation.PLATFORM_CLASS_PATH, paths);
+ appendPaths(fm, StandardLocation.CLASS_PATH, paths);
+ appendPaths(fm, StandardLocation.SOURCE_PATH, paths);
+
+ Map<Path, ClassIndex> newIndexes = new HashMap<>();
+
+ //setup existing/last known data:
+ for (Path p : paths) {
+ ClassIndex index = PATH_TO_INDEX.get(p);
+ if (index != null) {
+ newIndexes.put(p, index);
+ }
+ }
+
+ synchronized (currentIndexes) {
+ //temporary setting old data:
+ currentIndexes.clear();
+ currentIndexes.putAll(newIndexes);
+ }
+
+ //update/compute the indexes if needed:
+ for (Path p : paths) {
+ waitIndexingNotSuspended();
+
+ ClassIndex index = indexForPath(p);
+ newIndexes.put(p, index);
+ }
+
+ synchronized (currentIndexes) {
+ currentIndexes.clear();
+ currentIndexes.putAll(newIndexes);
+ }
+ } catch (Exception ex) {
+ proc.debug(ex, "SourceCodeAnalysisImpl.refreshIndexes(" + version + ")");
+ } finally {
+ synchronized (currentIndexes) {
+ indexVersion = version;
+ }
+ }
+ }
+
+ private void appendPaths(MemoryFileManager fm, Location loc, Collection<Path> paths) {
+ Iterable<? extends Path> locationPaths = fm.getLocationAsPaths(loc);
+ if (locationPaths == null)
+ return ;
+ for (Path path : locationPaths) {
+ if (".".equals(path.toString())) {
+ //skip CWD
+ continue;
+ }
+
+ paths.add(path);
+ }
+ }
+
+ //create/update index a given JavaFileManager entry (which may be a JDK installation, a jar/zip file or a directory):
+ //if an index exists for the given entry, the existing index is kept unless the timestamp is modified
+ private ClassIndex indexForPath(Path path) {
+ if (isJRTMarkerFile(path)) {
+ FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
+ Path modules = jrtfs.getPath("modules");
+ return PATH_TO_INDEX.compute(path, (p, index) -> {
+ try {
+ long lastModified = Files.getLastModifiedTime(modules).toMillis();
+ if (index == null || index.timestamp != lastModified) {
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(modules)) {
+ index = doIndex(lastModified, path, stream);
+ }
+ }
+ return index;
+ } catch (IOException ex) {
+ proc.debug(ex, "SourceCodeAnalysisImpl.indexesForPath(" + path.toString() + ")");
+ return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap());
+ }
+ });
+ } else if (!Files.isDirectory(path)) {
+ if (Files.exists(path)) {
+ return PATH_TO_INDEX.compute(path, (p, index) -> {
+ try {
+ long lastModified = Files.getLastModifiedTime(p).toMillis();
+ if (index == null || index.timestamp != lastModified) {
+ ClassLoader cl = SourceCodeAnalysisImpl.class.getClassLoader();
+
+ try (FileSystem zip = FileSystems.newFileSystem(path, cl)) {
+ index = doIndex(lastModified, path, zip.getRootDirectories());
+ }
+ }
+ return index;
+ } catch (IOException ex) {
+ proc.debug(ex, "SourceCodeAnalysisImpl.indexesForPath(" + path.toString() + ")");
+ return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap());
+ }
+ });
+ } else {
+ return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap());
+ }
+ } else {
+ return PATH_TO_INDEX.compute(path, (p, index) -> {
+ //no persistence for directories, as we cannot check timestamps:
+ if (index == null) {
+ index = doIndex(-1, path, Arrays.asList(p));
+ }
+ return index;
+ });
+ }
+ }
+
+ static boolean isJRTMarkerFile(Path path) {
+ return path.equals(Paths.get("JRT_MARKER_FILE"));
+ }
+
+ //create an index based on the content of the given dirs; the original JavaFileManager entry is originalPath.
+ private ClassIndex doIndex(long timestamp, Path originalPath, Iterable<? extends Path> dirs) {
+ Set<String> packages = new HashSet<>();
+ Map<String, Collection<String>> classSimpleName2FQN = new HashMap<>();
+
+ for (Path d : dirs) {
+ try {
+ Files.walkFileTree(d, new FileVisitor<Path>() {
+ int depth;
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ waitIndexingNotSuspended();
+ if (depth++ == 0)
+ return FileVisitResult.CONTINUE;
+ String dirName = dir.getFileName().toString();
+ String sep = dir.getFileSystem().getSeparator();
+ dirName = dirName.endsWith(sep) ? dirName.substring(0, dirName.length() - sep.length())
+ : dirName;
+ if (SourceVersion.isIdentifier(dirName))
+ return FileVisitResult.CONTINUE;
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ waitIndexingNotSuspended();
+ if (file.getFileName().toString().endsWith(".class")) {
+ String relativePath = d.relativize(file).toString();
+ String binaryName = relativePath.substring(0, relativePath.length() - 6).replace('/', '.');
+ int packageDot = binaryName.lastIndexOf('.');
+ if (packageDot > (-1)) {
+ packages.add(binaryName.substring(0, packageDot));
+ }
+ String typeName = binaryName.replace('$', '.');
+ addClassName2Map(classSimpleName2FQN, typeName);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ depth--;
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException ex) {
+ proc.debug(ex, "doIndex(" + d.toString() + ")");
+ }
+ }
+
+ return new ClassIndex(timestamp, originalPath, packages, classSimpleName2FQN);
+ }
+
+ private static void addClassName2Map(Map<String, Collection<String>> classSimpleName2FQN, String typeName) {
+ int simpleNameDot = typeName.lastIndexOf('.');
+ classSimpleName2FQN.computeIfAbsent(typeName.substring(simpleNameDot + 1), n -> new LinkedHashSet<>())
+ .add(typeName);
+ }
+
+ //holder for indexed data about a given path
+ public static final class ClassIndex {
+ public final long timestamp;
+ public final Path forPath;
+ public final Set<String> packages;
+ public final Map<String, Collection<String>> classSimpleName2FQN;
+
+ public ClassIndex(long timestamp, Path forPath, Set<String> packages, Map<String, Collection<String>> classSimpleName2FQN) {
+ this.timestamp = timestamp;
+ this.forPath = forPath;
+ this.packages = packages;
+ this.classSimpleName2FQN = classSimpleName2FQN;
+ }
+
+ }
+
+ //for tests, to be able to wait until the indexing finishes:
+ public void waitBackgroundTaskFinished() throws Exception {
+ boolean upToDate;
+ synchronized (currentIndexes) {
+ upToDate = classpathVersion == indexVersion;
+ }
+ while (!upToDate) {
+ INDEXER.submit(() -> {}).get();
+ synchronized (currentIndexes) {
+ upToDate = classpathVersion == indexVersion;
+ }
+ }
+ }
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java Sat Mar 05 20:46:44 2016 -0800
@@ -41,13 +41,14 @@
import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
-import com.sun.tools.javac.util.JavacMessages;
import com.sun.tools.javac.util.Name;
import static jdk.jshell.Util.isDoIt;
+import jdk.jshell.TaskFactory.AnalyzeTask;
import jdk.jshell.Wrap.Range;
+
import java.util.List;
import java.util.Locale;
-import java.util.function.BinaryOperator;
+
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.lang.model.type.TypeMirror;
@@ -209,7 +210,7 @@
}
- ExpressionInfo typeOfReturnStatement(JavacMessages messages, BinaryOperator<String> fullClassNameAndPackageToClass) {
+ ExpressionInfo typeOfReturnStatement(AnalyzeTask at, JShell state) {
ExpressionInfo ei = new ExpressionInfo();
Tree unitTree = firstStatement();
if (unitTree instanceof ReturnTree) {
@@ -219,9 +220,7 @@
if (viPath != null) {
TypeMirror tm = trees().getTypeMirror(viPath);
if (tm != null) {
- Type type = (Type)tm;
- TypePrinter tp = new TypePrinter(messages, fullClassNameAndPackageToClass, type);
- ei.typeName = tp.visit(type, Locale.getDefault());
+ ei.typeName = printType(at, state, tm);
switch (tm.getKind()) {
case VOID:
case NONE:
@@ -263,6 +262,12 @@
return sg.toString();
}
+ public static String printType(AnalyzeTask at, JShell state, TypeMirror type) {
+ Type typeImpl = (Type) type;
+ TypePrinter tp = new TypePrinter(at.messages(), state.maps::fullClassNameAndPackageToClass, typeImpl);
+ return tp.visit(typeImpl, Locale.getDefault());
+ }
+
/**
* Signature Generation
*/
--- a/langtools/test/TEST.groups Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/TEST.groups Sat Mar 05 20:46:44 2016 -0800
@@ -22,15 +22,17 @@
# Tiered testing definitions
-# All langtools tests are tier 1.
+# (Nearly) all langtools tests are tier 1.
tier1 = \
com \
jdk \
lib \
- tools
+ tools \
+ -jdk/jshell/ToolReloadTest.java
-# No langtools tests are tier 2.
-tier2 =
+# (Almost) no langtools tests are tier 2.
+tier2 = \
+ jdk/jshell/ToolReloadTest.java
# No langtools tests are tier 3 either.
tier3 =
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/ComputeFQNsTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015, 2016, 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 8131027
+ * @summary Test Get FQNs
+ * @library /tools/lib
+ * @build KullaTesting TestingInputStream ToolBox Compiler
+ * @run testng ComputeFQNsTest
+ */
+
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+@Test
+public class ComputeFQNsTest extends KullaTesting {
+
+ private final Compiler compiler = new Compiler();
+ private final Path outDir = Paths.get("ComputeFQNsTest");
+
+ public void testAddImport() throws Exception {
+ compiler.compile(outDir, "package test1; public class TestClass { }", "package test2; public class TestClass { }");
+ String jarName = "test.jar";
+ compiler.jar(outDir, jarName, "test1/TestClass.class", "test2/TestClass.class");
+ addToClasspath(compiler.getPath(outDir).resolve(jarName));
+
+ assertInferredFQNs("LinkedList", "java.util.LinkedList");
+ assertInferredFQNs("ArrayList", "java.util.ArrayList");
+ assertInferredFQNs("TestClass", "test1.TestClass", "test2.TestClass");
+ assertInferredFQNs("CharSequence", "CharSequence".length(), true, "java.lang.CharSequence");
+ assertInferredFQNs("unresolvable");
+ assertInferredFQNs("void test(ArrayList", "ArrayList".length(), false, "java.util.ArrayList");
+ assertInferredFQNs("void test(ArrayList l) throws InvocationTargetException", "InvocationTargetException".length(), false, "java.lang.reflect.InvocationTargetException");
+ assertInferredFQNs("void test(ArrayList l) { ArrayList", "ArrayList".length(), false, "java.util.ArrayList");
+ assertInferredFQNs("<T extends ArrayList", "ArrayList".length(), false, "java.util.ArrayList");
+ assertInferredFQNs("Object l = Arrays", "Arrays".length(), false, "java.util.Arrays");
+ assertInferredFQNs("class X<T extends ArrayList", "ArrayList".length(), false, "java.util.ArrayList");
+ assertInferredFQNs("class X extends ArrayList", "ArrayList".length(), false, "java.util.ArrayList");
+ assertInferredFQNs("class X extends java.util.ArrayList<TypeElement", "TypeElement".length(), false, "javax.lang.model.element.TypeElement");
+ assertInferredFQNs("class X extends java.util.ArrayList<TypeMirror, TypeElement", "TypeElement".length(), false, "javax.lang.model.element.TypeElement");
+ assertInferredFQNs("class X implements TypeElement", "TypeElement".length(), false, "javax.lang.model.element.TypeElement");
+ assertInferredFQNs("class X implements TypeMirror, TypeElement", "TypeElement".length(), false, "javax.lang.model.element.TypeElement");
+ assertInferredFQNs("class X implements java.util.List<TypeElement", "TypeElement".length(), false, "javax.lang.model.element.TypeElement");
+ assertInferredFQNs("class X implements java.util.List<TypeMirror, TypeElement", "TypeElement".length(), false, "javax.lang.model.element.TypeElement");
+ assertInferredFQNs("class X { ArrayList", "ArrayList".length(), false, "java.util.ArrayList");
+ }
+
+ @Test(enabled = false) //JDK-8150860
+ public void testSuspendIndexing() throws Exception {
+ compiler.compile(outDir, "package test; public class FQNTest { }");
+ String jarName = "test.jar";
+ compiler.jar(outDir, jarName, "test/FQNTest.class");
+ Path continueMarkFile = outDir.resolve("continuemark").toAbsolutePath();
+ Files.createDirectories(continueMarkFile.getParent());
+ try (Writer w = Files.newBufferedWriter(continueMarkFile)) {}
+
+ Path runMarkFile = outDir.resolve("runmark").toAbsolutePath();
+ Files.deleteIfExists(runMarkFile);
+
+ getState().sourceCodeAnalysis();
+
+ new Thread() {
+ @Override public void run() {
+ assertEval("{new java.io.FileOutputStream(\"" + runMarkFile.toAbsolutePath().toString() + "\").close();" +
+ " while (java.nio.file.Files.exists(java.nio.file.Paths.get(\"" + continueMarkFile.toString() + "\"))) Thread.sleep(100); }");
+ }
+ }.start();
+
+ while (!Files.exists(runMarkFile))
+ Thread.sleep(100);
+
+ addToClasspath(compiler.getPath(outDir).resolve(jarName));
+
+ String code = "FQNTest";
+
+ QualifiedNames candidates = getAnalysis().listQualifiedNames(code, code.length());
+
+ assertEquals(candidates.getNames(), Arrays.asList(), "Input: " + code + ", candidates=" + candidates.getNames());
+ assertEquals(candidates.isUpToDate(), false, "Input: " + code + ", up-to-date=" + candidates.isUpToDate());
+
+ Files.delete(continueMarkFile);
+
+ waitIndexingFinished();
+
+ candidates = getAnalysis().listQualifiedNames(code, code.length());
+
+ assertEquals(candidates.getNames(), Arrays.asList("test.FQNTest"), "Input: " + code + ", candidates=" + candidates.getNames());
+ assertEquals(true, candidates.isUpToDate(), "Input: " + code + ", up-to-date=" + candidates.isUpToDate());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/InferTypeTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 2016, 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 8131027
+ * @summary Test Type Inference
+ * @library /tools/lib
+ * @build KullaTesting TestingInputStream ToolBox Compiler
+ * @run testng InferTypeTest
+ */
+
+import org.testng.annotations.Test;
+
+@Test
+public class InferTypeTest extends KullaTesting {
+
+ public void testTypeInference() {
+ assertInferredType("1", "int");
+ assertEval("import java.util.*;");
+ assertInferredType("new ArrayList<String>()", "ArrayList<String>");
+ assertInferredType("null", "Object");
+ assertInferredType("1 + ", null); //incomplete
+ assertInferredType("undef", null); //unresolvable
+ assertEval("List<String> l1;");
+ assertEval("List<? extends String> l2;");
+ assertEval("List<? super String> l3;");
+ assertInferredType("l1", "List<String>");
+ assertInferredType("l2", "List<? extends String>");
+ assertInferredType("l3", "List<? super String>");
+ assertInferredType("l1.get(0)", "String");
+ assertInferredType("l2.get(0)", "String");
+ assertInferredType("l3.get(0)", "Object");
+ assertInferredType("\"\" + 1", "String");
+ assertEval("int i = 0;");
+ assertInferredType("i++", "int");
+ assertInferredType("++i", "int");
+ assertInferredType("i == 0 ? l1.get(0) : l2.get(0)", "String");
+ assertInferredType("", null);
+ assertInferredType("void test() { }", null);
+ assertInferredType("class Test { }", null);
+ assertInferredType("enum Test { A; }", null);
+ assertInferredType("interface Test { }", null);
+ assertInferredType("@interface Test { }", null);
+ assertInferredType("Object o;", null);
+ }
+
+}
--- a/langtools/test/jdk/jshell/KullaTesting.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/jdk/jshell/KullaTesting.java Sat Mar 05 20:46:44 2016 -0800
@@ -24,6 +24,7 @@
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.StringWriter;
+import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
@@ -61,6 +62,7 @@
import jdk.jshell.SourceCodeAnalysis;
import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
import jdk.jshell.SourceCodeAnalysis.Completeness;
+import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
import jdk.jshell.SourceCodeAnalysis.Suggestion;
import jdk.jshell.UnresolvedReferenceException;
import org.testng.annotations.AfterMethod;
@@ -862,6 +864,8 @@
}
private List<String> computeCompletions(String code, Boolean isSmart) {
+ waitIndexingFinished();
+
int cursor = code.indexOf('|');
code = code.replace("|", "");
assertTrue(cursor > -1, "'|' expected, but not found in: " + code);
@@ -874,6 +878,37 @@
.collect(Collectors.toList());
}
+ public void assertInferredType(String code, String expectedType) {
+ String inferredType = getAnalysis().analyzeType(code, code.length());
+
+ assertEquals(inferredType, expectedType, "Input: " + code + ", " + inferredType);
+ }
+
+ public void assertInferredFQNs(String code, String... fqns) {
+ assertInferredFQNs(code, code.length(), false, fqns);
+ }
+
+ public void assertInferredFQNs(String code, int simpleNameLen, boolean resolvable, String... fqns) {
+ waitIndexingFinished();
+
+ QualifiedNames candidates = getAnalysis().listQualifiedNames(code, code.length());
+
+ assertEquals(candidates.getNames(), Arrays.asList(fqns), "Input: " + code + ", candidates=" + candidates.getNames());
+ assertEquals(candidates.getSimpleNameLength(), simpleNameLen, "Input: " + code + ", simpleNameLen=" + candidates.getSimpleNameLength());
+ assertEquals(candidates.isResolvable(), resolvable, "Input: " + code + ", resolvable=" + candidates.isResolvable());
+ }
+
+ protected void waitIndexingFinished() {
+ try {
+ Method waitBackgroundTaskFinished = getAnalysis().getClass().getDeclaredMethod("waitBackgroundTaskFinished");
+
+ waitBackgroundTaskFinished.setAccessible(true);
+ waitBackgroundTaskFinished.invoke(getAnalysis());
+ } catch (Exception ex) {
+ throw new AssertionError("Cannot wait for indexing end.", ex);
+ }
+ }
+
public void assertDocumentation(String code, String... expected) {
int cursor = code.indexOf('|');
code = code.replace("|", "");
--- a/langtools/test/jdk/jshell/ToolReloadTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/jdk/jshell/ToolReloadTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -23,6 +23,7 @@
/*
* @test
+ * @key intermittent
* @bug 8081845 8147898
* @summary Tests for /reload in JShell tool
* @modules jdk.compiler/com.sun.tools.javac.api
--- a/langtools/test/tools/javac/6257443/T6257443.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/tools/javac/6257443/T6257443.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -31,13 +31,7 @@
*
* @clean foo.package-info
*
- * @compile -XD-printflat package-info.java
- * @run main/othervm T6257443 -no foo/package-info.class
- *
- * @compile -XD-stubs package-info.java
- * @run main/othervm T6257443 -no foo/package-info.class
- *
- * @compile -XD-printsource package-info.java
+ * @compile -printsource package-info.java
* @run main/othervm T6257443 -no foo/package-info.class
*/
--- a/langtools/test/tools/javac/6521805/T6521805a.java Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6521805
- * @summary Regression: JDK5/JDK6 javac allows write access to outer class reference
- * @author mcimadamore
- *
- * @compile/fail/ref=T6521805a_1.out T6521805a.java -XDrawDiagnostics
- * @compile/ref=T6521805a_2.out T6521805a.java -XDwarnOnSyntheticConflicts -XDrawDiagnostics
- */
-
-class T6521805a {
-
- static class Outer {
- T6521805a this$0 = null;
- }
-
- public class Inner extends Outer {
- public void foo() {
- this$0 = new T6521805a();
- }
- }
-}
--- a/langtools/test/tools/javac/6521805/T6521805a_1.out Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-T6521805a.java:17:12: compiler.err.synthetic.name.conflict: this$0, T6521805a.Outer
-1 error
--- a/langtools/test/tools/javac/6521805/T6521805a_2.out Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-T6521805a.java:17:12: compiler.warn.synthetic.name.conflict: this$0, T6521805a.Outer
-1 warning
--- a/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -61,8 +61,6 @@
test(null, Arrays.asList(a, b));
test(null, Arrays.asList(b, a));
- test(Arrays.asList("-XD-relax"), Arrays.asList(a, b));
- test(Arrays.asList("-XD-relax"), Arrays.asList(b, a));
for (CompileState stop : CompileState.values()) {
test(Arrays.asList("-XDshouldStopPolicyIfNoError=" + stop,
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Sat Mar 05 20:46:44 2016 -0800
@@ -231,22 +231,15 @@
"compiler.err.type.var.more.than.once.in.result", // UNUSED
"compiler.misc.non.denotable.type", // UNUSED
"compiler.misc.unnamed.package", // should be required, CR 6964147
- "compiler.misc.verbose.retro", // UNUSED
- "compiler.misc.verbose.retro.with", // UNUSED
- "compiler.misc.verbose.retro.with.list", // UNUSED
"compiler.warn.proc.type.already.exists", // TODO in JavacFiler
"javac.err.invalid.arg", // UNUSED ??
"javac.opt.arg.class", // UNUSED ??
"javac.opt.arg.pathname", // UNUSED ??
"javac.opt.moreinfo", // option commented out
"javac.opt.nogj", // UNUSED
- "javac.opt.printflat", // option commented out
"javac.opt.printsearch", // option commented out
"javac.opt.prompt", // option commented out
- "javac.opt.retrofit", // UNUSED
- "javac.opt.s", // option commented out
- "javac.opt.scramble", // option commented out
- "javac.opt.scrambleall" // option commented out
+ "javac.opt.s" // option commented out
));
/**
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Sat Mar 05 20:46:44 2016 -0800
@@ -86,9 +86,6 @@
compiler.misc.undecl.type.var # ClassReader
compiler.misc.unicode.str.not.supported # ClassReader
compiler.misc.malformed.vararg.method # ClassReader
-compiler.misc.verbose.retro # UNUSED
-compiler.misc.verbose.retro.with # UNUSED
-compiler.misc.verbose.retro.with.list # UNUSED
compiler.misc.version.not.available # JavaCompiler; implies build error
compiler.misc.where.description.captured
compiler.misc.where.typevar.1
--- a/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java Sat Mar 05 10:10:20 2016 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-// key: compiler.warn.synthetic.name.conflict
-// options: -XDwarnOnSyntheticConflicts
-
-class WarnSyntheticNameConflict {
-
- static class Outer {
- WarnSyntheticNameConflict this$0 = null;
- }
-
- public class Inner extends Outer { }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/file/T8150475.java Sat Mar 05 20:46:44 2016 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 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
+ * @compile -sourcepath / T8150475.java
+ */
+
+class T8150475 { }
+
--- a/langtools/test/tools/sjavac/IdleShutdown.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/tools/sjavac/IdleShutdown.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -65,11 +65,11 @@
// Use Sjavac object and wait less than TIMEOUT_MS in between calls
Thread.sleep(TIMEOUT_MS - 1000);
log("Compiling");
- service.compile(new String[0], null, null);
+ service.compile(new String[0]);
Thread.sleep(TIMEOUT_MS - 1000);
log("Compiling");
- service.compile(new String[0], null, null);
+ service.compile(new String[0]);
if (timeoutTimestamp.get() != -1)
throw new AssertionError("Premature timeout detected.");
@@ -103,7 +103,7 @@
public void shutdown() {
}
@Override
- public int compile(String[] args, Writer out, Writer err) {
+ public int compile(String[] args) {
// Attempt to trigger idle timeout during a call by sleeping
try {
Thread.sleep(TIMEOUT_MS + 1000);
--- a/langtools/test/tools/sjavac/PooledExecution.java Sat Mar 05 10:10:20 2016 +0100
+++ b/langtools/test/tools/sjavac/PooledExecution.java Sat Mar 05 20:46:44 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,10 +30,12 @@
* @build Wrapper
* @run main Wrapper PooledExecution
*/
+import java.io.PrintWriter;
import java.io.Writer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
+import com.sun.tools.sjavac.Log;
import com.sun.tools.sjavac.comp.PooledSjavac;
import com.sun.tools.sjavac.server.Sjavac;
@@ -67,7 +69,7 @@
for (int i = 0; i < NUM_REQUESTS; i++) {
tasks[i] = new Thread() {
public void run() {
- service.compile(new String[0], null, null);
+ service.compile(new String[0]);
tasksFinished.incrementAndGet();
}
};
@@ -109,7 +111,7 @@
AtomicInteger activeRequests = new AtomicInteger(0);
@Override
- public int compile(String[] args, Writer out, Writer err) {
+ public int compile(String[] args) {
leftToStart.countDown();
int numActiveRequests = activeRequests.incrementAndGet();
System.out.printf("Left to start: %2d / Currently active: %2d%n",
--- a/make/Init.gmk Sat Mar 05 10:10:20 2016 +0100
+++ b/make/Init.gmk Sat Mar 05 20:46:44 2016 -0800
@@ -154,6 +154,9 @@
# Do nothing
endif
+ # Do not let make delete spec files even if aborted while doing a reconfigure
+ .PRECIOUS: $(SPECS)
+
# Unless reconfigure is explicitely called, let all main targets depend on
# the spec files to be up to date.
ifeq ($(findstring reconfigure, $(INIT_TARGETS)), )
--- a/make/common/CORE_PKGS.gmk Sat Mar 05 10:10:20 2016 +0100
+++ b/make/common/CORE_PKGS.gmk Sat Mar 05 20:46:44 2016 -0800
@@ -103,6 +103,7 @@
java.lang.reflect \
java.math \
java.net \
+ java.net.http \
java.net.spi \
java.nio \
java.nio.channels \
--- a/make/common/NativeCompilation.gmk Sat Mar 05 10:10:20 2016 +0100
+++ b/make/common/NativeCompilation.gmk Sat Mar 05 20:46:44 2016 -0800
@@ -651,12 +651,15 @@
$$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE)
$$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET))))
+ $$(call MakeDir, $$(@D) $$($1_OBJECT_DIR))
$$(call ExecuteWithLog, $$@, \
$$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \
$$($1_VERSIONINFO_RESOURCE))
# Windows RC compiler does not support -showIncludes, so we mis-use CL for this.
- $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
- $(CC_OUT_OPTION)$$($1_RES_DEP).obj $$($1_VERSIONINFO_RESOURCE) > $$($1_RES_DEP).raw 2>&1 || true ; \
+ $$(call ExecuteWithLog, $$($1_RES_DEP).obj, \
+ $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
+ $(CC_OUT_OPTION)$$($1_RES_DEP).obj -P -Fi$$($1_RES_DEP).pp \
+ $$($1_VERSIONINFO_RESOURCE)) > $$($1_RES_DEP).raw 2>&1 || true ; \
$(ECHO) $$($1_RES): \\ > $$($1_RES_DEP) ; \
$(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).raw >> $$($1_RES_DEP) ; \
$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS)
@@ -670,7 +673,7 @@
$1_REAL_MAPFILE := $$($1_OBJECT_DIR)/mapfile
$$($1_REAL_MAPFILE) : $$($1_MAPFILE) $$($1_REORDER)
- $$(MKDIR) -p $$(@D)
+ $$(call MakeDir, $$(@D))
$$(CP) $$($1_MAPFILE) $$@.tmp
$$(SED) -e 's=OUTPUTDIR=$$($1_OBJECT_DIR)=' $$($1_REORDER) >> $$@.tmp
$$(MV) $$@.tmp $$@
@@ -768,7 +771,10 @@
$1_EXTRA_LDFLAGS += "-implib:$$($1_OBJECT_DIR)/$$($1_LIBRARY).lib"
endif
- $1_EXTRA_LIBS += $(GLOBAL_LIBS)
+ # Create loadmap on AIX. Helps in diagnosing some problems.
+ ifneq ($(COMPILER_BINDCMD_FILE_FLAG),)
+ $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap
+ endif
$1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
$$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_CREATE_DEBUGINFO_CMDS) \
@@ -846,8 +852,6 @@
ifneq (,$$($1_PROGRAM))
# A executable binary has been specified, setup the target for it.
- $1_EXTRA_LIBS += $(GLOBAL_LIBS)
-
$1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
$$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \
$$($1_CODESIGN) $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \
--- a/modules.xml Sat Mar 05 10:10:20 2016 +0100
+++ b/modules.xml Sat Mar 05 20:46:44 2016 -0800
@@ -316,6 +316,10 @@
<to>java.instrument</to>
</export>
<export>
+ <name>sun.net</name>
+ <to>java.httpclient</to>
+ </export>
+ <export>
<name>sun.net.dns</name>
<to>java.security.jgss</to>
<to>jdk.naming.dns</to>
@@ -496,6 +500,7 @@
<to>java.logging</to>
<to>java.management</to>
<to>java.prefs</to>
+ <to>java.httpclient</to>
</export>
<export>
<name>sun.util.resources</name>
@@ -520,6 +525,7 @@
<depend re-exports="true">java.compact2</depend>
<depend re-exports="true">java.compiler</depend>
<depend re-exports="true">java.instrument</depend>
+ <depend re-exports="true">java.httpclient</depend>
<depend re-exports="true">java.management</depend>
<depend re-exports="true">java.naming</depend>
<depend re-exports="true">java.prefs</depend>
@@ -838,6 +844,13 @@
</export>
</module>
<module>
+ <name>java.httpclient</name>
+ <depend>java.base</depend>
+ <export>
+ <name>java.net.http</name>
+ </export>
+ </module>
+ <module>
<name>java.instrument</name>
<depend>java.base</depend>
<export>
--- a/nashorn/.hgtags Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/.hgtags Sat Mar 05 20:46:44 2016 -0800
@@ -340,3 +340,4 @@
a618d3e89fdea5361895ef142a59074fe7ae3d98 jdk-9+104
4e9749cc32f15251d9b2d0eab4373529952902a3 jdk-9+105
cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106
+8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107
--- a/nashorn/make/build.xml Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/make/build.xml Sat Mar 05 20:46:44 2016 -0800
@@ -242,6 +242,7 @@
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
additionalparam="-quiet" failonerror="true" useexternalfile="true">
+ <arg value="${javadoc.option}"/>
<classpath>
<pathelement location="${build.classes.dir}"/>
</classpath>
@@ -261,6 +262,7 @@
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
additionalparam="-quiet" failonerror="true" useexternalfile="true">
+ <arg value="${javadoc.option}"/>
<classpath>
<pathelement location="${build.classes.dir}"/>
</classpath>
@@ -276,6 +278,7 @@
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${nashorn.module.src.dir}/overview.html"
extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
additionalparam="-quiet" failonerror="true" useexternalfile="true">
+ <arg value="${javadoc.option}"/>
<classpath>
<pathelement location="${build.classes.dir}"/>
</classpath>
@@ -289,6 +292,7 @@
<javadoc destdir="${dist.javadoc.dir}" use="yes"
windowtitle="Dynalink"
additionalparam="-quiet" failonerror="true" useexternalfile="true">
+ <arg value="${javadoc.option}"/>
<classpath>
<pathelement location="${build.classes.dir}"/>
</classpath>
--- a/nashorn/make/project.properties Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/make/project.properties Sat Mar 05 20:46:44 2016 -0800
@@ -34,6 +34,8 @@
javac.source=1.8
javac.target=1.8
+javadoc.option=-tag "implSpec:a:Implementation Requirements:"
+
# nashorn version information
nashorn.version=0.1
nashorn.fullversion=0.1
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java Sat Mar 05 20:46:44 2016 -0800
@@ -27,6 +27,7 @@
import java.util.Collection;
import java.util.Collections;
+import java.util.Objects;
import java.util.Set;
/**
@@ -34,19 +35,19 @@
*
* This class can also be subclassed by an arbitrary Java class. Nashorn will
* treat objects of such classes just like nashorn script objects. Usual nashorn
- * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued
+ * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be delegated
* to appropriate method call of this class.
*
* @since 1.8u40
*/
public abstract class AbstractJSObject implements JSObject {
/**
- * Call this object as a JavaScript function. This is equivalent to
- * 'func.apply(thiz, args)' in JavaScript.
- *
- * @param thiz 'this' object to be passed to the function
- * @param args arguments to method
- * @return result of call
+ * The default constructor.
+ */
+ public AbstractJSObject() {}
+
+ /**
+ * @implSpec This implementation always throws UnsupportedOperationException
*/
@Override
public Object call(final Object thiz, final Object... args) {
@@ -54,11 +55,7 @@
}
/**
- * Call this 'constructor' JavaScript function to create a new object.
- * This is equivalent to 'new func(arg1, arg2...)' in JavaScript.
- *
- * @param args arguments to method
- * @return result of constructor call
+ * @implSpec This implementation always throws UnsupportedOperationException
*/
@Override
public Object newObject(final Object... args) {
@@ -66,10 +63,7 @@
}
/**
- * Evaluate a JavaScript expression.
- *
- * @param s JavaScript expression to evaluate
- * @return evaluation result
+ * @implSpec This imlementation always throws UnsupportedOperationException
*/
@Override
public Object eval(final String s) {
@@ -77,21 +71,16 @@
}
/**
- * Retrieves a named member of this JavaScript object.
- *
- * @param name of member
- * @return member
+ * @implSpec This implementation always returns null
*/
@Override
public Object getMember(final String name) {
+ Objects.requireNonNull(name);
return null;
}
/**
- * Retrieves an indexed member of this JavaScript object.
- *
- * @param index index slot to retrieve
- * @return member
+ * @implSpec This implementation always returns null
*/
@Override
public Object getSlot(final int index) {
@@ -99,21 +88,16 @@
}
/**
- * Does this object have a named member?
- *
- * @param name name of member
- * @return true if this object has a member of the given name
+ * @implSpec This implementation always returns false
*/
@Override
public boolean hasMember(final String name) {
+ Objects.requireNonNull(name);
return false;
}
/**
- * Does this object have a indexed property?
- *
- * @param slot index to check
- * @return true if this object has a slot
+ * @implSpec This implementation always returns false
*/
@Override
public boolean hasSlot(final int slot) {
@@ -121,31 +105,25 @@
}
/**
- * Remove a named member from this JavaScript object
- *
- * @param name name of the member
+ * @implSpec This implementation is a no-op
*/
@Override
public void removeMember(final String name) {
+ Objects.requireNonNull(name);
//empty
}
/**
- * Set a named member in this JavaScript object
- *
- * @param name name of the member
- * @param value value of the member
+ * @implSpec This implementation is a no-op
*/
@Override
public void setMember(final String name, final Object value) {
+ Objects.requireNonNull(name);
//empty
}
/**
- * Set an indexed member in this JavaScript object
- *
- * @param index index of the member slot
- * @param value value of the member
+ * @implSpec This implementation is a no-op
*/
@Override
public void setSlot(final int index, final Object value) {
@@ -155,9 +133,7 @@
// property and value iteration
/**
- * Returns the set of all property names of this object.
- *
- * @return set of property names
+ * @implSpec This implementation returns empty set
*/
@Override
public Set<String> keySet() {
@@ -165,9 +141,7 @@
}
/**
- * Returns the set of all property values of this object.
- *
- * @return set of property values.
+ * @implSpec This implementation returns empty set
*/
@Override
public Collection<Object> values() {
@@ -177,22 +151,13 @@
// JavaScript instanceof check
/**
- * Checking whether the given object is an instance of 'this' object.
- *
- * @param instance instance to check
- * @return true if the given 'instance' is an instance of this 'function' object
+ * @implSpec This implementation always returns false
*/
@Override
public boolean isInstance(final Object instance) {
return false;
}
- /**
- * Checking whether this object is an instance of the given 'clazz' object.
- *
- * @param clazz clazz to check
- * @return true if this object is an instance of the given 'clazz'
- */
@Override
public boolean isInstanceOf(final Object clazz) {
if (clazz instanceof JSObject) {
@@ -202,20 +167,13 @@
return false;
}
- /**
- * ECMA [[Class]] property
- *
- * @return ECMA [[Class]] property value of this object
- */
@Override
public String getClassName() {
return getClass().getName();
}
/**
- * Is this a function object?
- *
- * @return if this mirror wraps a ECMAScript function instance
+ * @implSpec This implementation always returns false
*/
@Override
public boolean isFunction() {
@@ -223,9 +181,7 @@
}
/**
- * Is this a 'use strict' function object?
- *
- * @return true if this mirror represents a ECMAScript 'use strict' function
+ * @implSpec This implementation always returns false
*/
@Override
public boolean isStrictFunction() {
@@ -233,9 +189,7 @@
}
/**
- * Is this an array object?
- *
- * @return if this mirror wraps a ECMAScript array object
+ * @implSpec This implementation always returns false
*/
@Override
public boolean isArray() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java Sat Mar 05 20:46:44 2016 -0800
@@ -32,7 +32,7 @@
/**
* This interface can be implemented by an arbitrary Java class. Nashorn will
* treat objects of such classes just like nashorn script objects. Usual nashorn
- * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued
+ * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be delegated
* to appropriate method call of this interface.
*
* @since 1.8u40
@@ -42,7 +42,7 @@
* Call this object as a JavaScript function. This is equivalent to
* 'func.apply(thiz, args)' in JavaScript.
*
- * @param thiz 'this' object to be passed to the function
+ * @param thiz 'this' object to be passed to the function. This may be null.
* @param args arguments to method
* @return result of call
*/
@@ -70,6 +70,7 @@
*
* @param name of member
* @return member
+ * @throws NullPointerException if name is null
*/
public Object getMember(final String name);
@@ -101,6 +102,7 @@
* Remove a named member from this JavaScript object
*
* @param name name of the member
+ * @throws NullPointerException if name is null
*/
public void removeMember(final String name);
@@ -109,6 +111,7 @@
*
* @param name name of the member
* @param value value of the member
+ * @throws NullPointerException if name is null
*/
public void setMember(final String name, final Object value);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java Sat Mar 05 20:46:44 2016 -0800
@@ -46,6 +46,8 @@
*/
@SuppressWarnings("serial")
public abstract class NashornException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
// script file name
private String fileName;
// script line number
@@ -58,7 +60,7 @@
private Object ecmaError;
/**
- * Constructor
+ * Constructor to initialize error message, file name, line and column numbers.
*
* @param msg exception message
* @param fileName file name
@@ -70,7 +72,7 @@
}
/**
- * Constructor
+ * Constructor to initialize error message, cause exception, file name, line and column numbers.
*
* @param msg exception message
* @param cause exception cause
@@ -86,7 +88,7 @@
}
/**
- * Constructor
+ * Constructor to initialize error message and cause exception.
*
* @param msg exception message
* @param cause exception cause
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Sat Mar 05 20:46:44 2016 -0800
@@ -154,7 +154,7 @@
}
/**
- * Create a new Script engine initialized by given class loader.
+ * Create a new Script engine initialized with the given class loader.
*
* @param appLoader class loader to be used as script "app" class loader.
* @return newly created script engine.
@@ -167,7 +167,7 @@
}
/**
- * Create a new Script engine initialized by given class filter.
+ * Create a new Script engine initialized with the given class filter.
*
* @param classFilter class filter to use.
* @return newly created script engine.
@@ -181,7 +181,7 @@
}
/**
- * Create a new Script engine initialized by given arguments.
+ * Create a new Script engine initialized with the given arguments.
*
* @param args arguments array passed to script engine.
* @return newly created script engine.
@@ -195,7 +195,7 @@
}
/**
- * Create a new Script engine initialized by given arguments.
+ * Create a new Script engine initialized with the given arguments and the given class loader.
*
* @param args arguments array passed to script engine.
* @param appLoader class loader to be used as script "app" class loader.
@@ -210,7 +210,7 @@
}
/**
- * Create a new Script engine initialized by given arguments.
+ * Create a new Script engine initialized with the given arguments, class loader and class filter.
*
* @param args arguments array passed to script engine.
* @param appLoader class loader to be used as script "app" class loader.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Sat Mar 05 20:46:44 2016 -0800
@@ -287,22 +287,21 @@
});
}
-
@Override
- public boolean isInstance(final Object obj) {
- if (! (obj instanceof ScriptObjectMirror)) {
+ public boolean isInstance(final Object instance) {
+ if (! (instance instanceof ScriptObjectMirror)) {
return false;
}
- final ScriptObjectMirror instance = (ScriptObjectMirror)obj;
+ final ScriptObjectMirror mirror = (ScriptObjectMirror)instance;
// if not belongs to my global scope, return false
- if (global != instance.global) {
+ if (global != mirror.global) {
return false;
}
return inGlobal(new Callable<Boolean>() {
@Override public Boolean call() {
- return sobj.isInstance(instance.sobj);
+ return sobj.isInstance(mirror.sobj);
}
});
}
@@ -653,10 +652,10 @@
}
/**
- * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
+ * Make a script object mirror on given object if needed.
*
* @param obj object to be wrapped/converted
- * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
+ * @param homeGlobal global to which this object belongs.
* @return wrapped/converted object
*/
public static Object wrap(final Object obj, final Object homeGlobal) {
@@ -664,13 +663,13 @@
}
/**
- * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. The
- * created wrapper will implement the Java {@code List} interface if {@code obj} is a JavaScript
- * {@code Array} object; this is compatible with Java JSON libraries expectations. Arrays retrieved through its
+ * Make a script object mirror on given object if needed. The created wrapper will implement
+ * the Java {@code List} interface if {@code obj} is a JavaScript {@code Array} object;
+ * this is compatible with Java JSON libraries expectations. Arrays retrieved through its
* properties (transitively) will also implement the list interface.
*
* @param obj object to be wrapped/converted
- * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
+ * @param homeGlobal global to which this object belongs.
* @return wrapped/converted object
*/
public static Object wrapAsJSONCompatible(final Object obj, final Object homeGlobal) {
@@ -678,10 +677,10 @@
}
/**
- * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
+ * Make a script object mirror on given object if needed.
*
* @param obj object to be wrapped/converted
- * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
+ * @param homeGlobal global to which this object belongs.
* @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if
* {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively)
* will also implement the list interface.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Sat Mar 05 20:46:44 2016 -0800
@@ -74,9 +74,15 @@
* @param func the function to wrap
* @param sync the object to synchronize on
* @return a synchronizing wrapper function
+ * @throws IllegalArgumentException if func does not represent a script function
*/
- public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
- return func.createSynchronized(unwrap(sync));
+ public static Object makeSynchronizedFunction(final Object func, final Object sync) {
+ final Object unwrapped = unwrap(func);
+ if (unwrapped instanceof ScriptFunction) {
+ return ((ScriptFunction)unwrapped).createSynchronized(unwrap(sync));
+ }
+
+ throw new IllegalArgumentException();
}
/**
@@ -84,9 +90,19 @@
*
* @param obj object to be wrapped
* @return wrapped object
+ * @throws IllegalArgumentException if obj cannot be wrapped
*/
- public static ScriptObjectMirror wrap(final ScriptObject obj) {
- return (ScriptObjectMirror) ScriptObjectMirror.wrap(obj, Context.getGlobal());
+ public static ScriptObjectMirror wrap(final Object obj) {
+ if (obj instanceof ScriptObjectMirror) {
+ return (ScriptObjectMirror)obj;
+ }
+
+ if (obj instanceof ScriptObject) {
+ final ScriptObject sobj = (ScriptObject)obj;
+ return (ScriptObjectMirror) ScriptObjectMirror.wrap(sobj, Context.getGlobal());
+ }
+
+ throw new IllegalArgumentException();
}
/**
@@ -135,7 +151,8 @@
* Convert the given object to the given type.
*
* @param obj object to be converted
- * @param type destination type to convert to
+ * @param type destination type to convert to. type is either a Class
+ * or nashorn representation of a Java type returned by Java.type() call in script.
* @return converted object
*/
public static Object convert(final Object obj, final Object type) {
--- a/nashorn/test/script/basic/JDK-8026367.js Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/test/script/basic/JDK-8026367.js Sat Mar 05 20:46:44 2016 -0800
@@ -37,10 +37,12 @@
// Sync called with one argument will synchronize on this-object of invocation
inc: sync(function(d) {
this.count += d;
+ Assert.assertTrue(java.lang.Thread.holdsLock(this));
}),
// Pass explicit object to synchronize on as second argument
dec: sync(function(d) {
this.count -= d;
+ Assert.assertTrue(java.lang.Thread.holdsLock(obj));
}, obj)
};
--- a/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java Sat Mar 05 10:10:20 2016 +0100
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java Sat Mar 05 20:46:44 2016 -0800
@@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package jdk.nashorn.internal.runtime.test;
+package jdk.nashorn.api.scripting.test;
import java.util.Arrays;
import javax.script.ScriptEngine;
@@ -70,4 +70,4 @@
assertEquals(RESULT, engine.eval("Function.prototype.apply.call(f, null, [1,2,3])"));
}
-}
\ No newline at end of file
+}