# HG changeset patch # User duke # Date 1499267101 -7200 # Node ID df0a816d95ef2fcf23055ef51fa82f93049d4910 # Parent 4b85cf24767355e9248b1082ddfb3abf2cb146a1# Parent c2c8c97ad733df845dff3f71d5e9da0c6ed8b266 Merge diff -r 4b85cf247673 -r df0a816d95ef .hgtags-top-repo --- a/.hgtags-top-repo Thu Dec 17 14:10:29 2009 -0800 +++ b/.hgtags-top-repo Wed Jul 05 17:05:01 2017 +0200 @@ -52,3 +52,4 @@ d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75 c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76 1f17ca8353babb13f4908c1f87d11508232518c8 jdk7-b77 +ab4ae8f4514693a9fe17ca2fec0239d8f8450d2c jdk7-b78 diff -r 4b85cf247673 -r df0a816d95ef corba/.hgtags --- a/corba/.hgtags Thu Dec 17 14:10:29 2009 -0800 +++ b/corba/.hgtags Wed Jul 05 17:05:01 2017 +0200 @@ -52,3 +52,4 @@ 0fb137085952c8e47878e240d1cb40f14de463c4 jdk7-b75 937144222e2219939101b0129d26a872a7956b13 jdk7-b76 6881f0383f623394b5ec73f27a5f329ff55d0467 jdk7-b77 +a7f7276b48cd74d8eb1baa83fbf3d1ef4a2603c8 jdk7-b78 diff -r 4b85cf247673 -r df0a816d95ef hotspot/.hgtags --- a/hotspot/.hgtags Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/.hgtags Wed Jul 05 17:05:01 2017 +0200 @@ -52,3 +52,4 @@ d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75 9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76 455105fc81d941482f8f8056afaa7aa0949c9300 jdk7-b77 +e703499b4b51e3af756ae77c3d5e8b3058a14e4e jdk7-b78 diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/hotspot_version --- a/hotspot/make/hotspot_version Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/hotspot_version Wed Jul 05 17:05:01 2017 +0200 @@ -35,7 +35,7 @@ HS_MAJOR_VER=17 HS_MINOR_VER=0 -HS_BUILD_NUMBER=05 +HS_BUILD_NUMBER=06 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/linux/makefiles/debug.make --- a/hotspot/make/linux/makefiles/debug.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/linux/makefiles/debug.make Wed Jul 05 17:05:01 2017 +0200 @@ -38,7 +38,7 @@ "Please use 'make jvmg' to build debug JVM. \n" \ "----------------------------------------------------------------------\n") -G_SUFFIX = +G_SUFFIX = _g VERSION = debug SYSDEFS += -DASSERT -DDEBUG PICFLAGS = DEFAULT diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/linux/makefiles/fastdebug.make --- a/hotspot/make/linux/makefiles/fastdebug.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/linux/makefiles/fastdebug.make Wed Jul 05 17:05:01 2017 +0200 @@ -58,7 +58,7 @@ # Linker mapfile MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug -G_SUFFIX = +G_SUFFIX = _g VERSION = optimized SYSDEFS += -DASSERT -DFASTDEBUG PICFLAGS = DEFAULT diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/linux/makefiles/jsig.make --- a/hotspot/make/linux/makefiles/jsig.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/linux/makefiles/jsig.make Wed Jul 05 17:05:01 2017 +0200 @@ -25,9 +25,12 @@ # Rules to build signal interposition library, used by vm.make # libjsig[_g].so: signal interposition library -JSIG = jsig$(G_SUFFIX) +JSIG = jsig LIBJSIG = lib$(JSIG).so +JSIG_G = $(JSIG)$(G_SUFFIX) +LIBJSIG_G = lib$(JSIG_G).so + JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm DEST_JSIG = $(JDK_LIBDIR)/$(LIBJSIG) @@ -50,6 +53,7 @@ @echo Making signal interposition lib... $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl + $(QUIETLY) [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); } install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/linux/makefiles/jvmg.make --- a/hotspot/make/linux/makefiles/jvmg.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/linux/makefiles/jvmg.make Wed Jul 05 17:05:01 2017 +0200 @@ -35,7 +35,7 @@ # Linker mapfile MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug -G_SUFFIX = +G_SUFFIX = _g VERSION = debug SYSDEFS += -DASSERT -DDEBUG PICFLAGS = DEFAULT diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/linux/makefiles/launcher.make --- a/hotspot/make/linux/makefiles/launcher.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/linux/makefiles/launcher.make Wed Jul 05 17:05:01 2017 +0200 @@ -25,7 +25,9 @@ # Rules to build gamma launcher, used by vm.make # gamma[_g]: launcher -LAUNCHER = gamma$(G_SUFFIX) + +LAUNCHER = gamma +LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX) LAUNCHERDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher LAUNCHERFLAGS = $(ARCHFLAG) \ @@ -70,4 +72,5 @@ $(LINK_LAUNCHER/PRE_HOOK) \ $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER); \ $(LINK_LAUNCHER/POST_HOOK) \ + [ -f $(LAUNCHER_G) ] || { ln -s $@ $(LAUNCHER_G); }; \ } diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/linux/makefiles/saproc.make --- a/hotspot/make/linux/makefiles/saproc.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/linux/makefiles/saproc.make Wed Jul 05 17:05:01 2017 +0200 @@ -25,9 +25,13 @@ # Rules to build serviceability agent library, used by vm.make # libsaproc[_g].so: serviceability agent -SAPROC = saproc$(G_SUFFIX) + +SAPROC = saproc LIBSAPROC = lib$(SAPROC).so +SAPROC_G = $(SAPROC)$(G_SUFFIX) +LIBSAPROC_G = lib$(SAPROC_G).so + AGENT_DIR = $(GAMMADIR)/agent SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family) @@ -75,6 +79,7 @@ $(SA_DEBUG_CFLAGS) \ -o $@ \ -lthread_db + $(QUIETLY) [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); } install_saproc: checkAndBuildSA $(QUIETLY) if [ -e $(LIBSAPROC) ] ; then \ diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/linux/makefiles/vm.make --- a/hotspot/make/linux/makefiles/vm.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/linux/makefiles/vm.make Wed Jul 05 17:05:01 2017 +0200 @@ -113,8 +113,9 @@ #---------------------------------------------------------------------- # JVM -JVM = jvm$(G_SUFFIX) -LIBJVM = lib$(JVM).so +JVM = jvm +LIBJVM = lib$(JVM).so +LIBJVM_G = lib$(JVM)$(G_SUFFIX).so JVM_OBJ_FILES = $(Obj_Files) @@ -201,6 +202,7 @@ $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM); \ $(LINK_LIB.CC/POST_HOOK) \ rm -f $@.1; ln -s $@ $@.1; \ + [ -f $(LIBJVM_G) ] || { ln -s $@ $(LIBJVM_G); ln -s $@.1 $(LIBJVM_G).1; }; \ if [ -x /usr/sbin/selinuxenabled ] ; then \ /usr/sbin/selinuxenabled; \ if [ $$? = 0 ] ; then \ diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/debug.make --- a/hotspot/make/solaris/makefiles/debug.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/debug.make Wed Jul 05 17:05:01 2017 +0200 @@ -54,7 +54,7 @@ "Please use 'gnumake jvmg' to build debug JVM. \n" \ "-------------------------------------------------------------------------\n") -G_SUFFIX = +G_SUFFIX = _g VERSION = debug SYSDEFS += -DASSERT -DDEBUG PICFLAGS = DEFAULT diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/dtrace.make --- a/hotspot/make/solaris/makefiles/dtrace.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/dtrace.make Wed Jul 05 17:05:01 2017 +0200 @@ -24,8 +24,8 @@ # Rules to build jvm_db/dtrace, used by vm.make -# we build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE configuration +# We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 +# but not for CORE or KERNEL configurations. ifneq ("${TYPE}", "CORE") ifneq ("${TYPE}", "KERNEL") @@ -37,12 +37,13 @@ else - JVM_DB = libjvm_db -LIBJVM_DB = libjvm$(G_SUFFIX)_db.so +LIBJVM_DB = libjvm_db.so +LIBJVM_DB_G = libjvm$(G_SUFFIX)_db.so JVM_DTRACE = jvm_dtrace -LIBJVM_DTRACE = libjvm$(G_SUFFIX)_dtrace.so +LIBJVM_DTRACE = libjvm_dtrace.so +LIBJVM_DTRACE_G = libjvm$(G_SUFFIX)_dtrace.so JVMOFFS = JvmOffsets JVMOFFS.o = $(JVMOFFS).o @@ -77,7 +78,7 @@ LFLAGS_JVM_DTRACE += -D_REENTRANT $(PICFLAG) else LFLAGS_JVM_DB += -mt $(PICFLAG) -xnolib -LFLAGS_JVM_DTRACE += -mt $(PICFLAG) -xnolib +LFLAGS_JVM_DTRACE += -mt $(PICFLAG) -xnolib -ldl endif ISA = $(subst i386,i486,$(shell isainfo -n)) @@ -86,18 +87,24 @@ ifneq ("${ISA}","${BUILDARCH}") XLIBJVM_DB = 64/$(LIBJVM_DB) +XLIBJVM_DB_G = 64/$(LIBJVM_DB_G) XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE) +XLIBJVM_DTRACE_G = 64/$(LIBJVM_DTRACE_G) $(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE) @echo Making $@ $(QUIETLY) mkdir -p 64/ ; \ $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. -I$(GENERATED) \ $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc + [ -f $(XLIBJVM_DB_G) ] || { ln -s $(LIBJVM_DB) $(XLIBJVM_DB_G); } + $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) @echo Making $@ $(QUIETLY) mkdir -p 64/ ; \ $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. \ $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor + [ -f $(XLIBJVM_DTRACE_G) ] || { ln -s $(LIBJVM_DTRACE) $(XLIBJVM_DTRACE_G); } + endif # ifneq ("${ISA}","${BUILDARCH}") ifdef USE_GCC @@ -142,11 +149,13 @@ @echo Making $@ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. -I$(GENERATED) \ $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc + [ -f $(LIBJVM_DB_G) ] || { ln -s $@ $(LIBJVM_DB_G); } $(LIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(XLIBJVM_DTRACE) $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) @echo Making $@ $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) -D$(TYPE) -I. \ $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor + [ -f $(LIBJVM_DTRACE_G) ] || { ln -s $@ $(LIBJVM_DTRACE_G); } $(DTRACE).d: $(DTRACE_SRCDIR)/hotspot.d $(DTRACE_SRCDIR)/hotspot_jni.d \ $(DTRACE_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/fastdebug.make --- a/hotspot/make/solaris/makefiles/fastdebug.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/fastdebug.make Wed Jul 05 17:05:01 2017 +0200 @@ -90,7 +90,6 @@ # for this method for now. (fix this when dtrace bug 6258412 is fixed) OPT_CFLAGS/ciEnv.o = $(OPT_CFLAGS) -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_ - # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) # If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings @@ -115,8 +114,7 @@ # and mustn't be otherwise. MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) - -G_SUFFIX = +G_SUFFIX = _g VERSION = optimized SYSDEFS += -DASSERT -DFASTDEBUG -DCHECK_UNHANDLED_OOPS PICFLAGS = DEFAULT diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/jsig.make --- a/hotspot/make/solaris/makefiles/jsig.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/jsig.make Wed Jul 05 17:05:01 2017 +0200 @@ -25,8 +25,11 @@ # Rules to build signal interposition library, used by vm.make # libjsig[_g].so: signal interposition library -JSIG = jsig$(G_SUFFIX) -LIBJSIG = lib$(JSIG).so +JSIG = jsig +LIBJSIG = lib$(JSIG).so + +JSIG_G = $(JSIG)$(G_SUFFIX) +LIBJSIG_G = lib$(JSIG_G).so JSIGSRCDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/vm @@ -46,6 +49,7 @@ @echo Making signal interposition lib... $(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ $(LFLAGS_JSIG) -o $@ $< -ldl + [ -f $(LIBJSIG_G) ] || { ln -s $@ $(LIBJSIG_G); } install_jsig: $(LIBJSIG) @echo "Copying $(LIBJSIG) to $(DEST_JSIG)" diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/jvmg.make --- a/hotspot/make/solaris/makefiles/jvmg.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/jvmg.make Wed Jul 05 17:05:01 2017 +0200 @@ -51,7 +51,7 @@ # and mustn't be otherwise. MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) -G_SUFFIX = +G_SUFFIX = _g VERSION = debug SYSDEFS += -DASSERT -DDEBUG PICFLAGS = DEFAULT diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/launcher.make --- a/hotspot/make/solaris/makefiles/launcher.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/launcher.make Wed Jul 05 17:05:01 2017 +0200 @@ -25,7 +25,8 @@ # Rules to build gamma launcher, used by vm.make # gamma[_g]: launcher -LAUNCHER = gamma$(G_SUFFIX) +LAUNCHER = gamma +LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX) LAUNCHERDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher LAUNCHERFLAGS = $(ARCHFLAG) \ @@ -88,5 +89,6 @@ $(LINK_LAUNCHER/PRE_HOOK) \ $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER); \ $(LINK_LAUNCHER/POST_HOOK) \ + [ -f $(LAUNCHER_G) ] || { ln -s $@ $(LAUNCHER_G); }; \ ;; \ esac diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/saproc.make --- a/hotspot/make/solaris/makefiles/saproc.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/saproc.make Wed Jul 05 17:05:01 2017 +0200 @@ -25,9 +25,13 @@ # Rules to build serviceability agent library, used by vm.make # libsaproc[_g].so: serviceability agent -SAPROC = saproc$(G_SUFFIX) + +SAPROC = saproc LIBSAPROC = lib$(SAPROC).so +SAPROC_G = $(SAPROC)$(G_SUFFIX) +LIBSAPROC_G = lib$(SAPROC_G).so + AGENT_DIR = $(GAMMADIR)/agent SASRCDIR = $(AGENT_DIR)/src/os/$(Platform_os_family)/proc @@ -69,6 +73,7 @@ $(SA_LFLAGS) \ -o $@ \ -ldl -ldemangle -lthread -lc + [ -f $(LIBSAPROC_G) ] || { ln -s $@ $(LIBSAPROC_G); } install_saproc: checkAndBuildSA $(QUIETLY) if [ -f $(LIBSAPROC) ] ; then \ diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/sparcWorks.make --- a/hotspot/make/solaris/makefiles/sparcWorks.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/sparcWorks.make Wed Jul 05 17:05:01 2017 +0200 @@ -281,8 +281,6 @@ OPT_CFLAGS=-xO4 $(EXTRA_OPT_CFLAGS) endif -CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_sparc/vm/solaris_sparc.il - endif # sparc ifeq ("${Platform_arch_model}", "x86_32") @@ -293,13 +291,14 @@ # [phh] Is this still true for 6.1? OPT_CFLAGS+=-xO3 -CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_x86/vm/solaris_x86_32.il - endif # 32bit x86 # no more exceptions CFLAGS/NOEX=-noex +# Inline functions +CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_${Platform_arch}/vm/solaris_${Platform_arch_model}.il + # Reduce code bloat by reverting back to 5.0 behavior for static initializers CFLAGS += -Qoption ccfe -one_static_init @@ -312,6 +311,15 @@ PICFLAG/BETTER = $(PICFLAG/DEFAULT) PICFLAG/BYFILE = $(PICFLAG/$@)$(PICFLAG/DEFAULT$(PICFLAG/$@)) +# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file. +MAPFLAG = -M FILENAME + +# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj +SONAMEFLAG = -h SONAME + +# Build shared library +SHARED_FLAG = -G + # Would be better if these weren't needed, since we link with CC, but # at present removing them causes run-time errors LFLAGS += -library=Crun diff -r 4b85cf247673 -r df0a816d95ef hotspot/make/solaris/makefiles/vm.make --- a/hotspot/make/solaris/makefiles/vm.make Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/make/solaris/makefiles/vm.make Wed Jul 05 17:05:01 2017 +0200 @@ -108,11 +108,16 @@ # older libm before libCrun, just to make sure it's found and used first. LIBS += -lsocket -lsched -ldl $(LIBM) -lCrun -lthread -ldoor -lc else +ifeq ($(COMPILER_REV_NUMERIC), 502) +# SC6.1 has it's own libm.so: specifying anything else provokes a name conflict. +LIBS += -ldl -lthread -lsocket -lm -lsched -ldoor +else LIBS += -ldl -lthread -lsocket $(LIBM) -lsched -ldoor -endif +endif # 502 +endif # 505 else LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -endif +endif # sparcWorks # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM @@ -126,8 +131,9 @@ #---------------------------------------------------------------------- # JVM -JVM = jvm$(G_SUFFIX) -LIBJVM = lib$(JVM).so +JVM = jvm +LIBJVM = lib$(JVM).so +LIBJVM_G = lib$(JVM)$(G_SUFFIX).so JVM_OBJ_FILES = $(Obj_Files) $(DTRACE_OBJS) @@ -173,11 +179,12 @@ -sbfast|-xsbfast) \ ;; \ *) \ - echo Linking vm...; \ - $(LINK_LIB.CC/PRE_HOOK) \ - $(LINK_VM) $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM); \ - $(LINK_LIB.CC/POST_HOOK) \ - rm -f $@.1; ln -s $@ $@.1; \ + echo Linking vm...; \ + $(LINK_LIB.CC/PRE_HOOK) \ + $(LINK_VM) $(LFLAGS_VM) -o $@ $(LIBJVM.o) $(LIBS_VM); \ + $(LINK_LIB.CC/POST_HOOK) \ + rm -f $@.1; ln -s $@ $@.1; \ + [ -f $(LIBJVM_G) ] || { ln -s $@ $(LIBJVM_G); ln -s $@.1 $(LIBJVM_G).1; }; \ ;; \ esac diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -189,14 +189,17 @@ Register OSR_buf = osrBufferPointer()->as_register(); { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); int monitor_offset = BytesPerWord * method()->max_locals() + - (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1); + (2 * BytesPerWord) * (number_of_locks - 1); + // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in + // the OSR buffer using 2 word entries: first the lock and then + // the oop. for (int i = 0; i < number_of_locks; i++) { - int slot_offset = monitor_offset - ((i * BasicObjectLock::size()) * BytesPerWord); + int slot_offset = monitor_offset - ((i * 2) * BytesPerWord); #ifdef ASSERT // verify the interpreter's monitor has a non-null object { Label L; - __ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes(), O7); + __ ld_ptr(OSR_buf, slot_offset + 1*BytesPerWord, O7); __ cmp(G0, O7); __ br(Assembler::notEqual, false, Assembler::pt, L); __ delayed()->nop(); @@ -205,9 +208,9 @@ } #endif // ASSERT // Copy the lock field into the compiled activation. - __ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::lock_offset_in_bytes(), O7); + __ ld_ptr(OSR_buf, slot_offset + 0, O7); __ st_ptr(O7, frame_map()->address_for_monitor_lock(i)); - __ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes(), O7); + __ ld_ptr(OSR_buf, slot_offset + 1*BytesPerWord, O7); __ st_ptr(O7, frame_map()->address_for_monitor_object(i)); } } @@ -953,9 +956,11 @@ } else { #ifdef _LP64 assert(base != to_reg->as_register_lo(), "can't handle this"); + assert(O7 != to_reg->as_register_lo(), "can't handle this"); __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_lo()); + __ lduw(base, offset + lo_word_offset_in_bytes, O7); // in case O7 is base or offset, use it last __ sllx(to_reg->as_register_lo(), 32, to_reg->as_register_lo()); - __ ld(base, offset + lo_word_offset_in_bytes, to_reg->as_register_lo()); + __ or3(to_reg->as_register_lo(), O7, to_reg->as_register_lo()); #else if (base == to_reg->as_register_lo()) { __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_hi()); @@ -976,8 +981,8 @@ FloatRegister reg = to_reg->as_double_reg(); // split unaligned loads if (unaligned || PatchALot) { - __ ldf(FloatRegisterImpl::S, base, offset + BytesPerWord, reg->successor()); - __ ldf(FloatRegisterImpl::S, base, offset, reg); + __ ldf(FloatRegisterImpl::S, base, offset + 4, reg->successor()); + __ ldf(FloatRegisterImpl::S, base, offset, reg); } else { __ ldf(FloatRegisterImpl::D, base, offset, to_reg->as_double_reg()); } @@ -2200,6 +2205,7 @@ Register len = O2; __ add(src, arrayOopDesc::base_offset_in_bytes(basic_type), src_ptr); + LP64_ONLY(__ sra(src_pos, 0, src_pos);) //higher 32bits must be null if (shift == 0) { __ add(src_ptr, src_pos, src_ptr); } else { @@ -2208,6 +2214,7 @@ } __ add(dst, arrayOopDesc::base_offset_in_bytes(basic_type), dst_ptr); + LP64_ONLY(__ sra(dst_pos, 0, dst_pos);) //higher 32bits must be null if (shift == 0) { __ add(dst_ptr, dst_pos, dst_ptr); } else { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -144,17 +144,17 @@ if (index->is_register()) { // apply the shift and accumulate the displacement if (shift > 0) { - LIR_Opr tmp = new_register(T_INT); + LIR_Opr tmp = new_pointer_register(); __ shift_left(index, shift, tmp); index = tmp; } if (disp != 0) { - LIR_Opr tmp = new_register(T_INT); + LIR_Opr tmp = new_pointer_register(); if (Assembler::is_simm13(disp)) { - __ add(tmp, LIR_OprFact::intConst(disp), tmp); + __ add(tmp, LIR_OprFact::intptrConst(disp), tmp); index = tmp; } else { - __ move(LIR_OprFact::intConst(disp), tmp); + __ move(LIR_OprFact::intptrConst(disp), tmp); __ add(tmp, index, tmp); index = tmp; } @@ -162,8 +162,8 @@ } } else if (disp != 0 && !Assembler::is_simm13(disp)) { // index is illegal so replace it with the displacement loaded into a register - index = new_register(T_INT); - __ move(LIR_OprFact::intConst(disp), index); + index = new_pointer_register(); + __ move(LIR_OprFact::intptrConst(disp), index); disp = 0; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,10 +22,9 @@ * */ -// // Sets the default values for platform dependent flags used by the client compiler. // (see c1_globals.hpp) -// + #ifndef TIERED define_pd_global(bool, BackgroundCompilation, true ); define_pd_global(bool, CICompileOSR, true ); @@ -48,27 +47,24 @@ define_pd_global(bool, UseTLAB, true ); define_pd_global(bool, ProfileInterpreter, false); define_pd_global(intx, FreqInlineSize, 325 ); -define_pd_global(intx, NewRatio, 8 ); // Design center runs on 1.3.1 define_pd_global(bool, ResizeTLAB, true ); define_pd_global(intx, ReservedCodeCacheSize, 32*M ); define_pd_global(intx, CodeCacheExpansionSize, 32*K ); define_pd_global(uintx,CodeCacheMinBlockLength, 1); -define_pd_global(uintx, PermSize, 12*M ); -define_pd_global(uintx, MaxPermSize, 64*M ); -define_pd_global(bool, NeverActAsServerClassMachine, true); +define_pd_global(uintx,PermSize, 12*M ); +define_pd_global(uintx,MaxPermSize, 64*M ); +define_pd_global(bool, NeverActAsServerClassMachine, true ); define_pd_global(intx, NewSizeThreadIncrease, 16*K ); -define_pd_global(uintx, DefaultMaxRAM, 1*G); +define_pd_global(uint64_t,MaxRAM, 1ULL*G); define_pd_global(intx, InitialCodeCacheSize, 160*K); -#endif // TIERED +#endif // !TIERED define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, RoundFPResults, false); - -define_pd_global(bool, LIRFillDelaySlots, true); +define_pd_global(bool, LIRFillDelaySlots, true ); define_pd_global(bool, OptimizeSinglePrecision, false); -define_pd_global(bool, CSEArrayLength, true); +define_pd_global(bool, CSEArrayLength, true ); define_pd_global(bool, TwoOperandLIRForm, false); - -define_pd_global(intx, SafepointPollOffset, 0); +define_pd_global(intx, SafepointPollOffset, 0 ); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -59,7 +59,6 @@ define_pd_global(intx, FreqInlineSize, 175); define_pd_global(intx, INTPRESSURE, 48); // large register set define_pd_global(intx, InteriorEntryAlignment, 16); // = CodeEntryAlignment -define_pd_global(intx, NewRatio, 2); define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); // The default setting 16/16 seems to work best. // (For _228_jack 16/16 is 2% better than 4/4, 16/4, 32/32, 32/16, or 16/32.) @@ -83,25 +82,25 @@ // sequence of instructions to load a 64 bit pointer. // // InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(intx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(intx, ReservedCodeCacheSize, 48*M); -define_pd_global(intx, CodeCacheExpansionSize, 64*K); +define_pd_global(intx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(intx, ReservedCodeCacheSize, 48*M); +define_pd_global(intx, CodeCacheExpansionSize, 64*K); // Ergonomics related flags -define_pd_global(uintx, DefaultMaxRAM, 32*G); +define_pd_global(uint64_t,MaxRAM, 128ULL*G); #else // InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(intx, InitialCodeCacheSize, 1536*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(intx, ReservedCodeCacheSize, 32*M); -define_pd_global(intx, CodeCacheExpansionSize, 32*K); +define_pd_global(intx, InitialCodeCacheSize, 1536*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(intx, ReservedCodeCacheSize, 32*M); +define_pd_global(intx, CodeCacheExpansionSize, 32*K); // Ergonomics related flags -define_pd_global(uintx, DefaultMaxRAM, 1*G); +define_pd_global(uint64_t,MaxRAM, 4ULL*G); #endif -define_pd_global(uintx,CodeCacheMinBlockLength, 4); +define_pd_global(uintx,CodeCacheMinBlockLength, 4); // Heap related flags -define_pd_global(uintx, PermSize, ScaleForWordSize(16*M)); -define_pd_global(uintx, MaxPermSize, ScaleForWordSize(64*M)); +define_pd_global(uintx,PermSize, ScaleForWordSize(16*M)); +define_pd_global(uintx,MaxPermSize, ScaleForWordSize(64*M)); // Ergonomics related flags define_pd_global(bool, NeverActAsServerClassMachine, false); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/sparc/vm/globals_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,10 +22,8 @@ * */ -// // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -// // For sparc we do not do call backs when a thread is in the interpreter, because the // interpreter dispatch needs at least two instructions - first to load the dispatch address @@ -41,26 +39,23 @@ define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast -define_pd_global(intx, CodeEntryAlignment, 32); -define_pd_global(uintx, TLABSize, 0); -define_pd_global(uintx, NewSize, ScaleForWordSize((2048 * K) + (2 * (64 * K)))); -define_pd_global(intx, SurvivorRatio, 8); -define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC -define_pd_global(intx, InlineSmallCode, 1500); +define_pd_global(intx, CodeEntryAlignment, 32); +define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC +define_pd_global(intx, InlineSmallCode, 1500); #ifdef _LP64 // Stack slots are 2X larger in LP64 than in the 32 bit VM. -define_pd_global(intx, ThreadStackSize, 1024); -define_pd_global(intx, VMThreadStackSize, 1024); +define_pd_global(intx, ThreadStackSize, 1024); +define_pd_global(intx, VMThreadStackSize, 1024); #else -define_pd_global(intx, ThreadStackSize, 512); -define_pd_global(intx, VMThreadStackSize, 512); +define_pd_global(intx, ThreadStackSize, 512); +define_pd_global(intx, VMThreadStackSize, 512); #endif define_pd_global(intx, StackYellowPages, 2); define_pd_global(intx, StackRedPages, 1); define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1)); -define_pd_global(intx, PreInflateSpin, 40); // Determined by running design center +define_pd_global(intx, PreInflateSpin, 40); // Determined by running design center define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -150,8 +150,7 @@ } -address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) { - assert(!unbox, "NYI");//6815692// +address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { address compiled_entry = __ pc(); Label cont; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -2251,6 +2251,7 @@ emit_byte(0x9D); } +#ifndef _LP64 // no 32bit push/pop on amd64 void Assembler::popl(Address dst) { // NOTE: this will adjust stack by 8byte on 64bits InstructionMark im(this); @@ -2258,6 +2259,7 @@ emit_byte(0x8F); emit_operand(rax, dst); } +#endif void Assembler::prefetch_prefix(Address src) { prefix(src); @@ -2428,6 +2430,7 @@ emit_byte(0x9C); } +#ifndef _LP64 // no 32bit push/pop on amd64 void Assembler::pushl(Address src) { // Note this will push 64bit on 64bit InstructionMark im(this); @@ -2435,6 +2438,7 @@ emit_byte(0xFF); emit_operand(rsi, src); } +#endif void Assembler::pxor(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); @@ -5591,7 +5595,12 @@ } void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) { - andpd(dst, as_Address(src)); + if (reachable(src)) { + andpd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + andpd(dst, Address(rscratch1, 0)); + } } void MacroAssembler::andptr(Register dst, int32_t imm32) { @@ -6078,11 +6087,21 @@ } void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src) { - comisd(dst, as_Address(src)); + if (reachable(src)) { + comisd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + comisd(dst, Address(rscratch1, 0)); + } } void MacroAssembler::comiss(XMMRegister dst, AddressLiteral src) { - comiss(dst, as_Address(src)); + if (reachable(src)) { + comiss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + comiss(dst, Address(rscratch1, 0)); + } } @@ -7647,7 +7666,7 @@ #ifdef ASSERT Label L; - testl(tmp, tmp); + testptr(tmp, tmp); jccb(Assembler::notZero, L); hlt(); bind(L); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/assembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -1244,7 +1244,9 @@ void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); void pcmpestri(XMMRegister xmm1, Address src, int imm8); +#ifndef _LP64 // no 32bit push/pop on amd64 void popl(Address dst); +#endif #ifdef _LP64 void popq(Address dst); @@ -1285,7 +1287,9 @@ // Interleave Low Bytes void punpcklbw(XMMRegister dst, XMMRegister src); +#ifndef _LP64 // no 32bit push/pop on amd64 void pushl(Address src); +#endif void pushq(Address src); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -301,22 +301,25 @@ Register OSR_buf = osrBufferPointer()->as_pointer_register(); { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); int monitor_offset = BytesPerWord * method()->max_locals() + - (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1); + (2 * BytesPerWord) * (number_of_locks - 1); + // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in + // the OSR buffer using 2 word entries: first the lock and then + // the oop. for (int i = 0; i < number_of_locks; i++) { - int slot_offset = monitor_offset - ((i * BasicObjectLock::size()) * BytesPerWord); + int slot_offset = monitor_offset - ((i * 2) * BytesPerWord); #ifdef ASSERT // verify the interpreter's monitor has a non-null object { Label L; - __ cmpptr(Address(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); + __ cmpptr(Address(OSR_buf, slot_offset + 1*BytesPerWord), (int32_t)NULL_WORD); __ jcc(Assembler::notZero, L); __ stop("locked object is NULL"); __ bind(L); } #endif - __ movptr(rbx, Address(OSR_buf, slot_offset + BasicObjectLock::lock_offset_in_bytes())); + __ movptr(rbx, Address(OSR_buf, slot_offset + 0)); __ movptr(frame_map()->address_for_monitor_lock(i), rbx); - __ movptr(rbx, Address(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes())); + __ movptr(rbx, Address(OSR_buf, slot_offset + 1*BytesPerWord)); __ movptr(frame_map()->address_for_monitor_object(i), rbx); } } @@ -785,7 +788,13 @@ ShouldNotReachHere(); __ movoop(as_Address(addr, noreg), c->as_jobject()); } else { +#ifdef _LP64 + __ movoop(rscratch1, c->as_jobject()); + null_check_here = code_offset(); + __ movptr(as_Address_lo(addr), rscratch1); +#else __ movoop(as_Address(addr), c->as_jobject()); +#endif } } break; @@ -1118,8 +1127,14 @@ __ pushptr(frame_map()->address_for_slot(src ->single_stack_ix())); __ popptr (frame_map()->address_for_slot(dest->single_stack_ix())); } else { +#ifndef _LP64 __ pushl(frame_map()->address_for_slot(src ->single_stack_ix())); __ popl (frame_map()->address_for_slot(dest->single_stack_ix())); +#else + //no pushl on 64bits + __ movl(rscratch1, frame_map()->address_for_slot(src ->single_stack_ix())); + __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), rscratch1); +#endif } } else if (src->is_double_stack()) { @@ -3136,8 +3151,10 @@ #ifdef _LP64 assert_different_registers(c_rarg0, dst, dst_pos, length); + __ movl2ptr(src_pos, src_pos); //higher 32bits must be null __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); assert_different_registers(c_rarg1, length); + __ movl2ptr(dst_pos, dst_pos); //higher 32bits must be null __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); __ mov(c_rarg2, length); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -755,8 +755,19 @@ } LIR_Opr addr = new_pointer_register(); - __ move(obj.result(), addr); - __ add(addr, offset.result(), addr); + LIR_Address* a; + if(offset.result()->is_constant()) { + a = new LIR_Address(obj.result(), + NOT_LP64(offset.result()->as_constant_ptr()->as_jint()) LP64_ONLY((int)offset.result()->as_constant_ptr()->as_jlong()), + as_BasicType(type)); + } else { + a = new LIR_Address(obj.result(), + offset.result(), + LIR_Address::times_1, + 0, + as_BasicType(type)); + } + __ leal(LIR_OprFact::address(a), addr); if (type == objectType) { // Write-barrier needed for Object fields. // Do the pre-write barrier, if any. diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/c1_globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,10 +22,8 @@ * */ -// // Sets the default values for platform dependent flags used by the client compiler. // (see c1_globals.hpp) -// #ifndef TIERED define_pd_global(bool, BackgroundCompilation, true ); @@ -48,27 +46,24 @@ define_pd_global(intx, OnStackReplacePercentage, 933 ); define_pd_global(intx, FreqInlineSize, 325 ); -define_pd_global(intx, NewRatio, 12 ); define_pd_global(intx, NewSizeThreadIncrease, 4*K ); define_pd_global(intx, InitialCodeCacheSize, 160*K); define_pd_global(intx, ReservedCodeCacheSize, 32*M ); define_pd_global(bool, ProfileInterpreter, false); define_pd_global(intx, CodeCacheExpansionSize, 32*K ); define_pd_global(uintx,CodeCacheMinBlockLength, 1); -define_pd_global(uintx, PermSize, 12*M ); -define_pd_global(uintx, MaxPermSize, 64*M ); -define_pd_global(bool, NeverActAsServerClassMachine, true); -define_pd_global(uintx, DefaultMaxRAM, 1*G); +define_pd_global(uintx,PermSize, 12*M ); +define_pd_global(uintx,MaxPermSize, 64*M ); +define_pd_global(bool, NeverActAsServerClassMachine, true ); +define_pd_global(uint64_t,MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); -#endif // TIERED +#endif // !TIERED define_pd_global(bool, UseTypeProfile, false); define_pd_global(bool, RoundFPResults, true ); - define_pd_global(bool, LIRFillDelaySlots, false); -define_pd_global(bool, OptimizeSinglePrecision, true); +define_pd_global(bool, OptimizeSinglePrecision, true ); define_pd_global(bool, CSEArrayLength, false); -define_pd_global(bool, TwoOperandLIRForm, true); +define_pd_global(bool, TwoOperandLIRForm, true ); - -define_pd_global(intx, SafepointPollOffset, 256); +define_pd_global(intx, SafepointPollOffset, 256 ); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/c2_globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,7 +22,6 @@ * */ -// // Sets the default values for platform dependent flags used by the server compiler. // (see c2_globals.hpp). Alpha-sorted. @@ -46,8 +45,8 @@ define_pd_global(intx, CompileThreshold, 10000); #endif // TIERED define_pd_global(intx, Tier2CompileThreshold, 10000); -define_pd_global(intx, Tier3CompileThreshold, 20000 ); -define_pd_global(intx, Tier4CompileThreshold, 40000 ); +define_pd_global(intx, Tier3CompileThreshold, 20000); +define_pd_global(intx, Tier4CompileThreshold, 40000); define_pd_global(intx, BackEdgeThreshold, 100000); define_pd_global(intx, Tier2BackEdgeThreshold, 100000); @@ -61,7 +60,6 @@ #ifdef AMD64 define_pd_global(intx, INTPRESSURE, 13); define_pd_global(intx, InteriorEntryAlignment, 16); -define_pd_global(intx, NewRatio, 2); define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); // InitialCodeCacheSize derived from specjbb2000 run. @@ -69,19 +67,18 @@ define_pd_global(intx, CodeCacheExpansionSize, 64*K); // Ergonomics related flags -define_pd_global(uintx, DefaultMaxRAM, 32*G); +define_pd_global(uint64_t,MaxRAM, 128ULL*G); #else define_pd_global(intx, INTPRESSURE, 6); define_pd_global(intx, InteriorEntryAlignment, 4); -define_pd_global(intx, NewRatio, 8); // Design center runs on 1.3.1 define_pd_global(intx, NewSizeThreadIncrease, 4*K); -define_pd_global(intx, LoopUnrollLimit, 50); // Design center runs on 1.3.1 +define_pd_global(intx, LoopUnrollLimit, 50); // Design center runs on 1.3.1 // InitialCodeCacheSize derived from specjbb2000 run. define_pd_global(intx, InitialCodeCacheSize, 2304*K); // Integral multiple of CodeCacheExpansionSize define_pd_global(intx, CodeCacheExpansionSize, 32*K); // Ergonomics related flags -define_pd_global(uintx, DefaultMaxRAM, 1*G); +define_pd_global(uint64_t,MaxRAM, 4ULL*G); #endif // AMD64 define_pd_global(intx, OptoLoopAlignment, 16); define_pd_global(intx, RegisterCostAreaRatio, 16000); @@ -97,8 +94,8 @@ define_pd_global(uintx,CodeCacheMinBlockLength, 4); // Heap related flags -define_pd_global(uintx, PermSize, ScaleForWordSize(16*M)); -define_pd_global(uintx, MaxPermSize, ScaleForWordSize(64*M)); +define_pd_global(uintx,PermSize, ScaleForWordSize(16*M)); +define_pd_global(uintx,MaxPermSize, ScaleForWordSize(64*M)); // Ergonomics related flags define_pd_global(bool, NeverActAsServerClassMachine, false); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,17 +22,16 @@ * */ -// // 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, CountInterpCalls, true); +define_pd_global(bool, ConvertSleepToYield, true); +define_pd_global(bool, ShareVtableStubs, true); +define_pd_global(bool, CountInterpCalls, true); +define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this -define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks -define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast +define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks +define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast // See 4827828 for this change. There is no globals_core_i486.hpp. I can't // assign a different value for C2 without touching a number of files. Use @@ -42,29 +41,24 @@ // the uep and the vep doesn't get real alignment but just slops on by // only assured that the entry instruction meets the 5 byte size requirement. #ifdef COMPILER2 -define_pd_global(intx, CodeEntryAlignment, 32); +define_pd_global(intx, CodeEntryAlignment, 32); #else -define_pd_global(intx, CodeEntryAlignment, 16); +define_pd_global(intx, CodeEntryAlignment, 16); #endif // COMPILER2 +define_pd_global(intx, InlineFrequencyCount, 100); +define_pd_global(intx, InlineSmallCode, 1000); -define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this - -define_pd_global(uintx, TLABSize, 0); +define_pd_global(intx, StackYellowPages, 2); +define_pd_global(intx, StackRedPages, 1); #ifdef AMD64 -define_pd_global(uintx, NewSize, ScaleForWordSize(2048 * K)); // Very large C++ stack frames using solaris-amd64 optimized builds // due to lack of optimization caused by C++ compiler bugs define_pd_global(intx, StackShadowPages, SOLARIS_ONLY(20) NOT_SOLARIS(6) DEBUG_ONLY(+2)); #else -define_pd_global(uintx, NewSize, 1024 * K); define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1)); #endif // AMD64 -define_pd_global(intx, InlineFrequencyCount, 100); -define_pd_global(intx, InlineSmallCode, 1000); -define_pd_global(intx, PreInflateSpin, 10); -define_pd_global(intx, StackYellowPages, 2); -define_pd_global(intx, StackRedPages, 1); +define_pd_global(intx, PreInflateSpin, 10); define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -196,6 +196,9 @@ } else { assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); movl(reg, Address(rsi, bcp_offset)); + // Check if the secondary index definition is still ~x, otherwise + // we have to change the following assembler code to calculate the + // plain index. assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line"); notl(reg); // convert to plain index } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -185,12 +185,30 @@ } +void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index, + int bcp_offset, + bool giant_index) { + assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + if (!giant_index) { + load_unsigned_short(index, Address(r13, bcp_offset)); + } else { + assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); + movl(index, Address(r13, bcp_offset)); + // Check if the secondary index definition is still ~x, otherwise + // we have to change the following assembler code to calculate the + // plain index. + assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line"); + notl(index); // convert to plain index + } +} + + void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, - int bcp_offset) { - assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + int bcp_offset, + bool giant_index) { assert(cache != index, "must use different registers"); - load_unsigned_short(index, Address(r13, bcp_offset)); + get_cache_index_at_bcp(index, bcp_offset, giant_index); movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); // convert from field index to ConstantPoolCacheEntry index @@ -200,10 +218,10 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, - int bcp_offset) { - assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + int bcp_offset, + bool giant_index) { assert(cache != tmp, "must use different register"); - load_unsigned_short(tmp, Address(r13, bcp_offset)); + get_cache_index_at_bcp(tmp, bcp_offset, giant_index); assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); // convert from field index to ConstantPoolCacheEntry index // and from word offset to byte offset @@ -1236,7 +1254,8 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, - Register reg2) { + Register reg2, + bool receiver_can_be_null) { if (ProfileInterpreter) { Label profile_continue; @@ -1246,8 +1265,15 @@ // We are making a call. Increment the count. increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + Label skip_receiver_profile; + if (receiver_can_be_null) { + testptr(receiver, receiver); + jcc(Assembler::zero, skip_receiver_profile); + } + // Record the receiver type. record_klass_in_profile(receiver, mdp, reg2); + bind(skip_receiver_profile); // The method data pointer needs to be updated to reflect the new target. update_mdp_by_constant(mdp, diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -95,9 +95,10 @@ void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); void get_cache_and_index_at_bcp(Register cache, Register index, - int bcp_offset); + int bcp_offset, bool giant_index = false); void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, - int bcp_offset); + int bcp_offset, bool giant_index = false); + void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false); void pop_ptr(Register r = rax); @@ -236,7 +237,8 @@ void profile_call(Register mdp); void profile_final_call(Register mdp); void profile_virtual_call(Register receiver, Register mdp, - Register scratch2); + Register scratch2, + bool receiver_can_be_null = false); void profile_ret(Register return_bci, Register mdp); void profile_null_seen(Register mdp); void profile_typecheck(Register mdp, Register klass, Register scratch); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -277,12 +277,11 @@ address entry_point = __ pc(); // abstract method entry - // remove return address. Not really needed, since exception - // handling throws away expression stack - __ pop(rbx); - // adjust stack to what a normal return would do - __ mov(rsp, r13); + // pop return address, reset last_sp to NULL + __ empty_expression_stack(); + __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) // throw exception __ call_VM(noreg, CAST_FROM_FN_PTR(address, @@ -300,7 +299,10 @@ if (!EnableMethodHandles) { return generate_abstract_entry(); } - return generate_abstract_entry(); //6815692// + + address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm); + + return entry_point; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/methodHandles_x86.cpp --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -448,7 +448,7 @@ rbx_index, Address::times_ptr, base + vtableEntry::method_offset_in_bytes()); Register rbx_method = rbx_temp; - __ movl(rbx_method, vtable_entry_addr); + __ movptr(rbx_method, vtable_entry_addr); __ verify_oop(rbx_method); __ jmp(rbx_method_fie); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -2935,6 +2935,16 @@ // arraycopy stubs used by compilers generate_arraycopy_stubs(); + + // generic method handle stubs + if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { + for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; + ek < MethodHandles::_EK_LIMIT; + ek = MethodHandles::EntryKind(1 + (int)ek)) { + StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); + MethodHandles::generate_method_handle_stub(_masm, ek); + } + } } public: diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -155,15 +155,8 @@ } -address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) { +address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) { TosState incoming_state = state; - if (EnableInvokeDynamic) { - if (unbox) { - incoming_state = atos; - } - } else { - assert(!unbox, "old behavior"); - } Label interpreter_entry; address compiled_entry = __ pc(); @@ -216,46 +209,6 @@ __ restore_bcp(); __ restore_locals(); - Label L_fail; - - if (unbox && state != atos) { - // cast and unbox - BasicType type = as_BasicType(state); - if (type == T_BYTE) type = T_BOOLEAN; // FIXME - KlassHandle boxk = SystemDictionaryHandles::box_klass(type); - __ mov32(rbx, ExternalAddress((address) boxk.raw_value())); - __ testl(rax, rax); - Label L_got_value, L_get_value; - // convert nulls to zeroes (avoid NPEs here) - if (!(type == T_FLOAT || type == T_DOUBLE)) { - // if rax already contains zero bits, forge ahead - __ jcc(Assembler::zero, L_got_value); - } else { - __ jcc(Assembler::notZero, L_get_value); - __ fldz(); - __ jmp(L_got_value); - } - __ bind(L_get_value); - __ cmp32(rbx, Address(rax, oopDesc::klass_offset_in_bytes())); - __ jcc(Assembler::notEqual, L_fail); - int offset = java_lang_boxing_object::value_offset_in_bytes(type); - // Cf. TemplateTable::getfield_or_static - switch (type) { - case T_BYTE: // fall through: - case T_BOOLEAN: __ load_signed_byte(rax, Address(rax, offset)); break; - case T_CHAR: __ load_unsigned_short(rax, Address(rax, offset)); break; - case T_SHORT: __ load_signed_short(rax, Address(rax, offset)); break; - case T_INT: __ movl(rax, Address(rax, offset)); break; - case T_FLOAT: __ fld_s(Address(rax, offset)); break; - case T_DOUBLE: __ fld_d(Address(rax, offset)); break; - // Access to java.lang.Double.value does not need to be atomic: - case T_LONG: { __ movl(rdx, Address(rax, offset + 4)); - __ movl(rax, Address(rax, offset + 0)); } break; - default: ShouldNotReachHere(); - } - __ bind(L_got_value); - } - Label L_got_cache, L_giant_index; if (EnableInvokeDynamic) { __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic); @@ -263,32 +216,6 @@ } __ get_cache_and_index_at_bcp(rbx, rcx, 1, false); __ bind(L_got_cache); - if (unbox && state == atos) { - // insert a casting conversion, to keep verifier sane - Label L_ok, L_ok_pops; - __ testl(rax, rax); - __ jcc(Assembler::zero, L_ok); - __ push(rax); // save the object to check - __ push(rbx); // save CP cache reference - __ movl(rdx, Address(rax, oopDesc::klass_offset_in_bytes())); - __ movl(rbx, Address(rbx, rcx, - Address::times_4, constantPoolCacheOopDesc::base_offset() + - ConstantPoolCacheEntry::f1_offset())); - __ movl(rbx, Address(rbx, __ delayed_value(sun_dyn_CallSiteImpl::type_offset_in_bytes, rcx))); - __ movl(rbx, Address(rbx, __ delayed_value(java_dyn_MethodType::rtype_offset_in_bytes, rcx))); - __ movl(rax, Address(rbx, __ delayed_value(java_lang_Class::klass_offset_in_bytes, rcx))); - __ check_klass_subtype(rdx, rax, rbx, L_ok_pops); - __ pop(rcx); // pop and discard CP cache - __ mov(rbx, rax); // target supertype into rbx for L_fail - __ pop(rax); // failed object into rax for L_fail - __ jmp(L_fail); - - __ bind(L_ok_pops); - // restore pushed temp regs: - __ pop(rbx); - __ pop(rax); - __ bind(L_ok); - } __ movl(rbx, Address(rbx, rcx, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::flags_offset())); @@ -301,14 +228,6 @@ __ bind(L_giant_index); __ get_cache_and_index_at_bcp(rbx, rcx, 1, true); __ jmp(L_got_cache); - - if (unbox) { - __ bind(L_fail); - __ push(rbx); // missed klass (required) - __ push(rax); // bad object (actual) - __ movptr(rdx, ExternalAddress((address) &Interpreter::_throw_WrongMethodType_entry)); - __ call(rdx); - } } return entry; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -100,21 +100,26 @@ return entry; } -// Arguments are: required type in rarg1, failing object (or NULL) in rarg2 +// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4. address TemplateInterpreterGenerator::generate_WrongMethodType_handler() { address entry = __ pc(); __ pop(c_rarg2); // failing object is at TOS __ pop(c_rarg1); // required type is at TOS+8 - // expression stack must be empty before entering the VM if an - // exception happened + __ verify_oop(c_rarg1); + __ verify_oop(c_rarg2); + + // Various method handle types use interpreter registers as temps. + __ restore_bcp(); + __ restore_locals(); + + // Expression stack must be empty before entering the VM for an exception. __ empty_expression_stack(); __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime:: - throw_WrongMethodTypeException), + InterpreterRuntime::throw_WrongMethodTypeException), // pass required type, failing object (or NULL) c_rarg1, c_rarg2); return entry; @@ -166,8 +171,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, - int step, bool unbox) { - assert(!unbox, "NYI");//6815692// + int step) { // amd64 doesn't need to do anything special about compiled returns // to the interpreter so the code that exists on x86 to place a sentinel @@ -183,15 +187,29 @@ __ restore_bcp(); __ restore_locals(); - __ get_cache_and_index_at_bcp(rbx, rcx, 1); + Label L_got_cache, L_giant_index; + if (EnableInvokeDynamic) { + __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic); + __ jcc(Assembler::equal, L_giant_index); + } + __ get_cache_and_index_at_bcp(rbx, rcx, 1, false); + __ bind(L_got_cache); __ movl(rbx, Address(rbx, rcx, - Address::times_8, + Address::times_ptr, in_bytes(constantPoolCacheOopDesc::base_offset()) + 3 * wordSize)); __ andl(rbx, 0xFF); if (TaggedStackInterpreter) __ shll(rbx, 1); // 2 slots per parameter. __ lea(rsp, Address(rsp, rbx, Address::times_8)); __ dispatch_next(state, step); + + // out of the main line of code... + if (EnableInvokeDynamic) { + __ bind(L_giant_index); + __ get_cache_and_index_at_bcp(rbx, rcx, 1, true); + __ jmp(L_got_cache); + } + return entry; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -2890,9 +2890,6 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) { - bool is_invdyn_bootstrap = (byte_no < 0); - if (is_invdyn_bootstrap) byte_no = -byte_no; - // determine flags Bytecodes::Code code = bytecode(); const bool is_invokeinterface = code == Bytecodes::_invokeinterface; @@ -2907,8 +2904,6 @@ const Register flags = rdx; assert_different_registers(method, index, recv, flags); - assert(!is_invdyn_bootstrap || is_invokedynamic, "byte_no<0 hack only for invdyn"); - // save 'interpreter return address' __ save_bcp(); @@ -2944,9 +2939,7 @@ // load return address { address table_addr; - if (is_invdyn_bootstrap) - table_addr = (address)Interpreter::return_5_unbox_addrs_by_index_table(); - else if (is_invokeinterface || is_invokedynamic) + if (is_invokeinterface || is_invokedynamic) table_addr = (address)Interpreter::return_5_addrs_by_index_table(); else table_addr = (address)Interpreter::return_3_addrs_by_index_table(); @@ -3153,54 +3146,10 @@ __ profile_call(rsi); } - Label handle_unlinked_site; - __ movptr(rcx, Address(rax, __ delayed_value(sun_dyn_CallSiteImpl::target_offset_in_bytes, rcx))); - __ testptr(rcx, rcx); - __ jcc(Assembler::zero, handle_unlinked_site); - + __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx))); + __ null_check(rcx); __ prepare_to_jump_from_interpreted(); __ jump_to_method_handle_entry(rcx, rdx); - - // Initial calls come here... - __ bind(handle_unlinked_site); - __ pop(rcx); // remove return address pushed by prepare_invoke - - // box stacked arguments into an array for the bootstrap method - address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic); - __ restore_bcp(); // rsi must be correct for call_VM - __ call_VM(rax, entry, rax); - __ movl(rdi, rax); // protect bootstrap MH from prepare_invoke - - // recompute return address - __ restore_bcp(); // rsi must be correct for prepare_invoke - prepare_invoke(rax, rbx, -byte_no); // smashes rcx, rdx - // rax: CallSite object (f1) - // rbx: unused (f2) - // rdi: bootstrap MH - // rdx: flags - - // now load up the arglist, which has been neatly boxed - __ get_thread(rcx); - __ movptr(rdx, Address(rcx, JavaThread::vm_result_2_offset())); - __ movptr(Address(rcx, JavaThread::vm_result_2_offset()), NULL_WORD); - __ verify_oop(rdx); - // rdx = arglist - - // save SP now, before we add the bootstrap call to the stack - // We must preserve a fiction that the original arguments are outgoing, - // because the return sequence will reset the stack to this point - // and then pop all those arguments. It seems error-prone to use - // a different argument list size just for bootstrapping. - __ prepare_to_jump_from_interpreted(); - - // Now let's play adapter, pushing the real arguments on the stack. - __ pop(rbx); // return PC - __ push(rdi); // boot MH - __ push(rax); // call site - __ push(rdx); // arglist - __ push(rbx); // return PC, again - __ mov(rcx, rdi); - __ jump_to_method_handle_entry(rcx, rdx); } //---------------------------------------------------------------------------------------------------- diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -203,18 +203,15 @@ __ jcc(Assembler::notEqual, fast_patch); __ get_method(scratch); // Let breakpoint table handling rewrite to quicker bytecode - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::set_original_bytecode_at), - scratch, r13, bc); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, r13, bc); #ifndef ASSERT __ jmpb(patch_done); +#else + __ jmp(patch_done); +#endif __ bind(fast_patch); } -#else - __ jmp(patch_done); - __ bind(fast_patch); - } +#ifdef ASSERT Label okay; __ load_unsigned_byte(scratch, at_bcp(0)); __ cmpl(scratch, (int) Bytecodes::java_code(bytecode)); @@ -2054,26 +2051,28 @@ } } -void TemplateTable::resolve_cache_and_index(int byte_no, - Register Rcache, - Register index) { +void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) { assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); + bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic); const Register temp = rbx; assert_different_registers(Rcache, index, temp); const int shift_count = (1 + byte_no) * BitsPerByte; Label resolved; - __ get_cache_and_index_at_bcp(Rcache, index, 1); - __ movl(temp, Address(Rcache, - index, Address::times_8, - constantPoolCacheOopDesc::base_offset() + - ConstantPoolCacheEntry::indices_offset())); - __ shrl(temp, shift_count); - // have we resolved this bytecode? - __ andl(temp, 0xFF); - __ cmpl(temp, (int) bytecode()); - __ jcc(Assembler::equal, resolved); + __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); + if (is_invokedynamic) { + // we are resolved if the f1 field contains a non-null CallSite object + __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD); + __ jcc(Assembler::notEqual, resolved); + } else { + __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset())); + __ shrl(temp, shift_count); + // have we resolved this bytecode? + __ andl(temp, 0xFF); + __ cmpl(temp, (int) bytecode()); + __ jcc(Assembler::equal, resolved); + } // resolve first time through address entry; @@ -2090,6 +2089,9 @@ case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; + case Bytecodes::_invokedynamic: + entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); + break; default: ShouldNotReachHere(); break; @@ -2098,7 +2100,7 @@ __ call_VM(noreg, entry, temp); // Update registers with resolved info - __ get_cache_and_index_at_bcp(Rcache, index, 1); + __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); __ bind(resolved); } @@ -2832,15 +2834,14 @@ ShouldNotReachHere(); } -void TemplateTable::prepare_invoke(Register method, - Register index, - int byte_no, - Bytecodes::Code code) { +void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) { // determine flags + Bytecodes::Code code = bytecode(); const bool is_invokeinterface = code == Bytecodes::_invokeinterface; + const bool is_invokedynamic = code == Bytecodes::_invokedynamic; const bool is_invokevirtual = code == Bytecodes::_invokevirtual; const bool is_invokespecial = code == Bytecodes::_invokespecial; - const bool load_receiver = code != Bytecodes::_invokestatic; + const bool load_receiver = (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic); const bool receiver_null_check = is_invokespecial; const bool save_flags = is_invokeinterface || is_invokevirtual; // setup registers & access constant pool cache @@ -2858,9 +2859,13 @@ __ movl(recv, flags); __ andl(recv, 0xFF); if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 - __ movptr(recv, Address(rsp, recv, Address::times_8, - -Interpreter::expr_offset_in_bytes(1))); - __ verify_oop(recv); + Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)); + if (is_invokedynamic) { + __ lea(recv, recv_addr); + } else { + __ movptr(recv, recv_addr); + __ verify_oop(recv); + } } // do null check if needed @@ -2878,10 +2883,14 @@ ConstantPoolCacheEntry::verify_tosBits(); // load return address { - ExternalAddress return_5((address)Interpreter::return_5_addrs_by_index_table()); - ExternalAddress return_3((address)Interpreter::return_3_addrs_by_index_table()); - __ lea(rscratch1, (is_invokeinterface ? return_5 : return_3)); - __ movptr(flags, Address(rscratch1, flags, Address::times_8)); + address table_addr; + if (is_invokeinterface || is_invokedynamic) + table_addr = (address)Interpreter::return_5_addrs_by_index_table(); + else + table_addr = (address)Interpreter::return_3_addrs_by_index_table(); + ExternalAddress table(table_addr); + __ lea(rscratch1, table); + __ movptr(flags, Address(rscratch1, flags, Address::times_ptr)); } // push return address @@ -2947,7 +2956,7 @@ void TemplateTable::invokevirtual(int byte_no) { transition(vtos, vtos); - prepare_invoke(rbx, noreg, byte_no, bytecode()); + prepare_invoke(rbx, noreg, byte_no); // rbx: index // rcx: receiver @@ -2959,7 +2968,7 @@ void TemplateTable::invokespecial(int byte_no) { transition(vtos, vtos); - prepare_invoke(rbx, noreg, byte_no, bytecode()); + prepare_invoke(rbx, noreg, byte_no); // do the call __ verify_oop(rbx); __ profile_call(rax); @@ -2969,7 +2978,7 @@ void TemplateTable::invokestatic(int byte_no) { transition(vtos, vtos); - prepare_invoke(rbx, noreg, byte_no, bytecode()); + prepare_invoke(rbx, noreg, byte_no); // do the call __ verify_oop(rbx); __ profile_call(rax); @@ -2983,7 +2992,7 @@ void TemplateTable::invokeinterface(int byte_no) { transition(vtos, vtos); - prepare_invoke(rax, rbx, byte_no, bytecode()); + prepare_invoke(rax, rbx, byte_no); // rax: Interface // rbx: index @@ -3072,7 +3081,24 @@ return; } - __ stop("invokedynamic NYI");//6815692// + prepare_invoke(rax, rbx, byte_no); + + // rax: CallSite object (f1) + // rbx: unused (f2) + // rcx: receiver address + // rdx: flags (unused) + + if (ProfileInterpreter) { + Label L; + // %%% should make a type profile for any invokedynamic that takes a ref argument + // profile this call + __ profile_call(r13); + } + + __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx))); + __ null_check(rcx); + __ prepare_to_jump_from_interpreted(); + __ jump_to_method_handle_entry(rcx, rdx); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/templateTable_x86_64.hpp --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,8 +22,7 @@ * */ - static void prepare_invoke(Register method, Register index, int byte_no, - Bytecodes::Code code); + static void prepare_invoke(Register method, Register index, int byte_no); static void invokevirtual_helper(Register index, Register recv, Register flags); static void volatile_barrier(Assembler::Membar_mask_bits order_constraint); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/x86/vm/vm_version_x86.cpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -255,6 +255,8 @@ if (!VM_Version::supports_sse2()) { vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported"); } + // in 64 bit the use of SSE2 is the minimum + if (UseSSE < 2) UseSSE = 2; #endif // If the OS doesn't support SSE, we can't use this feature even if the HW does diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -204,6 +204,20 @@ goto unwind_and_return; } + // Update the invocation counter + if ((UseCompiler || CountCompiledCalls) && !method->is_synchronized()) { + thread->set_do_not_unlock(); + InvocationCounter *counter = method->invocation_counter(); + counter->increment(); + if (counter->reached_InvocationLimit()) { + CALL_VM_NOCHECK( + InterpreterRuntime::frequency_counter_overflow(thread, NULL)); + if (HAS_PENDING_EXCEPTION) + goto unwind_and_return; + } + thread->clr_do_not_unlock(); + } + // Lock if necessary BasicObjectLock *monitor; monitor = NULL; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/zero/vm/frame_zero.cpp --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -36,11 +36,8 @@ return zeroframe()->is_interpreter_frame(); } -bool frame::is_fake_stub_frame() const { - return zeroframe()->is_fake_stub_frame(); -} - frame frame::sender_for_entry_frame(RegisterMap *map) const { + assert(zeroframe()->is_entry_frame(), "wrong type of frame"); assert(map != NULL, "map must be set"); assert(!entry_frame_is_first(), "next Java fp must be non zero"); assert(entry_frame_call_wrapper()->anchor()->last_Java_sp() == sender_sp(), @@ -50,15 +47,10 @@ return frame(sender_sp(), sp() + 1); } -frame frame::sender_for_interpreter_frame(RegisterMap *map) const { - return frame(sender_sp(), sp() + 1); -} - -frame frame::sender_for_compiled_frame(RegisterMap *map) const { - return frame(sender_sp(), sp() + 1); -} - -frame frame::sender_for_fake_stub_frame(RegisterMap *map) const { +frame frame::sender_for_nonentry_frame(RegisterMap *map) const { + assert(zeroframe()->is_interpreter_frame() || + zeroframe()->is_shark_frame() || + zeroframe()->is_fake_stub_frame(), "wrong type of frame"); return frame(sender_sp(), sp() + 1); } @@ -69,17 +61,8 @@ if (is_entry_frame()) return sender_for_entry_frame(map); - - if (is_interpreted_frame()) - return sender_for_interpreter_frame(map); - - if (is_compiled_frame()) - return sender_for_compiled_frame(map); - - if (is_fake_stub_frame()) - return sender_for_fake_stub_frame(map); - - ShouldNotReachHere(); + else + return sender_for_nonentry_frame(map); } #ifdef CC_INTERP diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/zero/vm/frame_zero.hpp --- a/hotspot/src/cpu/zero/vm/frame_zero.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -65,10 +65,7 @@ } public: - bool is_fake_stub_frame() const; - - public: - frame sender_for_fake_stub_frame(RegisterMap* map) const; + frame sender_for_nonentry_frame(RegisterMap* map) const; public: void zero_print_on_error(int index, diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/zero/vm/globals_zero.hpp --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -23,10 +23,8 @@ * */ -// // 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); @@ -37,14 +35,7 @@ define_pd_global(bool, UncommonNullCast, true); define_pd_global(intx, CodeEntryAlignment, 32); -define_pd_global(uintx, TLABSize, 0); -#ifdef _LP64 -define_pd_global(uintx, NewSize, ScaleForWordSize(2048 * K)); -#else -define_pd_global(uintx, NewSize, ScaleForWordSize(1024 * K)); -#endif // _LP64 define_pd_global(intx, InlineFrequencyCount, 100); -define_pd_global(intx, InlineSmallCode, 1000); define_pd_global(intx, PreInflateSpin, 10); define_pd_global(intx, StackYellowPages, 2); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp --- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,14 @@ BasicType *in_sig_bt, VMRegPair *in_regs, BasicType ret_type) { +#ifdef SHARK + return SharkCompiler::compiler()->generate_native_wrapper(masm, + method, + in_sig_bt, + ret_type); +#else ShouldNotCallThis(); +#endif // SHARK } int Deoptimization::last_frame_adjust(int callee_parameters, diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp --- a/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2008 Red Hat, Inc. + * Copyright 2008, 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ // | ... | class SharkFrame : public ZeroFrame { - friend class SharkFunction; + friend class SharkStack; private: SharkFrame() : ZeroFrame() { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -223,8 +223,8 @@ "environment on Linux when /proc filesystem is not mounted."; void os::Linux::initialize_system_info() { - _processor_count = sysconf(_SC_NPROCESSORS_CONF); - if (_processor_count == 1) { + set_processor_count(sysconf(_SC_NPROCESSORS_CONF)); + if (processor_count() == 1) { pid_t pid = os::Linux::gettid(); char fname[32]; jio_snprintf(fname, sizeof(fname), "/proc/%d", pid); @@ -236,7 +236,7 @@ } } _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE); - assert(_processor_count > 0, "linux error"); + assert(processor_count() > 0, "linux error"); } void os::init_system_properties_values() { @@ -4683,6 +4683,7 @@ // Return immediately if a permit is available. if (_counter > 0) { _counter = 0 ; + OrderAccess::fence(); return ; } @@ -4725,6 +4726,7 @@ _counter = 0; status = pthread_mutex_unlock(_mutex); assert (status == 0, "invariant") ; + OrderAccess::fence(); return; } @@ -4765,6 +4767,7 @@ jt->java_suspend_self(); } + OrderAccess::fence(); } void Parker::unpark() { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/os/solaris/dtrace/libjvm_db.c --- a/hotspot/src/os/solaris/dtrace/libjvm_db.c Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c Wed Jul 05 17:05:01 2017 +0200 @@ -937,54 +937,56 @@ return err; } -static int -scopeDesc_chain(Nmethod_t *N) -{ +static int scopeDesc_chain(Nmethod_t *N) { int32_t decode_offset = 0; int32_t err; - if (debug > 2) - fprintf(stderr, "\t scopeDesc_chain: BEGIN\n"); + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: BEGIN\n"); + } err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset, &decode_offset, SZ32); CHECK_FAIL(err); while (decode_offset > 0) { - if (debug > 2) - fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset); + Vframe_t *vf = &N->vframes[N->vf_cnt]; - Vframe_t *vf = &N->vframes[N->vf_cnt]; + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset); + } + + err = scope_desc_at(N, decode_offset, vf); + CHECK_FAIL(err); - err = scope_desc_at(N, decode_offset, vf); - CHECK_FAIL(err); + if (vf->methodIdx > N->oops_len) { + fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops_len) !\n"); + return -1; + } + err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE, + &vf->methodOop); + CHECK_FAIL(err); - if (vf->methodIdx > N->oops_len) { - fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops_len) !\n"); - return -1; - } - err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE, - &vf->methodOop); + if (vf->methodOop) { + N->vf_cnt++; + err = line_number_from_bci(N->J, vf); CHECK_FAIL(err); - - if (vf->methodOop) { - N->vf_cnt++; - err = line_number_from_bci(N->J, vf); - CHECK_FAIL(err); - if (debug > 2) { - fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n", - vf->methodOop, vf->line); - } + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n", + vf->methodOop, vf->line); } - decode_offset = vf->sender_decode_offset; + } + decode_offset = vf->sender_decode_offset; } - if (debug > 2) - fprintf(stderr, "\t scopeDesc_chain: END \n\n"); + if (debug > 2) { + fprintf(stderr, "\t scopeDesc_chain: END \n\n"); + } return PS_OK; fail: - if (debug) - fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n"); + if (debug) { + fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n"); + } return err; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/os/solaris/vm/os_solaris.cpp --- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -457,7 +457,7 @@ void os::Solaris::initialize_system_info() { - _processor_count = sysconf(_SC_NPROCESSORS_CONF); + set_processor_count(sysconf(_SC_NPROCESSORS_CONF)); _processors_online = sysconf (_SC_NPROCESSORS_ONLN); _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE); } @@ -5803,6 +5803,7 @@ // Return immediately if a permit is available. if (_counter > 0) { _counter = 0 ; + OrderAccess::fence(); return ; } @@ -5846,6 +5847,7 @@ _counter = 0; status = os::Solaris::mutex_unlock(_mutex); assert (status == 0, "invariant") ; + OrderAccess::fence(); return; } @@ -5892,6 +5894,7 @@ jt->java_suspend_self(); } + OrderAccess::fence(); } void Parker::unpark() { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -3150,7 +3150,7 @@ _vm_allocation_granularity = si.dwAllocationGranularity; _processor_type = si.dwProcessorType; _processor_level = si.wProcessorLevel; - _processor_count = si.dwNumberOfProcessors; + set_processor_count(si.dwNumberOfProcessors); MEMORYSTATUSEX ms; ms.dwLength = sizeof(ms); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp --- a/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/os_cpu/linux_x86/vm/globals_linux_x86.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,10 +22,9 @@ * */ -// // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -// + define_pd_global(bool, DontYieldALot, false); #ifdef AMD64 define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default @@ -39,11 +38,10 @@ #endif // AMD64 define_pd_global(intx, CompilerThreadStackSize, 0); -define_pd_global(intx, SurvivorRatio, 8); -define_pd_global(uintx, JVMInvokeMethodSlack, 8192); +define_pd_global(uintx,JVMInvokeMethodSlack, 8192); // Only used on 64 bit platforms -define_pd_global(uintx, HeapBaseMinAddress, 2*G); +define_pd_global(uintx,HeapBaseMinAddress, 2*G); // Only used on 64 bit Windows platforms define_pd_global(bool, UseVectoredExceptions, false); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp --- a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,31 +22,25 @@ * */ -// // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -// + define_pd_global(bool, DontYieldALot, true); // Determined in the design center #ifdef AMD64 define_pd_global(intx, ThreadStackSize, 1024); // 0 => use system default define_pd_global(intx, VMThreadStackSize, 1024); -define_pd_global(intx, SurvivorRatio, 6); -define_pd_global(uintx, JVMInvokeMethodSlack, 8*K); +define_pd_global(uintx,JVMInvokeMethodSlack, 8*K); #else -// UseStackBanging is not pd -// define_pd_global(bool, UseStackBanging, true); - // ThreadStackSize 320 allows TaggedStackInterpreter and a couple of test cases // to run while keeping the number of threads that can be created high. define_pd_global(intx, ThreadStackSize, 320); define_pd_global(intx, VMThreadStackSize, 512); -define_pd_global(intx, SurvivorRatio, 8); -define_pd_global(uintx, JVMInvokeMethodSlack, 10*K); +define_pd_global(uintx,JVMInvokeMethodSlack, 10*K); #endif // AMD64 define_pd_global(intx, CompilerThreadStackSize, 0); // Only used on 64 bit platforms -define_pd_global(uintx, HeapBaseMinAddress, 256*M); +define_pd_global(uintx,HeapBaseMinAddress, 256*M); // Only used on 64 bit Windows platforms define_pd_global(bool, UseVectoredExceptions, false); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp --- a/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/os_cpu/windows_x86/vm/globals_windows_x86.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -22,10 +22,9 @@ * */ -// // Sets the default values for platform dependent flags used by the runtime system. // (see globals.hpp) -// + define_pd_global(bool, DontYieldALot, false); // Default stack size on Windows is determined by the executable (java.exe @@ -35,8 +34,6 @@ define_pd_global(intx, ThreadStackSize, 0); // 0 => use system default define_pd_global(intx, VMThreadStackSize, 0); // 0 => use system default -define_pd_global(intx, SurvivorRatio, 8); - #ifdef ASSERT define_pd_global(intx, CompilerThreadStackSize, 1024); #else diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -365,7 +365,7 @@ if (_next_loop_index < 31) _next_loop_index++; } else { // block already marked as loop header - assert(is_power_of_2(_loop_map.at(block->block_id())), "exactly one bit must be set"); + assert(is_power_of_2((unsigned int)_loop_map.at(block->block_id())), "exactly one bit must be set"); } } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1855,12 +1855,26 @@ addr = new LIR_Address(base_op, index_op->as_jint(), dst_type); } else { #ifdef X86 +#ifdef _LP64 + if (!index_op->is_illegal() && index_op->type() == T_INT) { + LIR_Opr tmp = new_pointer_register(); + __ convert(Bytecodes::_i2l, index_op, tmp); + index_op = tmp; + } +#endif addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type); #else if (index_op->is_illegal() || log2_scale == 0) { +#ifdef _LP64 + if (!index_op->is_illegal() && index_op->type() == T_INT) { + LIR_Opr tmp = new_pointer_register(); + __ convert(Bytecodes::_i2l, index_op, tmp); + index_op = tmp; + } +#endif addr = new LIR_Address(base_op, index_op, dst_type); } else { - LIR_Opr tmp = new_register(T_INT); + LIR_Opr tmp = new_pointer_register(); __ shift_left(index_op, log2_scale, tmp); addr = new LIR_Address(base_op, tmp, dst_type); } @@ -1915,10 +1929,25 @@ LIR_Opr index_op = idx.result(); if (log2_scale != 0) { // temporary fix (platform dependent code without shift on Intel would be better) - index_op = new_register(T_INT); - __ move(idx.result(), index_op); + index_op = new_pointer_register(); +#ifdef _LP64 + if(idx.result()->type() == T_INT) { + __ convert(Bytecodes::_i2l, idx.result(), index_op); + } else { +#endif + __ move(idx.result(), index_op); +#ifdef _LP64 + } +#endif __ shift_left(index_op, log2_scale, index_op); } +#ifdef _LP64 + else if(!index_op->is_illegal() && index_op->type() == T_INT) { + LIR_Opr tmp = new_pointer_register(); + __ convert(Bytecodes::_i2l, index_op, tmp); + index_op = tmp; + } +#endif LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type()); __ move(value.result(), addr); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -2464,6 +2464,10 @@ case T_LONG: // fall through case T_DOUBLE: { +#ifdef _LP64 + scope_values->append(&_int_0_scope_value); + scope_values->append(new ConstantLongValue(c->as_jlong_bits())); +#else if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) { scope_values->append(new ConstantIntValue(c->as_jint_hi_bits())); scope_values->append(new ConstantIntValue(c->as_jint_lo_bits())); @@ -2471,7 +2475,7 @@ scope_values->append(new ConstantIntValue(c->as_jint_lo_bits())); scope_values->append(new ConstantIntValue(c->as_jint_hi_bits())); } - +#endif return 2; } @@ -2503,17 +2507,18 @@ } else if (opr->is_single_cpu()) { bool is_oop = opr->is_oop_register(); int cache_idx = opr->cpu_regnr() * 2 + (is_oop ? 1 : 0); + Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long); ScopeValue* sv = _scope_value_cache.at(cache_idx); if (sv == NULL) { - Location::Type loc_type = is_oop ? Location::oop : Location::normal; + Location::Type loc_type = is_oop ? Location::oop : int_loc_type; VMReg rname = frame_map()->regname(opr); sv = new LocationValue(Location::new_reg_loc(loc_type, rname)); _scope_value_cache.at_put(cache_idx, sv); } // check if cached value is correct - DEBUG_ONLY(assert_equal(sv, new LocationValue(Location::new_reg_loc(is_oop ? Location::oop : Location::normal, frame_map()->regname(opr))))); + DEBUG_ONLY(assert_equal(sv, new LocationValue(Location::new_reg_loc(is_oop ? Location::oop : int_loc_type, frame_map()->regname(opr))))); scope_values->append(sv); return 1; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp --- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -61,9 +61,11 @@ BCEscapeAnalyzer* _parent; int _level; + public: class ArgumentMap; class StateInfo; + private: // helper functions bool is_argument(int i) { return i >= 0 && i < _arg_size; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -46,6 +46,9 @@ ciInstanceKlass* ciEnv::_Thread; ciInstanceKlass* ciEnv::_OutOfMemoryError; ciInstanceKlass* ciEnv::_String; +ciInstanceKlass* ciEnv::_StringBuffer; +ciInstanceKlass* ciEnv::_StringBuilder; +ciInstanceKlass* ciEnv::_Integer; ciSymbol* ciEnv::_unloaded_cisymbol = NULL; ciInstanceKlass* ciEnv::_unloaded_ciinstance_klass = NULL; @@ -110,6 +113,8 @@ _ArrayIndexOutOfBoundsException_instance = NULL; _ArrayStoreException_instance = NULL; _ClassCastException_instance = NULL; + _the_null_string = NULL; + _the_min_jint_string = NULL; } ciEnv::ciEnv(Arena* arena) { @@ -163,6 +168,8 @@ _ArrayIndexOutOfBoundsException_instance = NULL; _ArrayStoreException_instance = NULL; _ClassCastException_instance = NULL; + _the_null_string = NULL; + _the_min_jint_string = NULL; } ciEnv::~ciEnv() { @@ -248,6 +255,22 @@ return _ClassCastException_instance; } +ciInstance* ciEnv::the_null_string() { + if (_the_null_string == NULL) { + VM_ENTRY_MARK; + _the_null_string = get_object(Universe::the_null_string())->as_instance(); + } + return _the_null_string; +} + +ciInstance* ciEnv::the_min_jint_string() { + if (_the_min_jint_string == NULL) { + VM_ENTRY_MARK; + _the_min_jint_string = get_object(Universe::the_min_jint_string())->as_instance(); + } + return _the_min_jint_string; +} + // ------------------------------------------------------------------ // ciEnv::get_method_from_handle ciMethod* ciEnv::get_method_from_handle(jobject method) { @@ -690,10 +713,8 @@ ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder); // Get the method's name and signature. - int nt_index = cpool->name_and_type_ref_index_at(index); - int sig_index = cpool->signature_ref_index_at(nt_index); symbolOop name_sym = cpool->name_ref_at(index); - symbolOop sig_sym = cpool->symbol_at(sig_index); + symbolOop sig_sym = cpool->signature_ref_at(index); if (holder_is_accessible) { // Our declared holder is loaded. instanceKlass* lookup = declared_holder->get_instanceKlass(); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/ci/ciEnv.hpp --- a/hotspot/src/share/vm/ci/ciEnv.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -82,6 +82,9 @@ static ciInstanceKlass* _Thread; static ciInstanceKlass* _OutOfMemoryError; static ciInstanceKlass* _String; + static ciInstanceKlass* _StringBuffer; + static ciInstanceKlass* _StringBuilder; + static ciInstanceKlass* _Integer; static ciSymbol* _unloaded_cisymbol; static ciInstanceKlass* _unloaded_ciinstance_klass; @@ -97,6 +100,9 @@ ciInstance* _ArrayStoreException_instance; ciInstance* _ClassCastException_instance; + ciInstance* _the_null_string; // The Java string "null" + ciInstance* _the_min_jint_string; // The Java string "-2147483648" + // Look up a klass by name from a particular class loader (the accessor's). // If require_local, result must be defined in that class loader, or NULL. // If !require_local, a result from remote class loader may be reported, @@ -310,6 +316,15 @@ ciInstanceKlass* String_klass() { return _String; } + ciInstanceKlass* StringBuilder_klass() { + return _StringBuilder; + } + ciInstanceKlass* StringBuffer_klass() { + return _StringBuffer; + } + ciInstanceKlass* Integer_klass() { + return _Integer; + } ciInstance* NullPointerException_instance() { assert(_NullPointerException_instance != NULL, "initialization problem"); return _NullPointerException_instance; @@ -324,6 +339,9 @@ ciInstance* ArrayStoreException_instance(); ciInstance* ClassCastException_instance(); + ciInstance* the_null_string(); + ciInstance* the_min_jint_string(); + static ciSymbol* unloaded_cisymbol() { return _unloaded_cisymbol; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/ci/ciInstanceKlass.cpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -341,6 +341,20 @@ } // ------------------------------------------------------------------ +// ciInstanceKlass::get_field_by_name +ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static) { + VM_ENTRY_MARK; + instanceKlass* k = get_instanceKlass(); + fieldDescriptor fd; + klassOop def = k->find_field(name->get_symbolOop(), signature->get_symbolOop(), is_static, &fd); + if (def == NULL) { + return NULL; + } + ciField* field = new (CURRENT_THREAD_ENV->arena()) ciField(&fd); + return field; +} + +// ------------------------------------------------------------------ // ciInstanceKlass::non_static_fields. class NonStaticFieldFiller: public FieldClosure { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/ci/ciInstanceKlass.hpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -148,6 +148,7 @@ ciInstanceKlass* get_canonical_holder(int offset); ciField* get_field_by_offset(int field_offset, bool is_static); + ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static); GrowableArray* non_static_fields(); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/ci/ciObjectFactory.cpp --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -168,6 +168,15 @@ ciEnv::_String = get(SystemDictionary::string_klass()) ->as_instance_klass(); + ciEnv::_StringBuffer = + get(SystemDictionary::stringBuffer_klass()) + ->as_instance_klass(); + ciEnv::_StringBuilder = + get(SystemDictionary::StringBuilder_klass()) + ->as_instance_klass(); + ciEnv::_Integer = + get(SystemDictionary::int_klass()) + ->as_instance_klass(); for (int len = -1; len != _ci_objects->length(); ) { len = _ci_objects->length(); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -2511,23 +2511,12 @@ fac_ptr->nonstatic_byte_count -= 1; (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); - if (wordSize == jintSize) { - fac_ptr->nonstatic_word_count += 1; - } else { - fac_ptr->nonstatic_double_count += 1; - } - - FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4); + fac_ptr->nonstatic_word_count += 1; + + FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i + instanceKlass::low_offset); assert(atype == NONSTATIC_BYTE, ""); FieldAllocationType new_atype = NONSTATIC_WORD; - if (wordSize > jintSize) { - if (Universe::field_type_should_be_aligned(T_LONG)) { - atype = NONSTATIC_ALIGNED_DOUBLE; - } else { - atype = NONSTATIC_DOUBLE; - } - } - (*fields_ptr)->ushort_at_put(i+4, new_atype); + (*fields_ptr)->ushort_at_put(i + instanceKlass::low_offset, new_atype); found_vmentry = true; break; @@ -3085,7 +3074,7 @@ int len = fields->length(); for (int i = 0; i < len; i += instanceKlass::next_offset) { int real_offset; - FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i+4); + FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); switch (atype) { case STATIC_OOP: real_offset = next_static_oop_offset; @@ -3173,8 +3162,8 @@ default: ShouldNotReachHere(); } - fields->short_at_put(i+4, extract_low_short_from_int(real_offset) ); - fields->short_at_put(i+5, extract_high_short_from_int(real_offset) ); + fields->short_at_put(i + instanceKlass::low_offset, extract_low_short_from_int(real_offset)); + fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset)); } // Size of instances @@ -3766,8 +3755,9 @@ } bool ClassFileParser::is_supported_version(u2 major, u2 minor) { - u2 max_version = JDK_Version::is_gte_jdk17x_version() ? - JAVA_MAX_SUPPORTED_VERSION : JAVA_6_VERSION; + u2 max_version = + JDK_Version::is_gte_jdk17x_version() ? JAVA_MAX_SUPPORTED_VERSION : + (JDK_Version::is_gte_jdk16x_version() ? JAVA_6_VERSION : JAVA_1_5_VERSION); return (major >= JAVA_MIN_SUPPORTED_VERSION) && (major <= max_version) && ((major != max_version) || diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1124,8 +1124,7 @@ if (_dirty && _methods != NULL) { BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); - bs->write_ref_array(MemRegion((HeapWord*)_methods->base(), - _methods->array_size())); + bs->write_ref_array((HeapWord*)_methods->base(), _methods->length()); _dirty = false; } } @@ -2430,15 +2429,15 @@ } -// Support for sun_dyn_CallSiteImpl - -int sun_dyn_CallSiteImpl::_type_offset; -int sun_dyn_CallSiteImpl::_target_offset; -int sun_dyn_CallSiteImpl::_vmmethod_offset; - -void sun_dyn_CallSiteImpl::compute_offsets() { +// Support for java_dyn_CallSite + +int java_dyn_CallSite::_type_offset; +int java_dyn_CallSite::_target_offset; +int java_dyn_CallSite::_vmmethod_offset; + +void java_dyn_CallSite::compute_offsets() { if (!EnableInvokeDynamic) return; - klassOop k = SystemDictionary::CallSiteImpl_klass(); + klassOop k = SystemDictionary::CallSite_klass(); if (k != NULL) { compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true); compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature(), true); @@ -2446,23 +2445,23 @@ } } -oop sun_dyn_CallSiteImpl::type(oop site) { +oop java_dyn_CallSite::type(oop site) { return site->obj_field(_type_offset); } -oop sun_dyn_CallSiteImpl::target(oop site) { +oop java_dyn_CallSite::target(oop site) { return site->obj_field(_target_offset); } -void sun_dyn_CallSiteImpl::set_target(oop site, oop target) { +void java_dyn_CallSite::set_target(oop site, oop target) { site->obj_field_put(_target_offset, target); } -oop sun_dyn_CallSiteImpl::vmmethod(oop site) { +oop java_dyn_CallSite::vmmethod(oop site) { return site->obj_field(_vmmethod_offset); } -void sun_dyn_CallSiteImpl::set_vmmethod(oop site, oop ref) { +void java_dyn_CallSite::set_vmmethod(oop site, oop ref) { site->obj_field_put(_vmmethod_offset, ref); } @@ -2811,7 +2810,7 @@ java_dyn_MethodTypeForm::compute_offsets(); } if (EnableInvokeDynamic) { - sun_dyn_CallSiteImpl::compute_offsets(); + java_dyn_CallSite::compute_offsets(); } java_security_AccessControlContext::compute_offsets(); // Initialize reflection classes. The layouts of these classes diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/javaClasses.hpp --- a/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -1061,9 +1061,9 @@ }; -// Interface to sun.dyn.CallSiteImpl objects +// Interface to java.dyn.CallSite objects -class sun_dyn_CallSiteImpl: AllStatic { +class java_dyn_CallSite: AllStatic { friend class JavaClasses; private: diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -99,6 +99,15 @@ return java_lang_Class::parallelCapable(class_loader()); } // ---------------------------------------------------------------------------- +// ParallelDefineClass flag does not apply to bootclass loader +bool SystemDictionary::is_parallelDefine(Handle class_loader) { + if (class_loader.is_null()) return false; + if (AllowParallelDefineClass && java_lang_Class::parallelCapable(class_loader())) { + return true; + } + return false; +} +// ---------------------------------------------------------------------------- // Resolving of classes // Forwards to resolve_or_null @@ -724,13 +733,13 @@ // Do actual loading k = load_instance_class(name, class_loader, THREAD); - // For UnsyncloadClass and AllowParallelDefineClass only: + // For UnsyncloadClass only // If they got a linkageError, check if a parallel class load succeeded. // If it did, then for bytecode resolution the specification requires // that we return the same result we did for the other thread, i.e. the // successfully loaded instanceKlass // Should not get here for classloaders that support parallelism - // with the new cleaner mechanism + // with the new cleaner mechanism, even with AllowParallelDefineClass // Bootstrap goes through here to allow for an extra guarantee check if (UnsyncloadClass || (class_loader.is_null())) { if (k.is_null() && HAS_PENDING_EXCEPTION @@ -1483,14 +1492,17 @@ } // Support parallel classloading -// Initial implementation for bootstrap classloader -// For custom class loaders that support parallel classloading, +// All parallel class loaders, including bootstrap classloader +// lock a placeholder entry for this class/class_loader pair +// to allow parallel defines of different classes for this class loader // With AllowParallelDefine flag==true, in case they do not synchronize around // FindLoadedClass/DefineClass, calls, we check for parallel // loading for them, wait if a defineClass is in progress // and return the initial requestor's results +// This flag does not apply to the bootstrap classloader. // With AllowParallelDefine flag==false, call through to define_instance_class // which will throw LinkageError: duplicate class definition. +// False is the requested default. // For better performance, the class loaders should synchronize // findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they // potentially waste time reading and parsing the bytestream. @@ -1511,9 +1523,11 @@ { MutexLocker mu(SystemDictionary_lock, THREAD); // First check if class already defined - klassOop check = find_class(d_index, d_hash, name_h, class_loader); - if (check != NULL) { - return(instanceKlassHandle(THREAD, check)); + if (UnsyncloadClass || (is_parallelDefine(class_loader))) { + klassOop check = find_class(d_index, d_hash, name_h, class_loader); + if (check != NULL) { + return(instanceKlassHandle(THREAD, check)); + } } // Acquire define token for this class/classloader @@ -1529,7 +1543,7 @@ // Only special cases allow parallel defines and can use other thread's results // Other cases fall through, and may run into duplicate defines // caught by finding an entry in the SystemDictionary - if ((UnsyncloadClass || AllowParallelDefineClass) && (probe->instanceKlass() != NULL)) { + if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instanceKlass() != NULL)) { probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD); SystemDictionary_lock->notify_all(); @@ -1973,7 +1987,7 @@ WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass); initialize_wk_klasses_until(indy_group_start, scan, CHECK); if (EnableInvokeDynamic) { - initialize_wk_klasses_through(indy_group_start, scan, CHECK); + initialize_wk_klasses_through(indy_group_end, scan, CHECK); } if (_well_known_klasses[indy_group_start] == NULL) { // Skip the rest of the dynamic typing classes, if Linkage is not loaded. @@ -2404,7 +2418,7 @@ methodHandle mh_invdyn, TRAPS) { Handle empty; - // call sun.dyn.CallSiteImpl::makeSite(caller, name, mtype, cmid, cbci) + // call java.dyn.CallSite::makeSite(caller, name, mtype, cmid, cbci) oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle! JavaCallArguments args(Handle(THREAD, caller->java_mirror())); args.push_oop(name_str_oop); @@ -2413,17 +2427,19 @@ args.push_int(caller_bci); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, - SystemDictionary::CallSiteImpl_klass(), + SystemDictionary::CallSite_klass(), vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(), &args, CHECK_(empty)); oop call_site_oop = (oop) result.get_jobject(); assert(call_site_oop->is_oop() - /*&& sun_dyn_CallSiteImpl::is_instance(call_site_oop)*/, "must be sane"); - sun_dyn_CallSiteImpl::set_vmmethod(call_site_oop, mh_invdyn()); + /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane"); + java_dyn_CallSite::set_vmmethod(call_site_oop, mh_invdyn()); if (TraceMethodHandles) { +#ifndef PRODUCT tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); call_site_oop->print(); tty->cr(); +#endif //PRODUCT } return call_site_oop; } @@ -2436,9 +2452,17 @@ instanceKlassHandle ik(THREAD, caller()); - if (ik->bootstrap_method() != NULL) { - return Handle(THREAD, ik->bootstrap_method()); + oop boot_method_oop = ik->bootstrap_method(); + if (boot_method_oop != NULL) { + if (TraceMethodHandles) { + tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop); + } + NOT_PRODUCT(if (!boot_method_oop->is_oop()) { tty->print_cr("*** boot MH of "PTR_FORMAT" = "PTR_FORMAT, ik(), boot_method_oop); ik()->print(); }); + assert(boot_method_oop->is_oop() + && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); + return Handle(THREAD, boot_method_oop); } + boot_method_oop = NULL; // GC safety // call java.dyn.Linkage::findBootstrapMethod(caller, sbk) JavaCallArguments args(Handle(THREAD, ik->java_mirror())); @@ -2452,9 +2476,18 @@ vmSymbols::findBootstrapMethod_name(), vmSymbols::findBootstrapMethod_signature(), &args, CHECK_(empty)); - oop boot_method_oop = (oop) result.get_jobject(); + boot_method_oop = (oop) result.get_jobject(); if (boot_method_oop != NULL) { + if (TraceMethodHandles) { +#ifndef PRODUCT + tty->print_cr("--------"); + tty->print_cr("bootstrap method for "PTR_FORMAT" computed as "PTR_FORMAT":", ik(), boot_method_oop); + ik()->print(); + boot_method_oop->print(); + tty->print_cr("========"); +#endif //PRODUCT + } assert(boot_method_oop->is_oop() && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); // probably no race conditions, but let's be careful: @@ -2463,6 +2496,14 @@ else boot_method_oop = ik->bootstrap_method(); } else { + if (TraceMethodHandles) { +#ifndef PRODUCT + tty->print_cr("--------"); + tty->print_cr("bootstrap method for "PTR_FORMAT" computed as NULL:", ik()); + ik()->print(); + tty->print_cr("========"); +#endif //PRODUCT + } boot_method_oop = ik->bootstrap_method(); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/systemDictionary.hpp --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -144,13 +144,13 @@ template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ template(Linkage_klass, java_dyn_Linkage, Opt) \ template(CallSite_klass, java_dyn_CallSite, Opt) \ - template(CallSiteImpl_klass, sun_dyn_CallSiteImpl, Opt) \ template(Dynamic_klass, java_dyn_Dynamic, Opt) \ /* Note: MethodHandle must be first, and Dynamic last in group */ \ \ template(vector_klass, java_util_Vector, Pre) \ template(hashtable_klass, java_util_Hashtable, Pre) \ template(stringBuffer_klass, java_lang_StringBuffer, Pre) \ + template(StringBuilder_klass, java_lang_StringBuilder, Pre) \ \ /* It's NULL in non-1.4 JDKs. */ \ template(stackTraceElement_klass, java_lang_StackTraceElement, Opt) \ @@ -578,6 +578,7 @@ static Handle compute_loader_lock_object(Handle class_loader, TRAPS); static void check_loader_lock_contention(Handle loader_lock, TRAPS); static bool is_parallelCapable(Handle class_loader); + static bool is_parallelDefine(Handle class_loader); static klassOop find_shared_class(symbolHandle class_name); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/verifier.cpp --- a/hotspot/src/share/vm/classfile/verifier.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1903,17 +1903,8 @@ verify_cp_type(index, cp, types, CHECK_VERIFY(this)); // Get method name and signature - symbolHandle method_name; - symbolHandle method_sig; - if (opcode == Bytecodes::_invokedynamic) { - int name_index = cp->name_ref_index_at(index); - int sig_index = cp->signature_ref_index_at(index); - method_name = symbolHandle(THREAD, cp->symbol_at(name_index)); - method_sig = symbolHandle(THREAD, cp->symbol_at(sig_index)); - } else { - method_name = symbolHandle(THREAD, cp->name_ref_at(index)); - method_sig = symbolHandle(THREAD, cp->signature_ref_at(index)); - } + symbolHandle method_name(THREAD, cp->name_ref_at(index)); + symbolHandle method_sig(THREAD, cp->signature_ref_at(index)); if (!SignatureVerifier::is_valid_method_signature(method_sig)) { class_format_error( diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/vmSymbols.cpp --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -303,6 +303,11 @@ const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; return (flags & (req | neg)) == req; } +inline bool match_F_Y(jshort flags) { + const int req = JVM_ACC_SYNCHRONIZED; + const int neg = JVM_ACC_STATIC; + return (flags & (req | neg)) == req; +} inline bool match_F_RN(jshort flags) { const int req = JVM_ACC_NATIVE; const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; @@ -361,6 +366,7 @@ const char* sname = vmSymbols::name_for(signature_for(id)); const char* fname = ""; switch (flags_for(id)) { + case F_Y: fname = "synchronized "; break; case F_RN: fname = "native "; break; case F_SN: fname = "native static "; break; case F_S: fname = "static "; break; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -84,6 +84,7 @@ template(java_lang_reflect_Field, "java/lang/reflect/Field") \ template(java_lang_reflect_Array, "java/lang/reflect/Array") \ template(java_lang_StringBuffer, "java/lang/StringBuffer") \ + template(java_lang_StringBuilder, "java/lang/StringBuilder") \ template(java_lang_CharSequence, "java/lang/CharSequence") \ template(java_security_AccessControlContext, "java/security/AccessControlContext") \ template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \ @@ -104,6 +105,7 @@ template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \ template(sun_jkernel_DownloadManager, "sun/jkernel/DownloadManager") \ template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \ + template(setBootClassLoaderHook_name, "setBootClassLoaderHook") \ \ /* class file format tags */ \ template(tag_source_file, "SourceFile") \ @@ -233,10 +235,9 @@ template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \ template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \ template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \ - template(sun_dyn_CallSiteImpl, "sun/dyn/CallSiteImpl") \ template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \ template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \ - template(makeSite_name, "makeSite") /*CallSiteImpl::makeImpl*/ \ + template(makeSite_name, "makeSite") /*CallSite::makeSite*/ \ template(makeSite_signature, "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;II)Ljava/dyn/CallSite;") \ template(findBootstrapMethod_name, "findBootstrapMethod") \ template(findBootstrapMethod_signature, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/dyn/MethodHandle;") \ @@ -335,6 +336,7 @@ template(ptypes_name, "ptypes") \ template(form_name, "form") \ template(erasedType_name, "erasedType") \ + template(append_name, "append") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ @@ -416,6 +418,13 @@ template(string_signature, "Ljava/lang/String;") \ template(reference_signature, "Ljava/lang/ref/Reference;") \ template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \ + template(String_StringBuilder_signature, "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \ + template(int_StringBuilder_signature, "(I)Ljava/lang/StringBuilder;") \ + template(char_StringBuilder_signature, "(C)Ljava/lang/StringBuilder;") \ + template(String_StringBuffer_signature, "(Ljava/lang/String;)Ljava/lang/StringBuffer;") \ + template(int_StringBuffer_signature, "(I)Ljava/lang/StringBuffer;") \ + template(char_StringBuffer_signature, "(C)Ljava/lang/StringBuffer;") \ + template(int_String_signature, "(I)Ljava/lang/String;") \ /* signature symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ \ @@ -815,10 +824,34 @@ /*the compiler does have special inlining code for these; bytecode inline is just fine */ \ \ do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \ - \ - do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ - /* (symbol object_initializer_name defined above) */ \ - \ + \ + do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \ + do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \ + do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \ + \ + do_intrinsic(_StringBuilder_append_char, java_lang_StringBuilder, append_name, char_StringBuilder_signature, F_R) \ + do_intrinsic(_StringBuilder_append_int, java_lang_StringBuilder, append_name, int_StringBuilder_signature, F_R) \ + do_intrinsic(_StringBuilder_append_String, java_lang_StringBuilder, append_name, String_StringBuilder_signature, F_R) \ + \ + do_intrinsic(_StringBuilder_toString, java_lang_StringBuilder, toString_name, void_string_signature, F_R) \ + \ + do_intrinsic(_StringBuffer_void, java_lang_StringBuffer, object_initializer_name, void_method_signature, F_R) \ + do_intrinsic(_StringBuffer_int, java_lang_StringBuffer, object_initializer_name, int_void_signature, F_R) \ + do_intrinsic(_StringBuffer_String, java_lang_StringBuffer, object_initializer_name, string_void_signature, F_R) \ + \ + do_intrinsic(_StringBuffer_append_char, java_lang_StringBuffer, append_name, char_StringBuffer_signature, F_Y) \ + do_intrinsic(_StringBuffer_append_int, java_lang_StringBuffer, append_name, int_StringBuffer_signature, F_Y) \ + do_intrinsic(_StringBuffer_append_String, java_lang_StringBuffer, append_name, String_StringBuffer_signature, F_Y) \ + \ + do_intrinsic(_StringBuffer_toString, java_lang_StringBuffer, toString_name, void_string_signature, F_Y) \ + \ + do_intrinsic(_Integer_toString, java_lang_Integer, toString_name, int_String_signature, F_S) \ + \ + do_intrinsic(_String_String, java_lang_String, object_initializer_name, string_void_signature, F_R) \ + \ + do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ + /* (symbol object_initializer_name defined above) */ \ + \ do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ /* (symbols invoke_name and invoke_signature defined above) */ \ \ @@ -946,11 +979,12 @@ enum Flags { // AccessFlags syndromes relevant to intrinsics. F_none = 0, - F_R, // !static !synchronized (R="regular") - F_S, // static !synchronized - F_RN, // !static native !synchronized - F_SN, // static native !synchronized - F_RNY // !static native synchronized + F_R, // !static ?native !synchronized (R="regular") + F_S, // static ?native !synchronized + F_Y, // !static ?native synchronized + F_RN, // !static native !synchronized + F_SN, // static native !synchronized + F_RNY // !static native synchronized }; public: diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/code/dependencies.cpp --- a/hotspot/src/share/vm/code/dependencies.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/code/dependencies.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1528,19 +1528,23 @@ int nsup = 0, nint = 0; for (ContextStream str(*this); str.next(); ) { klassOop k = str.klass(); - switch (str._change_type) { + switch (str.change_type()) { case Change_new_type: tty->print_cr(" dependee = %s", instanceKlass::cast(k)->external_name()); break; case Change_new_sub: - if (!WizardMode) - ++nsup; - else tty->print_cr(" context super = %s", instanceKlass::cast(k)->external_name()); + if (!WizardMode) { + ++nsup; + } else { + tty->print_cr(" context super = %s", instanceKlass::cast(k)->external_name()); + } break; case Change_new_impl: - if (!WizardMode) - ++nint; - else tty->print_cr(" context interface = %s", instanceKlass::cast(k)->external_name()); + if (!WizardMode) { + ++nint; + } else { + tty->print_cr(" context interface = %s", instanceKlass::cast(k)->external_name()); + } break; } } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/code/dependencies.hpp --- a/hotspot/src/share/vm/code/dependencies.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/code/dependencies.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -470,7 +470,7 @@ // super types can be context types for a relevant dependency, which the // new type could invalidate. class DepChange : public StackObj { - private: + public: enum ChangeType { NO_CHANGE = 0, // an uninvolved klass Change_new_type, // a newly loaded type @@ -480,6 +480,7 @@ Start_Klass = CHANGE_LIMIT // internal indicator for ContextStream }; + private: // each change set is rooted in exactly one new type (at present): KlassHandle _new_type; @@ -510,15 +511,15 @@ // } class ContextStream : public StackObj { private: - DepChange& _changes; + DepChange& _changes; friend class DepChange; // iteration variables: - ChangeType _change_type; - klassOop _klass; - objArrayOop _ti_base; // i.e., transitive_interfaces - int _ti_index; - int _ti_limit; + ChangeType _change_type; + klassOop _klass; + objArrayOop _ti_base; // i.e., transitive_interfaces + int _ti_index; + int _ti_limit; // start at the beginning: void start() { @@ -530,11 +531,11 @@ _ti_limit = 0; } + public: ContextStream(DepChange& changes) : _changes(changes) { start(); } - public: ContextStream(DepChange& changes, No_Safepoint_Verifier& nsv) : _changes(changes) // the nsv argument makes it safe to hold oops like _klass @@ -542,6 +543,7 @@ bool next(); + ChangeType change_type() { return _change_type; } klassOop klass() { return _klass; } }; friend class DepChange::ContextStream; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -414,9 +414,8 @@ } const char* nmethod::compile_kind() const { - if (method() == NULL) return "unloaded"; - if (is_native_method()) return "c2n"; if (is_osr_method()) return "osr"; + if (method() != NULL && is_native_method()) return "c2n"; return NULL; } @@ -1127,6 +1126,9 @@ } flags.state = unloaded; + // Log the unloading. + log_state_change(); + // The methodOop is gone at this point assert(_method == NULL, "Tautology"); @@ -1137,8 +1139,6 @@ void nmethod::invalidate_osr_method() { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); - if (_entry_bci != InvalidOSREntryBci) - inc_decompile_count(); // Remove from list of active nmethods if (method() != NULL) instanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this); @@ -1146,59 +1146,63 @@ _entry_bci = InvalidOSREntryBci; } -void nmethod::log_state_change(int state) const { +void nmethod::log_state_change() const { if (LogCompilation) { if (xtty != NULL) { ttyLocker ttyl; // keep the following output all in one block - xtty->begin_elem("make_not_entrant %sthread='" UINTX_FORMAT "'", - (state == zombie ? "zombie='1' " : ""), - os::current_thread_id()); + if (flags.state == unloaded) { + xtty->begin_elem("make_unloaded thread='" UINTX_FORMAT "'", + os::current_thread_id()); + } else { + xtty->begin_elem("make_not_entrant thread='" UINTX_FORMAT "'%s", + os::current_thread_id(), + (flags.state == zombie ? " zombie='1'" : "")); + } log_identity(xtty); xtty->stamp(); xtty->end_elem(); } } - if (PrintCompilation) { - print_on(tty, state == zombie ? "made zombie " : "made not entrant "); + if (PrintCompilation && flags.state != unloaded) { + print_on(tty, flags.state == zombie ? "made zombie " : "made not entrant "); tty->cr(); } } // Common functionality for both make_not_entrant and make_zombie -void nmethod::make_not_entrant_or_zombie(int state) { +bool nmethod::make_not_entrant_or_zombie(int state) { assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); - // Code for an on-stack-replacement nmethod is removed when a class gets unloaded. - // They never become zombie/non-entrant, so the nmethod sweeper will never remove - // them. Instead the entry_bci is set to InvalidOSREntryBci, so the osr nmethod - // will never be used anymore. That the nmethods only gets removed when class unloading - // happens, make life much simpler, since the nmethods are not just going to disappear - // out of the blue. - if (is_osr_method()) { - if (osr_entry_bci() != InvalidOSREntryBci) { - // only log this once - log_state_change(state); - } - invalidate_osr_method(); - return; + // If the method is already zombie there is nothing to do + if (is_zombie()) { + return false; } - // If the method is already zombie or set to the state we want, nothing to do - if (is_zombie() || (state == not_entrant && is_not_entrant())) { - return; - } - - log_state_change(state); - // Make sure the nmethod is not flushed in case of a safepoint in code below. nmethodLocker nml(this); { + // invalidate osr nmethod before acquiring the patching lock since + // they both acquire leaf locks and we don't want a deadlock. + // This logic is equivalent to the logic below for patching the + // verified entry point of regular methods. + if (is_osr_method()) { + // this effectively makes the osr nmethod not entrant + invalidate_osr_method(); + } + // Enter critical section. Does not block for safepoint. MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); + + if (flags.state == state) { + // another thread already performed this transition so nothing + // to do, but return false to indicate this. + return false; + } + // The caller can be calling the method statically or through an inline // cache call. - if (!is_not_entrant()) { + if (!is_osr_method() && !is_not_entrant()) { NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), SharedRuntime::get_handle_wrong_method_stub()); assert (NativeJump::instruction_size == nmethod::_zombie_instruction_size, ""); @@ -1217,6 +1221,10 @@ // Change state flags.state = state; + + // Log the transition once + log_state_change(); + } // leave critical region under Patching_lock if (state == not_entrant) { @@ -1240,7 +1248,6 @@ // It's a true state change, so mark the method as decompiled. inc_decompile_count(); - // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event // and it hasn't already been reported for this nmethod then report it now. // (the event may have been reported earilier if the GC marked it for unloading). @@ -1268,7 +1275,7 @@ // Check whether method got unloaded at a safepoint before this, // if so we can skip the flushing steps below - if (method() == NULL) return; + if (method() == NULL) return true; // Remove nmethod from method. // We need to check if both the _code and _from_compiled_code_entry_point @@ -1282,6 +1289,8 @@ HandleMark hm; method()->clear_code(); } + + return true; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/code/nmethod.hpp --- a/hotspot/src/share/vm/code/nmethod.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/code/nmethod.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -252,7 +252,9 @@ void* operator new(size_t size, int nmethod_size); const char* reloc_string_for(u_char* begin, u_char* end); - void make_not_entrant_or_zombie(int state); + // Returns true if this thread changed the state of the nmethod or + // false if another thread performed the transition. + bool make_not_entrant_or_zombie(int state); void inc_decompile_count(); // used to check that writes to nmFlags are done consistently. @@ -375,10 +377,12 @@ bool is_zombie() const { return flags.state == zombie; } bool is_unloaded() const { return flags.state == unloaded; } - // Make the nmethod non entrant. The nmethod will continue to be alive. - // It is used when an uncommon trap happens. - void make_not_entrant() { make_not_entrant_or_zombie(not_entrant); } - void make_zombie() { make_not_entrant_or_zombie(zombie); } + // Make the nmethod non entrant. The nmethod will continue to be + // alive. It is used when an uncommon trap happens. Returns true + // if this thread changed the state of the nmethod or false if + // another thread performed the transition. + bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); } + bool make_zombie() { return make_not_entrant_or_zombie(zombie); } // used by jvmti to track if the unload event has been reported bool unload_reported() { return _unload_reported; } @@ -563,7 +567,7 @@ // Logging void log_identity(xmlStream* log) const; void log_new_nmethod() const; - void log_state_change(int state) const; + void log_state_change() const; // Prints a comment for one native instruction (reloc info, pc desc) void print_code_comment_on(outputStream* st, int column, address begin, address end); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -709,7 +709,8 @@ // Support for parallelizing survivor space rescan if (CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) { - size_t max_plab_samples = MaxNewSize/((SurvivorRatio+2)*MinTLABSize); + size_t max_plab_samples = cp->max_gen0_size()/ + ((SurvivorRatio+2)*MinTLABSize); _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads); _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples); _cursor = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -351,9 +351,16 @@ CollectionSetChooser::printSortedHeapRegions() { gclog_or_tty->print_cr("Printing %d Heap Regions sorted by amount of known garbage", _numMarkedRegions); + + DEBUG_ONLY(int marked_count = 0;) for (int i = 0; i < _markedRegions.length(); i++) { - printHeapRegion(_markedRegions.at(i)); + HeapRegion* r = _markedRegions.at(i); + if (r != NULL) { + printHeapRegion(r); + DEBUG_ONLY(marked_count++;) + } } + assert(marked_count == _numMarkedRegions, "must be"); gclog_or_tty->print_cr("Done sorted heap region print"); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -42,28 +42,49 @@ _n_periods(0), _threads(NULL), _n_threads(0) { - if (G1ConcRefine) { - _n_threads = (int)thread_num(); - if (_n_threads > 0) { - _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads); - int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids(); - ConcurrentG1RefineThread *next = NULL; - for (int i = _n_threads - 1; i >= 0; i--) { - ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i); - assert(t != NULL, "Conc refine should have been created"); - assert(t->cg1r() == this, "Conc refine thread should refer to this"); - _threads[i] = t; - next = t; - } - } + + // Ergomonically select initial concurrent refinement parameters + if (FLAG_IS_DEFAULT(G1ConcRefineGreenZone)) { + FLAG_SET_DEFAULT(G1ConcRefineGreenZone, MAX2(ParallelGCThreads, 1)); + } + set_green_zone(G1ConcRefineGreenZone); + + if (FLAG_IS_DEFAULT(G1ConcRefineYellowZone)) { + FLAG_SET_DEFAULT(G1ConcRefineYellowZone, green_zone() * 3); + } + set_yellow_zone(MAX2(G1ConcRefineYellowZone, green_zone())); + + if (FLAG_IS_DEFAULT(G1ConcRefineRedZone)) { + FLAG_SET_DEFAULT(G1ConcRefineRedZone, yellow_zone() * 2); + } + set_red_zone(MAX2(G1ConcRefineRedZone, yellow_zone())); + _n_worker_threads = thread_num(); + // We need one extra thread to do the young gen rset size sampling. + _n_threads = _n_worker_threads + 1; + reset_threshold_step(); + + _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads); + int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids(); + ConcurrentG1RefineThread *next = NULL; + for (int i = _n_threads - 1; i >= 0; i--) { + ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i); + assert(t != NULL, "Conc refine should have been created"); + assert(t->cg1r() == this, "Conc refine thread should refer to this"); + _threads[i] = t; + next = t; } } -size_t ConcurrentG1Refine::thread_num() { - if (G1ConcRefine) { - return (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads; +void ConcurrentG1Refine::reset_threshold_step() { + if (FLAG_IS_DEFAULT(G1ConcRefineThresholdStep)) { + _thread_threshold_step = (yellow_zone() - green_zone()) / (worker_thread_num() + 1); + } else { + _thread_threshold_step = G1ConcRefineThresholdStep; } - return 0; +} + +int ConcurrentG1Refine::thread_num() { + return MAX2((G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads, 1); } void ConcurrentG1Refine::init() { @@ -123,6 +144,15 @@ } } +void ConcurrentG1Refine::reinitialize_threads() { + reset_threshold_step(); + if (_threads != NULL) { + for (int i = 0; i < _n_threads; i++) { + _threads[i]->initialize(); + } + } +} + ConcurrentG1Refine::~ConcurrentG1Refine() { if (G1ConcRSLogCacheSize > 0) { assert(_card_counts != NULL, "Logic"); @@ -384,4 +414,3 @@ st->cr(); } } - diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -29,6 +29,31 @@ class ConcurrentG1Refine: public CHeapObj { ConcurrentG1RefineThread** _threads; int _n_threads; + int _n_worker_threads; + /* + * The value of the update buffer queue length falls into one of 3 zones: + * green, yellow, red. If the value is in [0, green) nothing is + * done, the buffers are left unprocessed to enable the caching effect of the + * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement + * threads are gradually activated. In [yellow, red) all threads are + * running. If the length becomes red (max queue length) the mutators start + * processing the buffers. + * + * There are some interesting cases (with G1AdaptiveConcRefine turned off): + * 1) green = yellow = red = 0. In this case the mutator will process all + * buffers. Except for those that are created by the deferred updates + * machinery during a collection. + * 2) green = 0. Means no caching. Can be a good way to minimize the + * amount of time spent updating rsets during a collection. + */ + int _green_zone; + int _yellow_zone; + int _red_zone; + + int _thread_threshold_step; + + // Reset the threshold step value based of the current zone boundaries. + void reset_threshold_step(); // The cache for card refinement. bool _use_cache; @@ -147,6 +172,8 @@ void init(); // Accomplish some initialization that has to wait. void stop(); + void reinitialize_threads(); + // Iterate over the conc refine threads void threads_do(ThreadClosure *tc); @@ -178,7 +205,20 @@ void clear_and_record_card_counts(); - static size_t thread_num(); + static int thread_num(); void print_worker_threads_on(outputStream* st) const; + + void set_green_zone(int x) { _green_zone = x; } + void set_yellow_zone(int x) { _yellow_zone = x; } + void set_red_zone(int x) { _red_zone = x; } + + int green_zone() const { return _green_zone; } + int yellow_zone() const { return _yellow_zone; } + int red_zone() const { return _red_zone; } + + int total_thread_num() const { return _n_threads; } + int worker_thread_num() const { return _n_worker_threads; } + + int thread_threshold_step() const { return _thread_threshold_step; } }; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -25,10 +25,6 @@ #include "incls/_precompiled.incl" #include "incls/_concurrentG1RefineThread.cpp.incl" -// ======= Concurrent Mark Thread ======== - -// The CM thread is created when the G1 garbage collector is used - ConcurrentG1RefineThread:: ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, int worker_id_offset, int worker_id) : @@ -37,19 +33,42 @@ _worker_id(worker_id), _active(false), _next(next), + _monitor(NULL), _cg1r(cg1r), - _vtime_accum(0.0), - _interval_ms(5.0) + _vtime_accum(0.0) { + + // Each thread has its own monitor. The i-th thread is responsible for signalling + // to thread i+1 if the number of buffers in the queue exceeds a threashold for this + // thread. Monitors are also used to wake up the threads during termination. + // The 0th worker in notified by mutator threads and has a special monitor. + // The last worker is used for young gen rset size sampling. + if (worker_id > 0) { + _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true); + } else { + _monitor = DirtyCardQ_CBL_mon; + } + initialize(); create_and_start(); } +void ConcurrentG1RefineThread::initialize() { + if (_worker_id < cg1r()->worker_thread_num()) { + // Current thread activation threshold + _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), + cg1r()->yellow_zone()); + // A thread deactivates once the number of buffer reached a deactivation threshold + _deactivation_threshold = MAX2(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone()); + } else { + set_active(true); + } +} + void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1p = g1h->g1_policy(); if (g1p->adaptive_young_list_length()) { int regions_visited = 0; - g1h->young_list_rs_length_sampling_init(); while (g1h->young_list_rs_length_sampling_more()) { g1h->young_list_rs_length_sampling_next(); @@ -70,99 +89,121 @@ } } -void ConcurrentG1RefineThread::run() { - initialize_in_thread(); +void ConcurrentG1RefineThread::run_young_rs_sampling() { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); _vtime_start = os::elapsedVTime(); - wait_for_universe_init(); + while(!_should_terminate) { + _sts.join(); + sample_young_list_rs_lengths(); + _sts.leave(); - while (!_should_terminate) { - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); - // Wait for completed log buffers to exist. - { - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); - while (((_worker_id == 0 && !dcqs.process_completed_buffers()) || - (_worker_id > 0 && !is_active())) && - !_should_terminate) { - DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag); - } - } - - if (_should_terminate) { - return; + if (os::supports_vtime()) { + _vtime_accum = (os::elapsedVTime() - _vtime_start); + } else { + _vtime_accum = 0.0; } - // Now we take them off (this doesn't hold locks while it applies - // closures.) (If we did a full collection, then we'll do a full - // traversal. - _sts.join(); - int n_logs = 0; - int lower_limit = 0; - double start_vtime_sec; // only used when G1SmoothConcRefine is on - int prev_buffer_num; // only used when G1SmoothConcRefine is on - // This thread activation threshold - int threshold = G1UpdateBufferQueueProcessingThreshold * _worker_id; - // Next thread activation threshold - int next_threshold = threshold + G1UpdateBufferQueueProcessingThreshold; - int deactivation_threshold = MAX2(threshold - G1UpdateBufferQueueProcessingThreshold / 2, 0); + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + if (_should_terminate) { + break; + } + _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefineServiceInterval); + } +} - if (G1SmoothConcRefine) { - lower_limit = 0; - start_vtime_sec = os::elapsedVTime(); - prev_buffer_num = (int) dcqs.completed_buffers_num(); - } else { - lower_limit = G1UpdateBufferQueueProcessingThreshold / 4; // For now. +void ConcurrentG1RefineThread::wait_for_completed_buffers() { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + while (!_should_terminate && !is_active()) { + _monitor->wait(Mutex::_no_safepoint_check_flag); + } +} + +bool ConcurrentG1RefineThread::is_active() { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + return _worker_id > 0 ? _active : dcqs.process_completed_buffers(); +} + +void ConcurrentG1RefineThread::activate() { + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + if (_worker_id > 0) { + if (G1TraceConcurrentRefinement) { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d", + _worker_id, _threshold, (int)dcqs.completed_buffers_num()); } - while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, lower_limit)) { - double end_vtime_sec; - double elapsed_vtime_sec; - int elapsed_vtime_ms; - int curr_buffer_num = (int) dcqs.completed_buffers_num(); + set_active(true); + } else { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + dcqs.set_process_completed(true); + } + _monitor->notify(); +} - if (G1SmoothConcRefine) { - end_vtime_sec = os::elapsedVTime(); - elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; - elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0); +void ConcurrentG1RefineThread::deactivate() { + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + if (_worker_id > 0) { + if (G1TraceConcurrentRefinement) { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d", + _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num()); + } + set_active(false); + } else { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + dcqs.set_process_completed(false); + } +} + +void ConcurrentG1RefineThread::run() { + initialize_in_thread(); + wait_for_universe_init(); - if (curr_buffer_num > prev_buffer_num || - curr_buffer_num > next_threshold) { - decreaseInterval(elapsed_vtime_ms); - } else if (curr_buffer_num < prev_buffer_num) { - increaseInterval(elapsed_vtime_ms); - } + if (_worker_id >= cg1r()->worker_thread_num()) { + run_young_rs_sampling(); + terminate(); + } + + _vtime_start = os::elapsedVTime(); + while (!_should_terminate) { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + + // Wait for work + wait_for_completed_buffers(); + + if (_should_terminate) { + break; + } + + _sts.join(); + + do { + int curr_buffer_num = (int)dcqs.completed_buffers_num(); + // If the number of the buffers falls down into the yellow zone, + // that means that the transition period after the evacuation pause has ended. + if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { + dcqs.set_completed_queue_padding(0); } - if (_worker_id == 0) { - sample_young_list_rs_lengths(); - } else if (curr_buffer_num < deactivation_threshold) { + + if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { // If the number of the buffer has fallen below our threshold // we should deactivate. The predecessor will reactivate this // thread should the number of the buffers cross the threshold again. - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); deactivate(); - if (G1TraceConcurrentRefinement) { - gclog_or_tty->print_cr("G1-Refine-deactivated worker %d", _worker_id); - } break; } // Check if we need to activate the next thread. - if (curr_buffer_num > next_threshold && _next != NULL && !_next->is_active()) { - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); + if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { _next->activate(); - DirtyCardQ_CBL_mon->notify_all(); - if (G1TraceConcurrentRefinement) { - gclog_or_tty->print_cr("G1-Refine-activated worker %d", _next->_worker_id); - } } + } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone())); - if (G1SmoothConcRefine) { - prev_buffer_num = curr_buffer_num; - _sts.leave(); - os::sleep(Thread::current(), (jlong) _interval_ms, false); - _sts.join(); - start_vtime_sec = os::elapsedVTime(); - } - n_logs++; + // We can exit the loop above while being active if there was a yield request. + if (is_active()) { + deactivate(); } + _sts.leave(); if (os::supports_vtime()) { @@ -172,7 +213,6 @@ } } assert(_should_terminate, "just checking"); - terminate(); } @@ -191,8 +231,8 @@ } { - MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag); - DirtyCardQ_CBL_mon->notify_all(); + MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + _monitor->notify(); } { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -40,42 +40,36 @@ // when the number of the rset update buffer crosses a certain threshold. A successor // would self-deactivate when the number of the buffers falls below the threshold. bool _active; - ConcurrentG1RefineThread * _next; - public: - virtual void run(); - - bool is_active() { return _active; } - void activate() { _active = true; } - void deactivate() { _active = false; } - - private: - ConcurrentG1Refine* _cg1r; - - double _interval_ms; + ConcurrentG1RefineThread* _next; + Monitor* _monitor; + ConcurrentG1Refine* _cg1r; - void decreaseInterval(int processing_time_ms) { - double min_interval_ms = (double) processing_time_ms; - _interval_ms = 0.8 * _interval_ms; - if (_interval_ms < min_interval_ms) - _interval_ms = min_interval_ms; - } - void increaseInterval(int processing_time_ms) { - double max_interval_ms = 9.0 * (double) processing_time_ms; - _interval_ms = 1.1 * _interval_ms; - if (max_interval_ms > 0 && _interval_ms > max_interval_ms) - _interval_ms = max_interval_ms; - } + int _thread_threshold_step; + // This thread activation threshold + int _threshold; + // This thread deactivation threshold + int _deactivation_threshold; - void sleepBeforeNextCycle(); + void sample_young_list_rs_lengths(); + void run_young_rs_sampling(); + void wait_for_completed_buffers(); + + void set_active(bool x) { _active = x; } + bool is_active(); + void activate(); + void deactivate(); // For use by G1CollectedHeap, which is a friend. static SuspendibleThreadSet* sts() { return &_sts; } - public: +public: + virtual void run(); // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, int worker_id_offset, int worker_id); + void initialize(); + // Printing void print() const; void print_on(outputStream* st) const; @@ -83,13 +77,10 @@ // Total virtual time so far. double vtime_accum() { return _vtime_accum; } - ConcurrentG1Refine* cg1r() { return _cg1r; } - - void sample_young_list_rs_lengths(); + ConcurrentG1Refine* cg1r() { return _cg1r; } // Yield for GC - void yield(); - + void yield(); // shutdown void stop(); }; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -760,7 +760,6 @@ rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); - satb_mq_set.set_process_completed_threshold(G1SATBProcessCompletedThreshold); satb_mq_set.set_active_all_threads(true); // update_g1_committed() will be called at the end of an evac pause diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -61,8 +61,8 @@ #pragma warning( disable:4355 ) // 'this' : used in base member initializer list #endif // _MSC_VER -DirtyCardQueueSet::DirtyCardQueueSet() : - PtrQueueSet(true /*notify_when_complete*/), +DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : + PtrQueueSet(notify_when_complete), _closure(NULL), _shared_dirty_card_queue(this, true /*perm*/), _free_ids(NULL), @@ -77,12 +77,12 @@ } void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, + int process_completed_threshold, int max_completed_queue, Mutex* lock, PtrQueueSet* fl_owner) { - PtrQueueSet::initialize(cbl_mon, fl_lock, max_completed_queue, fl_owner); + PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, + max_completed_queue, fl_owner); set_buffer_size(G1UpdateBufferSize); - set_process_completed_threshold(G1UpdateBufferQueueProcessingThreshold); - _shared_dirty_card_queue.set_lock(lock); _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon); } @@ -154,9 +154,10 @@ return b; } -DirtyCardQueueSet::CompletedBufferNode* -DirtyCardQueueSet::get_completed_buffer_lock(int stop_at) { - CompletedBufferNode* nd = NULL; + +BufferNode* +DirtyCardQueueSet::get_completed_buffer(int stop_at) { + BufferNode* nd = NULL; MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); if ((int)_n_completed_buffers <= stop_at) { @@ -166,53 +167,31 @@ if (_completed_buffers_head != NULL) { nd = _completed_buffers_head; - _completed_buffers_head = nd->next; + _completed_buffers_head = nd->next(); if (_completed_buffers_head == NULL) _completed_buffers_tail = NULL; _n_completed_buffers--; + assert(_n_completed_buffers >= 0, "Invariant"); } debug_only(assert_completed_buffer_list_len_correct_locked()); return nd; } -// We only do this in contexts where there is no concurrent enqueueing. -DirtyCardQueueSet::CompletedBufferNode* -DirtyCardQueueSet::get_completed_buffer_CAS() { - CompletedBufferNode* nd = _completed_buffers_head; - - while (nd != NULL) { - CompletedBufferNode* next = nd->next; - CompletedBufferNode* result = - (CompletedBufferNode*)Atomic::cmpxchg_ptr(next, - &_completed_buffers_head, - nd); - if (result == nd) { - return result; - } else { - nd = _completed_buffers_head; - } - } - assert(_completed_buffers_head == NULL, "Loop post"); - _completed_buffers_tail = NULL; - return NULL; -} - bool DirtyCardQueueSet:: apply_closure_to_completed_buffer_helper(int worker_i, - CompletedBufferNode* nd) { + BufferNode* nd) { if (nd != NULL) { + void **buf = BufferNode::make_buffer_from_node(nd); + size_t index = nd->index(); bool b = - DirtyCardQueue::apply_closure_to_buffer(_closure, nd->buf, - nd->index, _sz, + DirtyCardQueue::apply_closure_to_buffer(_closure, buf, + index, _sz, true, worker_i); - void** buf = nd->buf; - size_t index = nd->index; - delete nd; if (b) { deallocate_buffer(buf); return true; // In normal case, go on to next buffer. } else { - enqueue_complete_buffer(buf, index, true); + enqueue_complete_buffer(buf, index); return false; } } else { @@ -222,40 +201,36 @@ bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, int stop_at, - bool with_CAS) + bool during_pause) { - CompletedBufferNode* nd = NULL; - if (with_CAS) { - guarantee(stop_at == 0, "Precondition"); - nd = get_completed_buffer_CAS(); - } else { - nd = get_completed_buffer_lock(stop_at); - } + assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); + BufferNode* nd = get_completed_buffer(stop_at); bool res = apply_closure_to_completed_buffer_helper(worker_i, nd); if (res) Atomic::inc(&_processed_buffers_rs_thread); return res; } void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() { - CompletedBufferNode* nd = _completed_buffers_head; + BufferNode* nd = _completed_buffers_head; while (nd != NULL) { bool b = - DirtyCardQueue::apply_closure_to_buffer(_closure, nd->buf, 0, _sz, - false); + DirtyCardQueue::apply_closure_to_buffer(_closure, + BufferNode::make_buffer_from_node(nd), + 0, _sz, false); guarantee(b, "Should not stop early."); - nd = nd->next; + nd = nd->next(); } } void DirtyCardQueueSet::abandon_logs() { assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); - CompletedBufferNode* buffers_to_delete = NULL; + BufferNode* buffers_to_delete = NULL; { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); while (_completed_buffers_head != NULL) { - CompletedBufferNode* nd = _completed_buffers_head; - _completed_buffers_head = nd->next; - nd->next = buffers_to_delete; + BufferNode* nd = _completed_buffers_head; + _completed_buffers_head = nd->next(); + nd->set_next(buffers_to_delete); buffers_to_delete = nd; } _n_completed_buffers = 0; @@ -263,10 +238,9 @@ debug_only(assert_completed_buffer_list_len_correct_locked()); } while (buffers_to_delete != NULL) { - CompletedBufferNode* nd = buffers_to_delete; - buffers_to_delete = nd->next; - deallocate_buffer(nd->buf); - delete nd; + BufferNode* nd = buffers_to_delete; + buffers_to_delete = nd->next(); + deallocate_buffer(BufferNode::make_buffer_from_node(nd)); } // Since abandon is done only at safepoints, we can safely manipulate // these queues. diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,11 +84,12 @@ jint _processed_buffers_rs_thread; public: - DirtyCardQueueSet(); + DirtyCardQueueSet(bool notify_when_complete = true); void initialize(Monitor* cbl_mon, Mutex* fl_lock, - int max_completed_queue = 0, - Mutex* lock = NULL, PtrQueueSet* fl_owner = NULL); + int process_completed_threshold, + int max_completed_queue, + Mutex* lock, PtrQueueSet* fl_owner = NULL); // The number of parallel ids that can be claimed to allow collector or // mutator threads to do card-processing work. @@ -120,12 +121,13 @@ // is returned to the completed buffer set, and this call returns false. bool apply_closure_to_completed_buffer(int worker_i = 0, int stop_at = 0, - bool with_CAS = false); + bool during_pause = false); + bool apply_closure_to_completed_buffer_helper(int worker_i, - CompletedBufferNode* nd); + BufferNode* nd); - CompletedBufferNode* get_completed_buffer_CAS(); - CompletedBufferNode* get_completed_buffer_lock(int stop_at); + BufferNode* get_completed_buffer(int stop_at); + // Applies the current closure to all completed buffers, // non-consumptively. void apply_closure_to_all_completed_buffers(); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -928,6 +928,8 @@ TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); TraceTime t(full ? "Full GC (System.gc())" : "Full GC", PrintGC, true, gclog_or_tty); + TraceMemoryManagerStats tms(true /* fullGC */); + double start = os::elapsedTime(); g1_policy()->record_full_collection_start(); @@ -1001,6 +1003,8 @@ COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); + MemoryService::track_memory_usage(); + if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { HandleMark hm; // Discard invalid handles created during verification gclog_or_tty->print(" VerifyAfterGC:"); @@ -1371,6 +1375,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : SharedHeap(policy_), _g1_policy(policy_), + _dirty_card_queue_set(false), _ref_processor(NULL), _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), _bot_shared(NULL), @@ -1456,8 +1461,6 @@ Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap"); Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap"); - // We allocate this in any case, but only do no work if the command line - // param is off. _cg1r = new ConcurrentG1Refine(); // Reserve the maximum. @@ -1590,18 +1593,20 @@ JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, SATB_Q_FL_lock, - 0, + G1SATBProcessCompletedThreshold, Shared_SATB_Q_lock); JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, - G1UpdateBufferQueueMaxLength, + concurrent_g1_refine()->yellow_zone(), + concurrent_g1_refine()->red_zone(), Shared_DirtyCardQ_lock); if (G1DeferredRSUpdate) { dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, - 0, + -1, // never trigger processing + -1, // no limit on length Shared_DirtyCardQ_lock, &JavaThread::dirty_card_queue_set()); } @@ -1732,13 +1737,6 @@ return car->free(); } -void G1CollectedHeap::collect(GCCause::Cause cause) { - // The caller doesn't have the Heap_lock - assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); - MutexLocker ml(Heap_lock); - collect_locked(cause); -} - void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) { assert(Thread::current()->is_VM_thread(), "Precondition#1"); assert(Heap_lock->is_locked(), "Precondition#2"); @@ -1755,17 +1753,31 @@ } } - -void G1CollectedHeap::collect_locked(GCCause::Cause cause) { - // Don't want to do a GC until cleanup is completed. - wait_for_cleanup_complete(); - - // Read the GC count while holding the Heap_lock - int gc_count_before = SharedHeap::heap()->total_collections(); +void G1CollectedHeap::collect(GCCause::Cause cause) { + // The caller doesn't have the Heap_lock + assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); + + int gc_count_before; { - MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back - VM_G1CollectFull op(gc_count_before, cause); - VMThread::execute(&op); + MutexLocker ml(Heap_lock); + // Read the GC count while holding the Heap_lock + gc_count_before = SharedHeap::heap()->total_collections(); + + // Don't want to do a GC until cleanup is completed. + wait_for_cleanup_complete(); + } // We give up heap lock; VMThread::execute gets it back below + switch (cause) { + case GCCause::_scavenge_alot: { + // Do an incremental pause, which might sometimes be abandoned. + VM_G1IncCollectionPause op(gc_count_before, cause); + VMThread::execute(&op); + break; + } + default: { + // In all other cases, we currently do a full gc. + VM_G1CollectFull op(gc_count_before, cause); + VMThread::execute(&op); + } } } @@ -2119,7 +2131,7 @@ } size_t G1CollectedHeap::max_capacity() const { - return _g1_committed.byte_size(); + return g1_reserved_obj_bytes(); } jlong G1CollectedHeap::millis_since_last_gc() { @@ -2638,6 +2650,8 @@ } { + ResourceMark rm; + char verbose_str[128]; sprintf(verbose_str, "GC pause "); if (g1_policy()->in_young_gc_mode()) { @@ -2649,8 +2663,6 @@ if (g1_policy()->should_initiate_conc_mark()) strcat(verbose_str, " (initial-mark)"); - GCCauseSetter x(this, GCCause::_g1_inc_collection_pause); - // if PrintGCDetails is on, we'll print long statistics information // in the collector policy code, so let's not print this as the output // is messy if we do. @@ -2658,7 +2670,8 @@ TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty); - ResourceMark rm; + TraceMemoryManagerStats tms(false /* fullGC */); + assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); guarantee(!is_gc_active(), "collection is not reentrant"); @@ -2802,6 +2815,22 @@ _young_list->reset_auxilary_lists(); } } else { + if (_in_cset_fast_test != NULL) { + assert(_in_cset_fast_test_base != NULL, "Since _in_cset_fast_test isn't"); + FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); + // this is more for peace of mind; we're nulling them here and + // we're expecting them to be null at the beginning of the next GC + _in_cset_fast_test = NULL; + _in_cset_fast_test_base = NULL; + } + // This looks confusing, because the DPT should really be empty + // at this point -- since we have not done any collection work, + // there should not be any derived pointers in the table to update; + // however, there is some additional state in the DPT which is + // reset at the end of the (null) "gc" here via the following call. + // A better approach might be to split off that state resetting work + // into a separate method that asserts that the DPT is empty and call + // that here. That is deferred for now. COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); } @@ -2838,6 +2867,8 @@ assert(regions_accounted_for(), "Region leakage."); + MemoryService::track_memory_usage(); + if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { HandleMark hm; // Discard invalid handles created during verification gclog_or_tty->print(" VerifyAfterGC:"); @@ -4209,10 +4240,11 @@ RedirtyLoggedCardTableEntryFastClosure redirty; dirty_card_queue_set().set_closure(&redirty); dirty_card_queue_set().apply_closure_to_all_completed_buffers(); - JavaThread::dirty_card_queue_set().merge_bufferlists(&dirty_card_queue_set()); + + DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); + dcq.merge_bufferlists(&dirty_card_queue_set()); assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); } - COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -692,7 +692,7 @@ // Reserved (g1 only; super method includes perm), capacity and the used // portion in bytes. - size_t g1_reserved_obj_bytes() { return _g1_reserved.byte_size(); } + size_t g1_reserved_obj_bytes() const { return _g1_reserved.byte_size(); } virtual size_t capacity() const; virtual size_t used() const; // This should be called when we're not holding the heap lock. The diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1516,8 +1516,30 @@ (end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0; update_recent_gc_times(end_time_sec, elapsed_ms); _recent_avg_pause_time_ratio = _recent_gc_times_ms->sum()/interval_ms; - // using 1.01 to account for floating point inaccuracies - assert(recent_avg_pause_time_ratio() < 1.01, "All GC?"); + if (recent_avg_pause_time_ratio() < 0.0 || + (recent_avg_pause_time_ratio() - 1.0 > 0.0)) { +#ifndef PRODUCT + // Dump info to allow post-facto debugging + gclog_or_tty->print_cr("recent_avg_pause_time_ratio() out of bounds"); + gclog_or_tty->print_cr("-------------------------------------------"); + gclog_or_tty->print_cr("Recent GC Times (ms):"); + _recent_gc_times_ms->dump(); + gclog_or_tty->print_cr("(End Time=%3.3f) Recent GC End Times (s):", end_time_sec); + _recent_prev_end_times_for_all_gcs_sec->dump(); + gclog_or_tty->print_cr("GC = %3.3f, Interval = %3.3f, Ratio = %3.3f", + _recent_gc_times_ms->sum(), interval_ms, recent_avg_pause_time_ratio()); + // In debug mode, terminate the JVM if the user wants to debug at this point. + assert(!G1FailOnFPError, "Debugging data for CR 6898948 has been dumped above"); +#endif // !PRODUCT + // Clip ratio between 0.0 and 1.0, and continue. This will be fixed in + // CR 6902692 by redoing the manner in which the ratio is incrementally computed. + if (_recent_avg_pause_time_ratio < 0.0) { + _recent_avg_pause_time_ratio = 0.0; + } else { + assert(_recent_avg_pause_time_ratio - 1.0 > 0.0, "Ctl-point invariant"); + _recent_avg_pause_time_ratio = 1.0; + } + } } if (G1PolicyVerbose > 1) { @@ -1892,6 +1914,10 @@ calculate_young_list_min_length(); calculate_young_list_target_config(); + // Note that _mmu_tracker->max_gc_time() returns the time in seconds. + double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSUpdatePauseFractionPercent / 100.0; + adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms); + // _target_pause_time_ms = -1.0; @@ -1899,6 +1925,47 @@ // +void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, + double update_rs_processed_buffers, + double goal_ms) { + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + ConcurrentG1Refine *cg1r = G1CollectedHeap::heap()->concurrent_g1_refine(); + + if (G1AdaptiveConcRefine) { + const int k_gy = 3, k_gr = 6; + const double inc_k = 1.1, dec_k = 0.9; + + int g = cg1r->green_zone(); + if (update_rs_time > goal_ms) { + g = (int)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. + } else { + if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { + g = (int)MAX2(g * inc_k, g + 1.0); + } + } + // Change the refinement threads params + cg1r->set_green_zone(g); + cg1r->set_yellow_zone(g * k_gy); + cg1r->set_red_zone(g * k_gr); + cg1r->reinitialize_threads(); + + int processing_threshold_delta = MAX2((int)(cg1r->green_zone() * sigma()), 1); + int processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta, + cg1r->yellow_zone()); + // Change the barrier params + dcqs.set_process_completed_threshold(processing_threshold); + dcqs.set_max_completed_queue(cg1r->red_zone()); + } + + int curr_queue_size = dcqs.completed_buffers_num(); + if (curr_queue_size >= cg1r->yellow_zone()) { + dcqs.set_completed_queue_padding(curr_queue_size); + } else { + dcqs.set_completed_queue_padding(0); + } + dcqs.notify_if_necessary(); +} + double G1CollectorPolicy:: predict_young_collection_elapsed_time_ms(size_t adjustment) { @@ -2825,8 +2892,15 @@ double non_young_start_time_sec; start_recording_regions(); - guarantee(_target_pause_time_ms > -1.0, + guarantee(_target_pause_time_ms > -1.0 + NOT_PRODUCT(|| Universe::heap()->gc_cause() == GCCause::_scavenge_alot), "_target_pause_time_ms should have been set!"); +#ifndef PRODUCT + if (_target_pause_time_ms <= -1.0) { + assert(ScavengeALot && Universe::heap()->gc_cause() == GCCause::_scavenge_alot, "Error"); + _target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; + } +#endif assert(_collection_set == NULL, "Precondition"); double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); @@ -2972,7 +3046,3 @@ G1CollectorPolicy::record_collection_pause_end(abandoned); assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end."); } - -// Local Variables: *** -// c-indentation-style: gnu *** -// End: *** diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -316,6 +316,10 @@ bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group); #endif // PRODUCT + void adjust_concurrent_refinement(double update_rs_time, + double update_rs_processed_buffers, + double goal_ms); + protected: double _pause_time_target_ms; double _recorded_young_cset_choice_time_ms; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -86,12 +86,22 @@ // increase the array size (:-) // remove the oldest entry (this might allow more GC time for // the time slice than what's allowed) - // concolidate the two entries with the minimum gap between them - // (this mighte allow less GC time than what's allowed) - guarantee(0, "array full, currently we can't recover"); + // consolidate the two entries with the minimum gap between them + // (this might allow less GC time than what's allowed) + guarantee(NOT_PRODUCT(ScavengeALot ||) G1ForgetfulMMUTracker, + "array full, currently we can't recover unless +G1ForgetfulMMUTracker"); + // In the case where ScavengeALot is true, such overflow is not + // uncommon; in such cases, we can, without much loss of precision + // or performance (we are GC'ing most of the time anyway!), + // simply overwrite the oldest entry in the tracker: this + // is also the behaviour when G1ForgetfulMMUTracker is enabled. + _head_index = trim_index(_head_index + 1); + assert(_head_index == _tail_index, "Because we have a full circular buffer"); + _tail_index = trim_index(_tail_index + 1); + } else { + _head_index = trim_index(_head_index + 1); + ++_no_entries; } - _head_index = trim_index(_head_index + 1); - ++_no_entries; _array[_head_index] = G1MMUTrackerQueueElem(start, end); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -99,7 +99,10 @@ // The array is of fixed size and I don't think we'll need more than // two or three entries with the current behaviour of G1 pauses. // If the array is full, an easy fix is to look for the pauses with - // the shortest gap between them and concolidate them. + // the shortest gap between them and consolidate them. + // For now, we have taken the expedient alternative of forgetting + // the oldest entry in the event that +G1ForgetfulMMUTracker, thus + // potentially violating MMU specs for some time thereafter. G1MMUTrackerQueueElem _array[QueueLength]; int _head_index; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -85,7 +85,7 @@ diagnostic(bool, G1SummarizeZFStats, false, \ "Summarize zero-filling info") \ \ - develop(bool, G1TraceConcurrentRefinement, false, \ + diagnostic(bool, G1TraceConcurrentRefinement, false, \ "Trace G1 concurrent refinement") \ \ product(intx, G1MarkStackSize, 2 * 1024 * 1024, \ @@ -94,19 +94,6 @@ product(intx, G1MarkRegionStackSize, 1024 * 1024, \ "Size of the region stack for concurrent marking.") \ \ - develop(bool, G1ConcRefine, true, \ - "If true, run concurrent rem set refinement for G1") \ - \ - develop(intx, G1ConcRefineTargTraversals, 4, \ - "Number of concurrent refinement we try to achieve") \ - \ - develop(intx, G1ConcRefineInitialDelta, 4, \ - "Number of heap regions of alloc ahead of starting collection " \ - "pause to start concurrent refinement (initially)") \ - \ - develop(bool, G1SmoothConcRefine, true, \ - "Attempts to smooth out the overhead of concurrent refinement") \ - \ develop(bool, G1ConcZeroFill, true, \ "If true, run concurrent zero-filling thread") \ \ @@ -178,13 +165,38 @@ product(intx, G1UpdateBufferSize, 256, \ "Size of an update buffer") \ \ - product(intx, G1UpdateBufferQueueProcessingThreshold, 5, \ + product(intx, G1ConcRefineYellowZone, 0, \ "Number of enqueued update buffers that will " \ - "trigger concurrent processing") \ + "trigger concurrent processing. Will be selected ergonomically " \ + "by default.") \ + \ + product(intx, G1ConcRefineRedZone, 0, \ + "Maximum number of enqueued update buffers before mutator " \ + "threads start processing new ones instead of enqueueing them. " \ + "Will be selected ergonomically by default. Zero will disable " \ + "concurrent processing.") \ + \ + product(intx, G1ConcRefineGreenZone, 0, \ + "The number of update buffers that are left in the queue by the " \ + "concurrent processing threads. Will be selected ergonomically " \ + "by default.") \ \ - product(intx, G1UpdateBufferQueueMaxLength, 30, \ - "Maximum number of enqueued update buffers before mutator " \ - "threads start processing new ones instead of enqueueing them") \ + product(intx, G1ConcRefineServiceInterval, 300, \ + "The last concurrent refinement thread wakes up every " \ + "specified number of milliseconds to do miscellaneous work.") \ + \ + product(intx, G1ConcRefineThresholdStep, 0, \ + "Each time the rset update queue increases by this amount " \ + "activate the next refinement thread if available. " \ + "Will be selected ergonomically by default.") \ + \ + product(intx, G1RSUpdatePauseFractionPercent, 10, \ + "A target percentage of time that is allowed to be spend on " \ + "process RS update buffers during the collection pause.") \ + \ + product(bool, G1AdaptiveConcRefine, true, \ + "Select green, yellow and red zones adaptively to meet the " \ + "the pause requirements.") \ \ develop(intx, G1ConcRSLogCacheSize, 10, \ "Log base 2 of the length of conc RS hot-card cache.") \ @@ -242,6 +254,10 @@ product(bool, G1UseSurvivorSpaces, true, \ "When true, use survivor space.") \ \ + develop(bool, G1FailOnFPError, false, \ + "When set, G1 will fail when it encounters an FP 'error', " \ + "so as to allow debugging") \ + \ develop(bool, G1FixedTenuringThreshold, false, \ "When set, G1 will not adjust the tenuring threshold") \ \ @@ -252,6 +268,9 @@ "If non-0 is the size of the G1 survivor space, " \ "otherwise SurvivorRatio is used to determine the size") \ \ + product(bool, G1ForgetfulMMUTracker, false, \ + "If the MMU tracker's memory is full, forget the oldest entry") \ + \ product(uintx, G1HeapRegionSize, 0, \ "Size of the G1 regions.") \ \ diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -64,8 +64,8 @@ while (_index == 0) { handle_zero_index(); } + assert(_index > 0, "postcondition"); - _index -= oopSize; _buf[byte_index_to_index((int)_index)] = ptr; assert(0 <= _index && _index <= _sz, "Invariant."); @@ -99,94 +99,110 @@ assert(_sz > 0, "Didn't set a buffer size."); MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); if (_fl_owner->_buf_free_list != NULL) { - void** res = _fl_owner->_buf_free_list; - _fl_owner->_buf_free_list = (void**)_fl_owner->_buf_free_list[0]; + void** res = BufferNode::make_buffer_from_node(_fl_owner->_buf_free_list); + _fl_owner->_buf_free_list = _fl_owner->_buf_free_list->next(); _fl_owner->_buf_free_list_sz--; - // Just override the next pointer with NULL, just in case we scan this part - // of the buffer. - res[0] = NULL; return res; } else { - return NEW_C_HEAP_ARRAY(void*, _sz); + // Allocate space for the BufferNode in front of the buffer. + char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size()); + return BufferNode::make_buffer_from_block(b); } } void PtrQueueSet::deallocate_buffer(void** buf) { assert(_sz > 0, "Didn't set a buffer size."); MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); - buf[0] = (void*)_fl_owner->_buf_free_list; - _fl_owner->_buf_free_list = buf; + BufferNode *node = BufferNode::make_node_from_buffer(buf); + node->set_next(_fl_owner->_buf_free_list); + _fl_owner->_buf_free_list = node; _fl_owner->_buf_free_list_sz++; } void PtrQueueSet::reduce_free_list() { + assert(_fl_owner == this, "Free list reduction is allowed only for the owner"); // For now we'll adopt the strategy of deleting half. MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag); size_t n = _buf_free_list_sz / 2; while (n > 0) { assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong."); - void** head = _buf_free_list; - _buf_free_list = (void**)_buf_free_list[0]; - FREE_C_HEAP_ARRAY(void*,head); + void* b = BufferNode::make_block_from_node(_buf_free_list); + _buf_free_list = _buf_free_list->next(); + FREE_C_HEAP_ARRAY(char, b); + _buf_free_list_sz --; n--; } } -void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index, bool ignore_max_completed) { - // I use explicit locking here because there's a bailout in the middle. - _cbl_mon->lock_without_safepoint_check(); - - Thread* thread = Thread::current(); - assert( ignore_max_completed || - thread->is_Java_thread() || - SafepointSynchronize::is_at_safepoint(), - "invariant" ); - ignore_max_completed = ignore_max_completed || !thread->is_Java_thread(); +void PtrQueue::handle_zero_index() { + assert(0 == _index, "Precondition."); + // This thread records the full buffer and allocates a new one (while + // holding the lock if there is one). + if (_buf != NULL) { + if (_lock) { + locking_enqueue_completed_buffer(_buf); + } else { + if (qset()->process_or_enqueue_complete_buffer(_buf)) { + // Recycle the buffer. No allocation. + _sz = qset()->buffer_size(); + _index = _sz; + return; + } + } + } + // Reallocate the buffer + _buf = qset()->allocate_buffer(); + _sz = qset()->buffer_size(); + _index = _sz; + assert(0 <= _index && _index <= _sz, "Invariant."); +} - if (!ignore_max_completed && _max_completed_queue > 0 && - _n_completed_buffers >= (size_t) _max_completed_queue) { - _cbl_mon->unlock(); - bool b = mut_process_buffer(buf); - if (b) { - deallocate_buffer(buf); - return; +bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) { + if (Thread::current()->is_Java_thread()) { + // We don't lock. It is fine to be epsilon-precise here. + if (_max_completed_queue == 0 || _max_completed_queue > 0 && + _n_completed_buffers >= _max_completed_queue + _completed_queue_padding) { + bool b = mut_process_buffer(buf); + if (b) { + // True here means that the buffer hasn't been deallocated and the caller may reuse it. + return true; + } } + } + // The buffer will be enqueued. The caller will have to get a new one. + enqueue_complete_buffer(buf); + return false; +} - // Otherwise, go ahead and enqueue the buffer. Must reaquire the lock. - _cbl_mon->lock_without_safepoint_check(); - } - - // Here we still hold the _cbl_mon. - CompletedBufferNode* cbn = new CompletedBufferNode; - cbn->buf = buf; - cbn->next = NULL; - cbn->index = index; +void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { + MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); + BufferNode* cbn = BufferNode::new_from_buffer(buf); + cbn->set_index(index); if (_completed_buffers_tail == NULL) { assert(_completed_buffers_head == NULL, "Well-formedness"); _completed_buffers_head = cbn; _completed_buffers_tail = cbn; } else { - _completed_buffers_tail->next = cbn; + _completed_buffers_tail->set_next(cbn); _completed_buffers_tail = cbn; } _n_completed_buffers++; - if (!_process_completed && + if (!_process_completed && _process_completed_threshold >= 0 && _n_completed_buffers >= _process_completed_threshold) { _process_completed = true; if (_notify_when_complete) - _cbl_mon->notify_all(); + _cbl_mon->notify(); } debug_only(assert_completed_buffer_list_len_correct_locked()); - _cbl_mon->unlock(); } int PtrQueueSet::completed_buffers_list_length() { int n = 0; - CompletedBufferNode* cbn = _completed_buffers_head; + BufferNode* cbn = _completed_buffers_head; while (cbn != NULL) { n++; - cbn = cbn->next; + cbn = cbn->next(); } return n; } @@ -197,7 +213,7 @@ } void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() { - guarantee((size_t)completed_buffers_list_length() == _n_completed_buffers, + guarantee(completed_buffers_list_length() == _n_completed_buffers, "Completed buffer length is wrong."); } @@ -206,12 +222,8 @@ _sz = sz * oopSize; } -void PtrQueueSet::set_process_completed_threshold(size_t sz) { - _process_completed_threshold = sz; -} - -// Merge lists of buffers. Notify waiting threads if the length of the list -// exceeds threshold. The source queue is emptied as a result. The queues +// Merge lists of buffers. Notify the processing threads. +// The source queue is emptied as a result. The queues // must share the monitor. void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) { assert(_cbl_mon == src->_cbl_mon, "Should share the same lock"); @@ -223,7 +235,7 @@ } else { assert(_completed_buffers_head != NULL, "Well formedness"); if (src->_completed_buffers_head != NULL) { - _completed_buffers_tail->next = src->_completed_buffers_head; + _completed_buffers_tail->set_next(src->_completed_buffers_head); _completed_buffers_tail = src->_completed_buffers_tail; } } @@ -236,31 +248,13 @@ assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL || _completed_buffers_head != NULL && _completed_buffers_tail != NULL, "Sanity"); - - if (!_process_completed && - _n_completed_buffers >= _process_completed_threshold) { - _process_completed = true; - if (_notify_when_complete) - _cbl_mon->notify_all(); - } } -// Merge free lists of the two queues. The free list of the source -// queue is emptied as a result. The queues must share the same -// mutex that guards free lists. -void PtrQueueSet::merge_freelists(PtrQueueSet* src) { - assert(_fl_lock == src->_fl_lock, "Should share the same lock"); - MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag); - if (_buf_free_list != NULL) { - void **p = _buf_free_list; - while (*p != NULL) { - p = (void**)*p; - } - *p = src->_buf_free_list; - } else { - _buf_free_list = src->_buf_free_list; +void PtrQueueSet::notify_if_necessary() { + MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); + if (_n_completed_buffers >= _process_completed_threshold || _max_completed_queue == 0) { + _process_completed = true; + if (_notify_when_complete) + _cbl_mon->notify(); } - _buf_free_list_sz += src->_buf_free_list_sz; - src->_buf_free_list = NULL; - src->_buf_free_list_sz = 0; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -27,8 +27,10 @@ // the addresses of modified old-generation objects. This type supports // this operation. +// The definition of placement operator new(size_t, void*) in the . +#include + class PtrQueueSet; - class PtrQueue VALUE_OBJ_CLASS_SPEC { protected: @@ -77,7 +79,7 @@ else enqueue_known_active(ptr); } - inline void handle_zero_index(); + void handle_zero_index(); void locking_enqueue_completed_buffer(void** buf); void enqueue_known_active(void* ptr); @@ -126,34 +128,65 @@ }; +class BufferNode { + size_t _index; + BufferNode* _next; +public: + BufferNode() : _index(0), _next(NULL) { } + BufferNode* next() const { return _next; } + void set_next(BufferNode* n) { _next = n; } + size_t index() const { return _index; } + void set_index(size_t i) { _index = i; } + + // Align the size of the structure to the size of the pointer + static size_t aligned_size() { + static const size_t alignment = round_to(sizeof(BufferNode), sizeof(void*)); + return alignment; + } + + // BufferNode is allocated before the buffer. + // The chunk of memory that holds both of them is a block. + + // Produce a new BufferNode given a buffer. + static BufferNode* new_from_buffer(void** buf) { + return new (make_block_from_buffer(buf)) BufferNode; + } + + // The following are the required conversion routines: + static BufferNode* make_node_from_buffer(void** buf) { + return (BufferNode*)make_block_from_buffer(buf); + } + static void** make_buffer_from_node(BufferNode *node) { + return make_buffer_from_block(node); + } + static void* make_block_from_node(BufferNode *node) { + return (void*)node; + } + static void** make_buffer_from_block(void* p) { + return (void**)((char*)p + aligned_size()); + } + static void* make_block_from_buffer(void** p) { + return (void*)((char*)p - aligned_size()); + } +}; + // A PtrQueueSet represents resources common to a set of pointer queues. // In particular, the individual queues allocate buffers from this shared // set, and return completed buffers to the set. // All these variables are are protected by the TLOQ_CBL_mon. XXX ??? class PtrQueueSet VALUE_OBJ_CLASS_SPEC { - protected: - - class CompletedBufferNode: public CHeapObj { - public: - void** buf; - size_t index; - CompletedBufferNode* next; - CompletedBufferNode() : buf(NULL), - index(0), next(NULL){ } - }; - Monitor* _cbl_mon; // Protects the fields below. - CompletedBufferNode* _completed_buffers_head; - CompletedBufferNode* _completed_buffers_tail; - size_t _n_completed_buffers; - size_t _process_completed_threshold; + BufferNode* _completed_buffers_head; + BufferNode* _completed_buffers_tail; + int _n_completed_buffers; + int _process_completed_threshold; volatile bool _process_completed; // This (and the interpretation of the first element as a "next" // pointer) are protected by the TLOQ_FL_lock. Mutex* _fl_lock; - void** _buf_free_list; + BufferNode* _buf_free_list; size_t _buf_free_list_sz; // Queue set can share a freelist. The _fl_owner variable // specifies the owner. It is set to "this" by default. @@ -170,6 +203,7 @@ // Maximum number of elements allowed on completed queue: after that, // enqueuer does the work itself. Zero indicates no maximum. int _max_completed_queue; + int _completed_queue_padding; int completed_buffers_list_length(); void assert_completed_buffer_list_len_correct_locked(); @@ -191,9 +225,12 @@ // Because of init-order concerns, we can't pass these as constructor // arguments. void initialize(Monitor* cbl_mon, Mutex* fl_lock, - int max_completed_queue = 0, + int process_completed_threshold, + int max_completed_queue, PtrQueueSet *fl_owner = NULL) { _max_completed_queue = max_completed_queue; + _process_completed_threshold = process_completed_threshold; + _completed_queue_padding = 0; assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?"); _cbl_mon = cbl_mon; _fl_lock = fl_lock; @@ -208,14 +245,17 @@ void deallocate_buffer(void** buf); // Declares that "buf" is a complete buffer. - void enqueue_complete_buffer(void** buf, size_t index = 0, - bool ignore_max_completed = false); + void enqueue_complete_buffer(void** buf, size_t index = 0); + + // To be invoked by the mutator. + bool process_or_enqueue_complete_buffer(void** buf); bool completed_buffers_exist_dirty() { return _n_completed_buffers > 0; } bool process_completed_buffers() { return _process_completed; } + void set_process_completed(bool x) { _process_completed = x; } bool active() { return _all_active; } @@ -226,15 +266,24 @@ // Get the buffer size. size_t buffer_size() { return _sz; } - // Set the number of completed buffers that triggers log processing. - void set_process_completed_threshold(size_t sz); + // Get/Set the number of completed buffers that triggers log processing. + void set_process_completed_threshold(int sz) { _process_completed_threshold = sz; } + int process_completed_threshold() const { return _process_completed_threshold; } // Must only be called at a safe point. Indicates that the buffer free // list size may be reduced, if that is deemed desirable. void reduce_free_list(); - size_t completed_buffers_num() { return _n_completed_buffers; } + int completed_buffers_num() { return _n_completed_buffers; } void merge_bufferlists(PtrQueueSet* src); - void merge_freelists(PtrQueueSet* src); + + void set_max_completed_queue(int m) { _max_completed_queue = m; } + int max_completed_queue() { return _max_completed_queue; } + + void set_completed_queue_padding(int padding) { _completed_queue_padding = padding; } + int completed_queue_padding() { return _completed_queue_padding; } + + // Notify the consumer if the number of buffers crossed the threshold + void notify_if_necessary(); }; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -67,9 +67,9 @@ {} void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, - int max_completed_queue, + int process_completed_threshold, Mutex* lock) { - PtrQueueSet::initialize(cbl_mon, fl_lock, max_completed_queue); + PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1); _shared_satb_queue.set_lock(lock); if (ParallelGCThreads > 0) { _par_closures = NEW_C_HEAP_ARRAY(ObjectClosure*, ParallelGCThreads); @@ -122,12 +122,12 @@ bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par, int worker) { - CompletedBufferNode* nd = NULL; + BufferNode* nd = NULL; { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); if (_completed_buffers_head != NULL) { nd = _completed_buffers_head; - _completed_buffers_head = nd->next; + _completed_buffers_head = nd->next(); if (_completed_buffers_head == NULL) _completed_buffers_tail = NULL; _n_completed_buffers--; if (_n_completed_buffers == 0) _process_completed = false; @@ -135,9 +135,9 @@ } ObjectClosure* cl = (par ? _par_closures[worker] : _closure); if (nd != NULL) { - ObjPtrQueue::apply_closure_to_buffer(cl, nd->buf, 0, _sz); - deallocate_buffer(nd->buf); - delete nd; + void **buf = BufferNode::make_buffer_from_node(nd); + ObjPtrQueue::apply_closure_to_buffer(cl, buf, 0, _sz); + deallocate_buffer(buf); return true; } else { return false; @@ -145,13 +145,13 @@ } void SATBMarkQueueSet::abandon_partial_marking() { - CompletedBufferNode* buffers_to_delete = NULL; + BufferNode* buffers_to_delete = NULL; { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); while (_completed_buffers_head != NULL) { - CompletedBufferNode* nd = _completed_buffers_head; - _completed_buffers_head = nd->next; - nd->next = buffers_to_delete; + BufferNode* nd = _completed_buffers_head; + _completed_buffers_head = nd->next(); + nd->set_next(buffers_to_delete); buffers_to_delete = nd; } _completed_buffers_tail = NULL; @@ -159,10 +159,9 @@ DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); } while (buffers_to_delete != NULL) { - CompletedBufferNode* nd = buffers_to_delete; - buffers_to_delete = nd->next; - deallocate_buffer(nd->buf); - delete nd; + BufferNode* nd = buffers_to_delete; + buffers_to_delete = nd->next(); + deallocate_buffer(BufferNode::make_buffer_from_node(nd)); } assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); // So we can safely manipulate these queues. diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -60,8 +60,8 @@ SATBMarkQueueSet(); void initialize(Monitor* cbl_mon, Mutex* fl_lock, - int max_completed_queue = 0, - Mutex* lock = NULL); + int process_completed_threshold, + Mutex* lock); static void handle_zero_index_for_thread(JavaThread* t); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -42,7 +42,7 @@ void VM_G1IncCollectionPause::doit() { JvmtiGCForAllocationMarker jgcm; G1CollectedHeap* g1h = G1CollectedHeap::heap(); - GCCauseSetter x(g1h, GCCause::_g1_inc_collection_pause); + GCCauseSetter x(g1h, _gc_cause); g1h->do_collection_pause_at_safepoint(); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -68,8 +68,9 @@ class VM_G1IncCollectionPause: public VM_GC_Operation { public: - VM_G1IncCollectionPause(int gc_count_before) : - VM_GC_Operation(gc_count_before) {} + VM_G1IncCollectionPause(int gc_count_before, + GCCause::Cause gc_cause = GCCause::_g1_inc_collection_pause) : + VM_GC_Operation(gc_count_before) { _gc_cause = gc_cause; } virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; } virtual void doit(); virtual const char* name() const { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 Wed Jul 05 17:05:01 2017 +0200 @@ -109,7 +109,6 @@ dirtyCardQueue.cpp dirtyCardQueue.hpp dirtyCardQueue.cpp heapRegionRemSet.hpp dirtyCardQueue.cpp mutexLocker.hpp -dirtyCardQueue.cpp ptrQueue.inline.hpp dirtyCardQueue.cpp safepoint.hpp dirtyCardQueue.cpp thread.hpp dirtyCardQueue.cpp thread_.inline.hpp @@ -222,6 +221,15 @@ g1MarkSweep.hpp timer.hpp g1MarkSweep.hpp universe.hpp +g1MemoryPool.cpp heapRegion.hpp +g1MemoryPool.cpp g1CollectedHeap.inline.hpp +g1MemoryPool.cpp g1CollectedHeap.hpp +g1MemoryPool.cpp g1CollectorPolicy.hpp +g1MemoryPool.cpp g1MemoryPool.hpp + +g1MemoryPool.hpp memoryUsage.hpp +g1MemoryPool.hpp memoryPool.hpp + g1OopClosures.inline.hpp concurrentMark.hpp g1OopClosures.inline.hpp g1OopClosures.hpp g1OopClosures.inline.hpp g1CollectedHeap.hpp @@ -303,12 +311,13 @@ klass.hpp g1OopClosures.hpp +memoryService.cpp g1MemoryPool.hpp + ptrQueue.cpp allocation.hpp ptrQueue.cpp allocation.inline.hpp ptrQueue.cpp mutex.hpp ptrQueue.cpp mutexLocker.hpp ptrQueue.cpp ptrQueue.hpp -ptrQueue.cpp ptrQueue.inline.hpp ptrQueue.cpp thread_.inline.hpp ptrQueue.hpp allocation.hpp @@ -318,7 +327,6 @@ satbQueue.cpp allocation.inline.hpp satbQueue.cpp mutexLocker.hpp -satbQueue.cpp ptrQueue.inline.hpp satbQueue.cpp satbQueue.hpp satbQueue.cpp sharedHeap.hpp satbQueue.cpp thread.hpp diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -51,7 +51,7 @@ cname = PerfDataManager::counter_name(name_space(), "oldCapacity"); _old_capacity = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Bytes, (jlong) Arguments::initial_heap_size(), CHECK); + PerfData::U_Bytes, (jlong) InitialHeapSize, CHECK); cname = PerfDataManager::counter_name(name_space(), "boundaryMoved"); _boundary_moved = PerfDataManager::create_variable(SUN_GC, cname, diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/includeDB_compiler2 --- a/hotspot/src/share/vm/includeDB_compiler2 Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/includeDB_compiler2 Wed Jul 05 17:05:01 2017 +0200 @@ -149,6 +149,7 @@ c2compiler.hpp abstractCompiler.hpp callGenerator.cpp addnode.hpp +callGenerator.cpp bcEscapeAnalyzer.hpp callGenerator.cpp callGenerator.hpp callGenerator.cpp callnode.hpp callGenerator.cpp cfgnode.hpp @@ -321,6 +322,7 @@ compile.cpp rootnode.hpp compile.cpp runtime.hpp compile.cpp signature.hpp +compile.cpp stringopts.hpp compile.cpp stubRoutines.hpp compile.cpp systemDictionary.hpp compile.cpp timer.hpp @@ -476,12 +478,16 @@ graphKit.cpp runtime.hpp graphKit.cpp sharedRuntime.hpp +graphKit.hpp addnode.hpp graphKit.hpp callnode.hpp graphKit.hpp cfgnode.hpp graphKit.hpp ciEnv.hpp +graphKit.hpp divnode.hpp graphKit.hpp compile.hpp graphKit.hpp deoptimization.hpp graphKit.hpp phaseX.hpp +graphKit.hpp mulnode.hpp +graphKit.hpp subnode.hpp graphKit.hpp type.hpp idealKit.cpp addnode.hpp @@ -490,7 +496,10 @@ idealKit.cpp idealKit.hpp idealKit.cpp runtime.hpp +idealKit.hpp addnode.hpp +idealKit.hpp cfgnode.hpp idealKit.hpp connode.hpp +idealKit.hpp divnode.hpp idealKit.hpp mulnode.hpp idealKit.hpp phaseX.hpp idealKit.hpp subnode.hpp @@ -641,6 +650,7 @@ macro.cpp callnode.hpp macro.cpp cfgnode.hpp macro.cpp compile.hpp +macro.cpp compileLog.hpp macro.cpp connode.hpp macro.cpp locknode.hpp macro.cpp loopnode.hpp @@ -993,6 +1003,21 @@ split_if.cpp connode.hpp split_if.cpp loopnode.hpp +stringopts.hpp phaseX.hpp +stringopts.hpp node.hpp + +stringopts.cpp addnode.hpp +stringopts.cpp callnode.hpp +stringopts.cpp callGenerator.hpp +stringopts.cpp compileLog.hpp +stringopts.cpp divnode.hpp +stringopts.cpp idealKit.hpp +stringopts.cpp graphKit.hpp +stringopts.cpp rootnode.hpp +stringopts.cpp runtime.hpp +stringopts.cpp subnode.hpp +stringopts.cpp stringopts.hpp + stubGenerator_.cpp runtime.hpp stubRoutines.cpp runtime.hpp diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/includeDB_core --- a/hotspot/src/share/vm/includeDB_core Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/includeDB_core Wed Jul 05 17:05:01 2017 +0200 @@ -289,7 +289,7 @@ attachListener.hpp debug.hpp attachListener.hpp ostream.hpp -barrierSet.cpp barrierSet.hpp +barrierSet.cpp barrierSet.inline.hpp barrierSet.cpp collectedHeap.hpp barrierSet.cpp universe.hpp @@ -570,6 +570,7 @@ ciEnv.hpp dependencies.hpp ciEnv.hpp exceptionHandlerTable.hpp ciEnv.hpp oopMap.hpp +ciEnv.hpp systemDictionary.hpp ciEnv.hpp thread.hpp ciExceptionHandler.cpp ciExceptionHandler.hpp @@ -1291,6 +1292,7 @@ cpCacheOop.cpp markSweep.inline.hpp cpCacheOop.cpp objArrayOop.hpp cpCacheOop.cpp oop.inline.hpp +cpCacheOop.cpp rewriter.hpp cpCacheOop.cpp universe.inline.hpp cpCacheOop.hpp allocation.hpp diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -281,7 +281,7 @@ #define DO_BACKEDGE_CHECKS(skip, branch_pc) \ if ((skip) <= 0) { \ - if (UseCompiler && UseLoopCounter) { \ + if (UseLoopCounter) { \ bool do_OSR = UseOnStackReplacement; \ BACKEDGE_COUNT->increment(); \ if (do_OSR) do_OSR = BACKEDGE_COUNT->reached_InvocationLimit(); \ @@ -289,16 +289,12 @@ nmethod* osr_nmethod; \ OSR_REQUEST(osr_nmethod, branch_pc); \ if (osr_nmethod != NULL && osr_nmethod->osr_entry_bci() != InvalidOSREntryBci) { \ - intptr_t* buf; \ - CALL_VM(buf=SharedRuntime::OSR_migration_begin(THREAD), handle_exception); \ + intptr_t* buf = SharedRuntime::OSR_migration_begin(THREAD); \ istate->set_msg(do_osr); \ istate->set_osr_buf((address)buf); \ istate->set_osr_entry(osr_nmethod->osr_entry()); \ return; \ } \ - } else { \ - INCR_INVOCATION_COUNT; \ - SAFEPOINT; \ } \ } /* UseCompiler ... */ \ INCR_INVOCATION_COUNT; \ @@ -1281,12 +1277,7 @@ jfloat f; jdouble r; f = STACK_FLOAT(-1); -#ifdef IA64 - // IA64 gcc bug - r = ( f == 0.0f ) ? (jdouble) f : (jdouble) f + ia64_double_zero; -#else r = (jdouble) f; -#endif MORE_STACK(-1); // POP SET_STACK_DOUBLE(r, 1); UPDATE_PC_AND_TOS_AND_CONTINUE(1, 2); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/bytecodeTracer.cpp --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -282,18 +282,21 @@ constantPoolOop constants = method()->constants(); constantTag tag = constants->tag_at(i); + int nt_index = -1; + switch (tag.value()) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Methodref: case JVM_CONSTANT_Fieldref: + case JVM_CONSTANT_NameAndType: break; default: st->print_cr(" bad tag=%d at %d", tag.value(), i); return; } - symbolOop name = constants->name_ref_at(orig_i); - symbolOop signature = constants->signature_ref_at(orig_i); + symbolOop name = constants->uncached_name_ref_at(i); + symbolOop signature = constants->uncached_signature_ref_at(i); st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string()); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/interpreter.cpp --- a/hotspot/src/share/vm/interpreter/interpreter.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -314,6 +314,20 @@ break; } + case Bytecodes::_invokedynamic: { + Thread *thread = Thread::current(); + ResourceMark rm(thread); + methodHandle mh(thread, method); + type = Bytecode_invoke_at(mh, bci)->result_type(thread); + // since the cache entry might not be initialized: + // (NOT needed for the old calling convension) + if (!is_top_frame) { + int index = Bytes::get_native_u4(bcp+1); + method->constants()->cache()->entry_at(index)->set_parameter_size(callee_parameters); + } + break; + } + case Bytecodes::_ldc : type = constant_pool_type( method, *(bcp+1) ); break; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -681,7 +681,7 @@ IRT_END -// First time execution: Resolve symbols, create a permanent CallSiteImpl object. +// First time execution: Resolve symbols, create a permanent CallSite object. IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { ResourceMark rm(thread); @@ -708,21 +708,16 @@ constantPoolHandle pool(thread, caller_method->constants()); pool->set_invokedynamic(); // mark header to flag active call sites - int raw_index = four_byte_index(thread); - assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "invokedynamic indexes marked specially"); - - // there are two CPC entries that are of interest: - int site_index = constantPoolCacheOopDesc::decode_secondary_index(raw_index); - int main_index = pool->cache()->entry_at(site_index)->main_entry_index(); - // and there is one CP entry, a NameAndType: - int nt_index = pool->map_instruction_operand_to_index(raw_index); + int site_index = four_byte_index(thread); + // there is a second CPC entries that is of interest; it caches signature info: + int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index(); // first resolve the signature to a MH.invoke methodOop if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) { JvmtiHideSingleStepping jhss(thread); CallInfo info; LinkResolver::resolve_invoke(info, Handle(), pool, - raw_index, bytecode, CHECK); + site_index, bytecode, CHECK); // The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves // as a common reference point for all invokedynamic call sites with // that exact call descriptor. We will link it in the CP cache exactly @@ -741,7 +736,7 @@ assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(), "correct result from LinkResolver::resolve_invokedynamic"); - symbolHandle call_site_name(THREAD, pool->nt_name_ref_at(nt_index)); + symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index)); Handle call_site = SystemDictionary::make_dynamic_call_site(caller_method->method_holder(), caller_method->method_idnum(), @@ -753,61 +748,11 @@ // In the secondary entry, the f1 field is the call site, and the f2 (index) // field is some data about the invoke site. int extra_data = 0; - pool->cache()->entry_at(site_index)->set_dynamic_call(call_site(), extra_data); + pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site(), extra_data); } IRT_END -// Called on first time execution, and also whenever the CallSite.target is null. -// FIXME: Do more of this in Java code. -IRT_ENTRY(void, InterpreterRuntime::bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site)) { - methodHandle mh_invdyn(thread, (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site)); - Handle mh_type(thread, mh_invdyn->method_handle_type()); - objArrayHandle mh_ptypes(thread, java_dyn_MethodType::ptypes(mh_type())); - - // squish the arguments down to a single array - int nargs = mh_ptypes->length(); - objArrayHandle arg_array; - { - objArrayOop aaoop = oopFactory::new_objArray(SystemDictionary::object_klass(), nargs, CHECK); - arg_array = objArrayHandle(thread, aaoop); - } - frame fr = thread->last_frame(); - assert(fr.interpreter_frame_bcp() != NULL, "sanity"); - int tos_offset = 0; - for (int i = nargs; --i >= 0; ) { - intptr_t* slot_addr = fr.interpreter_frame_tos_at(tos_offset++); - oop ptype = mh_ptypes->obj_at(i); - oop arg = NULL; - if (!java_lang_Class::is_primitive(ptype)) { - arg = *(oop*) slot_addr; - } else { - BasicType bt = java_lang_Class::primitive_type(ptype); - assert(frame::interpreter_frame_expression_stack_direction() < 0, "else reconsider this code"); - jvalue value; - Interpreter::get_jvalue_in_slot(slot_addr, bt, &value); - tos_offset += type2size[bt]-1; - arg = java_lang_boxing_object::create(bt, &value, CHECK); - // FIXME: These boxing objects are not canonicalized under - // the Java autoboxing rules. They should be... - // The best approach would be to push the arglist creation into Java. - // The JVM should use a lower-level interface to communicate argument lists. - } - arg_array->obj_at_put(i, arg); - } - - // now find the bootstrap method - oop bootstrap_mh_oop = instanceKlass::cast(fr.interpreter_frame_method()->method_holder())->bootstrap_method(); - assert(bootstrap_mh_oop != NULL, "resolve_invokedynamic ensures a BSM"); - - // return the bootstrap method and argument array via vm_result/_2 - thread->set_vm_result(bootstrap_mh_oop); - thread->set_vm_result_2(arg_array()); -} -IRT_END - - - //------------------------------------------------------------------------------------------------------------------------ // Miscellaneous diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/interpreterRuntime.hpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -91,7 +91,6 @@ // Calls static void resolve_invoke (JavaThread* thread, Bytecodes::Code bytecode); static void resolve_invokedynamic(JavaThread* thread); - static void bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site); // Breakpoints static void _breakpoint(JavaThread* thread, methodOopDesc* method, address bcp); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/linkResolver.cpp --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1015,11 +1015,8 @@ // This guy is reached from InterpreterRuntime::resolve_invokedynamic. - assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "must be secondary index"); - int nt_index = pool->map_instruction_operand_to_index(raw_index); - // At this point, we only need the signature, and can ignore the name. - symbolHandle method_signature(THREAD, pool->nt_signature_ref_at(nt_index)); + symbolHandle method_signature(THREAD, pool->signature_ref_at(raw_index)); // raw_index works directly symbolHandle method_name = vmSymbolHandles::invoke_name(); KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/rewriter.cpp --- a/hotspot/src/share/vm/interpreter/rewriter.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -48,16 +48,6 @@ } -int Rewriter::add_extra_cp_cache_entry(int main_entry) { - // Hack: We put it on the map as an encoded value. - // The only place that consumes this is ConstantPoolCacheEntry::set_initial_state - int encoded = constantPoolCacheOopDesc::encode_secondary_index(main_entry); - int plain_secondary_index = _cp_cache_map.append(encoded); - return constantPoolCacheOopDesc::encode_secondary_index(plain_secondary_index); -} - - - // Creates a constant pool cache given a CPC map // This creates the constant pool cache initially in a state // that is unsafe for concurrent GC processing but sets it to @@ -127,7 +117,7 @@ assert(p[-1] == Bytecodes::_invokedynamic, ""); int cp_index = Bytes::get_Java_u2(p); int cpc = maybe_add_cp_cache_entry(cp_index); // add lazily - int cpc2 = add_extra_cp_cache_entry(cpc); + int cpc2 = add_secondary_cp_cache_entry(cpc); // Replace the trailing four bytes with a CPC index for the dynamic // call site. Unlike other CPC entries, there is one per bytecode, @@ -137,7 +127,7 @@ // all these entries. That is the main reason invokedynamic // must have a five-byte instruction format. (Of course, other JVM // implementations can use the bytes for other purposes.) - Bytes::put_native_u4(p, cpc2); + Bytes::put_native_u4(p, constantPoolCacheOopDesc::encode_secondary_index(cpc2)); // Note: We use native_u4 format exclusively for 4-byte indexes. } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/rewriter.hpp --- a/hotspot/src/share/vm/interpreter/rewriter.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/rewriter.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -43,13 +43,18 @@ bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; } int maybe_add_cp_cache_entry(int i) { return has_cp_cache(i) ? _cp_map[i] : add_cp_cache_entry(i); } int add_cp_cache_entry(int cp_index) { + assert((cp_index & _secondary_entry_tag) == 0, "bad tag"); assert(_cp_map[cp_index] == -1, "not twice on same cp_index"); int cache_index = _cp_cache_map.append(cp_index); _cp_map.at_put(cp_index, cache_index); assert(cp_entry_to_cp_cache(cp_index) == cache_index, ""); return cache_index; } - int add_extra_cp_cache_entry(int main_entry); + int add_secondary_cp_cache_entry(int main_cpc_entry) { + assert(main_cpc_entry < _cp_cache_map.length(), "must be earlier CP cache entry"); + int cache_index = _cp_cache_map.append(main_cpc_entry | _secondary_entry_tag); + return cache_index; + } // All the work goes in here: Rewriter(instanceKlassHandle klass, TRAPS); @@ -65,4 +70,8 @@ public: // Driver routine: static void rewrite(instanceKlassHandle klass, TRAPS); + + enum { + _secondary_entry_tag = nth_bit(30) + }; }; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/templateInterpreter.cpp --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -178,14 +178,12 @@ #endif // !PRODUCT EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries]; EntryPoint TemplateInterpreter::_earlyret_entry; -EntryPoint TemplateInterpreter::_return_unbox_entry; EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ]; EntryPoint TemplateInterpreter::_continuation_entry; EntryPoint TemplateInterpreter::_safept_entry; address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; -address TemplateInterpreter::_return_5_unbox_addrs_by_index[TemplateInterpreter::number_of_return_addrs]; DispatchTable TemplateInterpreter::_active_table; DispatchTable TemplateInterpreter::_normal_table; @@ -253,22 +251,6 @@ } } - if (EnableInvokeDynamic) { - CodeletMark cm(_masm, "unboxing return entry points"); - Interpreter::_return_unbox_entry = - EntryPoint( - generate_return_unbox_entry_for(btos, 5), - generate_return_unbox_entry_for(ctos, 5), - generate_return_unbox_entry_for(stos, 5), - generate_return_unbox_entry_for(atos, 5), // cast conversion - generate_return_unbox_entry_for(itos, 5), - generate_return_unbox_entry_for(ltos, 5), - generate_return_unbox_entry_for(ftos, 5), - generate_return_unbox_entry_for(dtos, 5), - Interpreter::_return_entry[5].entry(vtos) // no unboxing for void - ); - } - { CodeletMark cm(_masm, "earlyret entry points"); Interpreter::_earlyret_entry = EntryPoint( @@ -319,8 +301,6 @@ int index = Interpreter::TosState_as_index(states[j]); Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3); Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5); - if (EnableInvokeDynamic) - Interpreter::_return_5_unbox_addrs_by_index[index] = Interpreter::return_unbox_entry(states[j], 5); } { CodeletMark cm(_masm, "continuation entry points"); @@ -485,9 +465,11 @@ void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep) { assert(t->is_valid(), "template must exist"); switch (t->tos_in()) { - case btos: vep = __ pc(); __ pop(btos); bep = __ pc(); generate_and_dispatch(t); break; - case ctos: vep = __ pc(); __ pop(ctos); sep = __ pc(); generate_and_dispatch(t); break; - case stos: vep = __ pc(); __ pop(stos); sep = __ pc(); generate_and_dispatch(t); break; + case btos: + case ctos: + case stos: + ShouldNotReachHere(); // btos/ctos/stos should use itos. + break; case atos: vep = __ pc(); __ pop(atos); aep = __ pc(); generate_and_dispatch(t); break; case itos: vep = __ pc(); __ pop(itos); iep = __ pc(); generate_and_dispatch(t); break; case ltos: vep = __ pc(); __ pop(ltos); lep = __ pc(); generate_and_dispatch(t); break; @@ -547,18 +529,6 @@ } -address TemplateInterpreter::return_unbox_entry(TosState state, int length) { - assert(EnableInvokeDynamic, ""); - if (state == vtos) { - // no unboxing to do, actually - return return_entry(state, length); - } else { - assert(length == 5, "unboxing entries generated for invokedynamic only"); - return _return_unbox_entry.entry(state); - } -} - - address TemplateInterpreter::deopt_entry(TosState state, int length) { guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length"); return _deopt_entry[length].entry(state); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/templateInterpreter.hpp --- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -110,14 +110,12 @@ #endif // !PRODUCT static EntryPoint _return_entry[number_of_return_entries]; // entry points to return to from a call static EntryPoint _earlyret_entry; // entry point to return early from a call - static EntryPoint _return_unbox_entry; // entry point to unbox a return value from a call static EntryPoint _deopt_entry[number_of_deopt_entries]; // entry points to return to from a deoptimization static EntryPoint _continuation_entry; static EntryPoint _safept_entry; static address _return_3_addrs_by_index[number_of_return_addrs]; // for invokevirtual return entries static address _return_5_addrs_by_index[number_of_return_addrs]; // for invokeinterface return entries - static address _return_5_unbox_addrs_by_index[number_of_return_addrs]; // for invokedynamic bootstrap methods static DispatchTable _active_table; // the active dispatch table (used by the interpreter for dispatch) static DispatchTable _normal_table; // the normal dispatch table (used to set the active table in normal mode) @@ -159,12 +157,10 @@ // Support for invokes static address* return_3_addrs_by_index_table() { return _return_3_addrs_by_index; } static address* return_5_addrs_by_index_table() { return _return_5_addrs_by_index; } - static address* return_5_unbox_addrs_by_index_table() { return _return_5_unbox_addrs_by_index; } static int TosState_as_index(TosState state); // computes index into return_3_entry_by_index table static address return_entry (TosState state, int length); static address deopt_entry (TosState state, int length); - static address return_unbox_entry(TosState state, int length); // Safepoint support static void notice_safepoints(); // stops the thread when reaching a safepoint diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -51,10 +51,7 @@ address generate_WrongMethodType_handler(); address generate_ArrayIndexOutOfBounds_handler(const char* name); address generate_continuation_for(TosState state); - address generate_return_entry_for(TosState state, int step, bool unbox = false); - address generate_return_unbox_entry_for(TosState state, int step) { - return generate_return_entry_for(state, step, true); - } + address generate_return_entry_for(TosState state, int step); address generate_earlyret_entry_for(TosState state); address generate_deopt_entry_for(TosState state, int step); address generate_safept_entry_for(TosState state, address runtime_entry); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/barrierSet.cpp --- a/hotspot/src/share/vm/memory/barrierSet.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/barrierSet.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -41,11 +41,6 @@ // count is number of array elements being written void BarrierSet::static_write_ref_array_post(HeapWord* start, size_t count) { - assert(count <= (size_t)max_intx, "count too large"); - HeapWord* end = start + objArrayOopDesc::array_size((int)count); -#if 0 - warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT","INTPTR_FORMAT")\t", - start, count, start, end); -#endif - Universe::heap()->barrier_set()->write_ref_array_work(MemRegion(start, end)); + // simply delegate to instance method + Universe::heap()->barrier_set()->write_ref_array(start, count); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/barrierSet.hpp --- a/hotspot/src/share/vm/memory/barrierSet.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/barrierSet.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -121,17 +121,20 @@ virtual void read_ref_array(MemRegion mr) = 0; virtual void read_prim_array(MemRegion mr) = 0; + // Below length is the # array elements being written virtual void write_ref_array_pre( oop* dst, int length) {} virtual void write_ref_array_pre(narrowOop* dst, int length) {} + // Below MemRegion mr is expected to be HeapWord-aligned inline void write_ref_array(MemRegion mr); + // Below count is the # array elements being written, starting + // at the address "start", which may not necessarily be HeapWord-aligned + inline void write_ref_array(HeapWord* start, size_t count); - // Static versions, suitable for calling from generated code. + // Static versions, suitable for calling from generated code; + // count is # array elements being written, starting with "start", + // which may not necessarily be HeapWord-aligned. static void static_write_ref_array_pre(HeapWord* start, size_t count); static void static_write_ref_array_post(HeapWord* start, size_t count); - // Narrow oop versions of the above; count is # of array elements being written, - // starting with "start", which is HeapWord-aligned. - static void static_write_ref_array_pre_narrow(HeapWord* start, size_t count); - static void static_write_ref_array_post_narrow(HeapWord* start, size_t count); protected: virtual void write_ref_array_work(MemRegion mr) = 0; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/barrierSet.inline.hpp --- a/hotspot/src/share/vm/memory/barrierSet.inline.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/barrierSet.inline.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -43,6 +43,8 @@ } void BarrierSet::write_ref_array(MemRegion mr) { + assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start() , "Unaligned start"); + assert((HeapWord*)align_size_up ((uintptr_t)mr.end(), HeapWordSize) == mr.end(), "Unaligned end" ); if (kind() == CardTableModRef) { ((CardTableModRefBS*)this)->inline_write_ref_array(mr); } else { @@ -50,6 +52,34 @@ } } +// count is number of array elements being written +void BarrierSet::write_ref_array(HeapWord* start, size_t count) { + assert(count <= (size_t)max_intx, "count too large"); + HeapWord* end = (HeapWord*)((char*)start + (count*heapOopSize)); + // In the case of compressed oops, start and end may potentially be misaligned; + // so we need to conservatively align the first downward (this is not + // strictly necessary for current uses, but a case of good hygiene and, + // if you will, aesthetics) and the second upward (this is essential for + // current uses) to a HeapWord boundary, so we mark all cards overlapping + // this write. In the event that this evolves in the future to calling a + // logging barrier of narrow oop granularity, like the pre-barrier for G1 + // (mentioned here merely by way of example), we will need to change this + // interface, much like the pre-barrier one above, so it is "exactly precise" + // (if i may be allowed the adverbial redundancy for emphasis) and does not + // include narrow oop slots not included in the original write interval. + HeapWord* aligned_start = (HeapWord*)align_size_down((uintptr_t)start, HeapWordSize); + HeapWord* aligned_end = (HeapWord*)align_size_up ((uintptr_t)end, HeapWordSize); + // If compressed oops were not being used, these should already be aligned + assert(UseCompressedOops || (aligned_start == start && aligned_end == end), + "Expected heap word alignment of start and end"); +#if 0 + warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT","INTPTR_FORMAT")\t", + start, count, aligned_start, aligned_end); +#endif + write_ref_array_work(MemRegion(aligned_start, aligned_end)); +} + + void BarrierSet::write_region(MemRegion mr) { if (kind() == CardTableModRef) { ((CardTableModRefBS*)this)->inline_write_region(mr); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/cardTableModRefBS.cpp --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -511,6 +511,8 @@ } void CardTableModRefBS::dirty_MemRegion(MemRegion mr) { + assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start(), "Unaligned start"); + assert((HeapWord*)align_size_up ((uintptr_t)mr.end(), HeapWordSize) == mr.end(), "Unaligned end" ); jbyte* cur = byte_for(mr.start()); jbyte* last = byte_after(mr.last()); while (cur < last) { @@ -520,6 +522,8 @@ } void CardTableModRefBS::invalidate(MemRegion mr, bool whole_heap) { + assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start(), "Unaligned start"); + assert((HeapWord*)align_size_up ((uintptr_t)mr.end(), HeapWordSize) == mr.end(), "Unaligned end" ); for (int i = 0; i < _cur_covered_regions; i++) { MemRegion mri = mr.intersection(_covered[i]); if (!mri.is_empty()) dirty_MemRegion(mri); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/collectorPolicy.cpp --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -55,7 +55,7 @@ void CollectorPolicy::initialize_size_info() { // User inputs from -mx and ms are aligned - set_initial_heap_byte_size(Arguments::initial_heap_size()); + set_initial_heap_byte_size(InitialHeapSize); if (initial_heap_byte_size() == 0) { set_initial_heap_byte_size(NewSize + OldSize); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/heap.cpp --- a/hotspot/src/share/vm/memory/heap.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/heap.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -464,7 +464,7 @@ } // Verify that freelist contains the right amount of free space - guarantee(len == _free_segments, "wrong freelist"); + // guarantee(len == _free_segments, "wrong freelist"); // Verify that the number of free blocks is not out of hand. static int free_block_threshold = 10000; @@ -479,5 +479,5 @@ for(HeapBlock *h = first_block(); h != NULL; h = next_block(h)) { if (h->free()) count--; } - guarantee(count == 0, "missing free blocks"); + // guarantee(count == 0, "missing free blocks"); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/referenceProcessor.cpp --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -299,8 +299,8 @@ template -static bool enqueue_discovered_ref_helper(ReferenceProcessor* ref, - AbstractRefProcTaskExecutor* task_executor) { +bool enqueue_discovered_ref_helper(ReferenceProcessor* ref, + AbstractRefProcTaskExecutor* task_executor) { // Remember old value of pending references list T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr(); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/sharedHeap.hpp --- a/hotspot/src/share/vm/memory/sharedHeap.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/sharedHeap.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -224,10 +224,6 @@ CodeBlobClosure* code_roots, OopClosure* non_root_closure); - - // Like CollectedHeap::collect, but assume that the caller holds the Heap_lock. - virtual void collect_locked(GCCause::Cause cause) = 0; - // The functions below are helper functions that a subclass of // "SharedHeap" can use in the implementation of its virtual // functions. diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/universe.cpp --- a/hotspot/src/share/vm/memory/universe.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/universe.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -67,6 +67,8 @@ objArrayOop Universe::_the_empty_system_obj_array = NULL; objArrayOop Universe::_the_empty_class_klass_array = NULL; objArrayOop Universe::_the_array_interfaces_array = NULL; +oop Universe::_the_null_string = NULL; +oop Universe::_the_min_jint_string = NULL; LatestMethodOopCache* Universe::_finalizer_register_cache = NULL; LatestMethodOopCache* Universe::_loader_addClass_cache = NULL; ActiveMethodOopsCache* Universe::_reflect_invoke_cache = NULL; @@ -187,6 +189,8 @@ f->do_oop((oop*)&_the_empty_system_obj_array); f->do_oop((oop*)&_the_empty_class_klass_array); f->do_oop((oop*)&_the_array_interfaces_array); + f->do_oop((oop*)&_the_null_string); + f->do_oop((oop*)&_the_min_jint_string); _finalizer_register_cache->oops_do(f); _loader_addClass_cache->oops_do(f); _reflect_invoke_cache->oops_do(f); @@ -289,6 +293,9 @@ klassOop ok = SystemDictionary::object_klass(); + _the_null_string = StringTable::intern("null", CHECK); + _the_min_jint_string = StringTable::intern("-2147483648", CHECK); + if (UseSharedSpaces) { // Verify shared interfaces array. assert(_the_array_interfaces_array->obj_at(0) == @@ -744,22 +751,22 @@ static const uint64_t OopEncodingHeapMax = NarrowOopHeapMax << LogMinObjAlignmentInBytes; char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) { + size_t base = 0; #ifdef _LP64 if (UseCompressedOops) { assert(mode == UnscaledNarrowOop || mode == ZeroBasedNarrowOop || mode == HeapBasedNarrowOop, "mode is invalid"); + const size_t total_size = heap_size + HeapBaseMinAddress; // Return specified base for the first request. if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) { - return (char*)HeapBaseMinAddress; - } - const size_t total_size = heap_size + HeapBaseMinAddress; - if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) { + base = HeapBaseMinAddress; + } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) { if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) && (Universe::narrow_oop_shift() == 0)) { // Use 32-bits oops without encoding and // place heap's top on the 4Gb boundary - return (char*)(NarrowOopHeapMax - heap_size); + base = (NarrowOopHeapMax - heap_size); } else { // Can't reserve with NarrowOopShift == 0 Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); @@ -768,16 +775,38 @@ // Use zero based compressed oops with encoding and // place heap's top on the 32Gb boundary in case // total_size > 4Gb or failed to reserve below 4Gb. - return (char*)(OopEncodingHeapMax - heap_size); + base = (OopEncodingHeapMax - heap_size); } } } else { // Can't reserve below 32Gb. Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); } + // Set narrow_oop_base and narrow_oop_use_implicit_null_checks + // used in ReservedHeapSpace() constructors. + // The final values will be set in initialize_heap() below. + if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) { + // Use zero based compressed oops + Universe::set_narrow_oop_base(NULL); + // Don't need guard page for implicit checks in indexed + // addressing mode with zero based Compressed Oops. + Universe::set_narrow_oop_use_implicit_null_checks(true); + } else { + // Set to a non-NULL value so the ReservedSpace ctor computes + // the correct no-access prefix. + // The final value will be set in initialize_heap() below. + Universe::set_narrow_oop_base((address)NarrowOopHeapMax); +#ifdef _WIN64 + if (UseLargePages) { + // Cannot allocate guard pages for implicit checks in indexed + // addressing mode when large pages are specified on windows. + Universe::set_narrow_oop_use_implicit_null_checks(false); + } +#endif // _WIN64 + } } #endif - return NULL; // also return NULL (don't care) for 32-bit VM + return (char*)base; // also return NULL (don't care) for 32-bit VM } jint Universe::initialize_heap() { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/memory/universe.hpp --- a/hotspot/src/share/vm/memory/universe.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/memory/universe.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -169,6 +169,8 @@ static objArrayOop _the_empty_system_obj_array; // Canonicalized system obj array static objArrayOop _the_empty_class_klass_array; // Canonicalized obj array of type java.lang.Class static objArrayOop _the_array_interfaces_array; // Canonicalized 2-array of cloneable & serializable klasses + static oop _the_null_string; // A cache of "null" as a Java string + static oop _the_min_jint_string; // A cache of "-2147483648" as a Java string static LatestMethodOopCache* _finalizer_register_cache; // static method for registering finalizable objects static LatestMethodOopCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector static ActiveMethodOopsCache* _reflect_invoke_cache; // method for security checks @@ -310,6 +312,8 @@ static objArrayOop the_empty_system_obj_array () { return _the_empty_system_obj_array; } static objArrayOop the_empty_class_klass_array () { return _the_empty_class_klass_array; } static objArrayOop the_array_interfaces_array() { return _the_array_interfaces_array; } + static oop the_null_string() { return _the_null_string; } + static oop the_min_jint_string() { return _the_min_jint_string; } static methodOop finalizer_register_method() { return _finalizer_register_cache->get_methodOop(); } static methodOop loader_addClass_method() { return _loader_addClass_cache->get_methodOop(); } static ActiveMethodOopsCache* reflect_invoke_cache() { return _reflect_invoke_cache; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/constantPoolOop.cpp --- a/hotspot/src/share/vm/oops/constantPoolOop.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -262,25 +262,48 @@ int constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) { - jint ref_index = field_or_method_at(which, uncached); + int i = which; + if (!uncached && cache() != NULL) { + if (constantPoolCacheOopDesc::is_secondary_index(which)) + // Invokedynamic indexes are always processed in native order + // so there is no question of reading a native u2 in Java order here. + return cache()->main_entry_at(which)->constant_pool_index(); + // change byte-ordering and go via cache + i = remap_instruction_operand_from_cache(which); + } else { + if (tag_at(which).is_name_and_type()) + // invokedynamic index is a simple name-and-type + return which; + } + assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); + jint ref_index = *int_at_addr(i); return extract_high_short_from_int(ref_index); } int constantPoolOopDesc::impl_klass_ref_index_at(int which, bool uncached) { - jint ref_index = field_or_method_at(which, uncached); + guarantee(!constantPoolCacheOopDesc::is_secondary_index(which), + "an invokedynamic instruction does not have a klass"); + int i = which; + if (!uncached && cache() != NULL) { + // change byte-ordering and go via cache + i = remap_instruction_operand_from_cache(which); + } + assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); + jint ref_index = *int_at_addr(i); return extract_low_short_from_int(ref_index); } -int constantPoolOopDesc::map_instruction_operand_to_index(int operand) { - if (constantPoolCacheOopDesc::is_secondary_index(operand)) { - return cache()->main_entry_at(operand)->constant_pool_index(); - } +int constantPoolOopDesc::remap_instruction_operand_from_cache(int operand) { + // Operand was fetched by a stream using get_Java_u2, yet was stored + // by Rewriter::rewrite_member_reference in native order. + // So now we have to fix the damage by swapping back to native order. assert((int)(u2)operand == operand, "clean u2"); - int index = Bytes::swap_u2(operand); - return cache()->entry_at(index)->constant_pool_index(); + int cpc_index = Bytes::swap_u2(operand); + int member_index = cache()->entry_at(cpc_index)->constant_pool_index(); + return member_index; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/constantPoolOop.hpp --- a/hotspot/src/share/vm/oops/constantPoolOop.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -342,12 +342,14 @@ } // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, - // name_and_type_ref_index_at) all expect constant pool indices - // from the bytecodes to be passed in, which are actually potentially byte-swapped - // or rewritten constant pool cache indices. They all call map_instruction_operand_to_index. - int map_instruction_operand_to_index(int operand); + // name_and_type_ref_index_at) all expect to be passed indices obtained + // directly from the bytecode, and extracted according to java byte order. + // If the indices are meant to refer to fields or methods, they are + // actually potentially byte-swapped, rewritten constant pool cache indices. + // The routine remap_instruction_operand_from_cache manages the adjustment + // of these values back to constant pool indices. - // There are also "uncached" versions which do not map the operand index; see below. + // There are also "uncached" versions which do not adjust the operand index; see below. // Lookup for entries consisting of (klass_index, name_and_type index) klassOop klass_ref_at(int which, TRAPS); @@ -361,8 +363,6 @@ // Lookup for entries consisting of (name_index, signature_index) int name_ref_index_at(int which_nt); // == low-order jshort of name_and_type_at(which_nt) int signature_ref_index_at(int which_nt); // == high-order jshort of name_and_type_at(which_nt) - symbolOop nt_name_ref_at(int which_nt) { return symbol_at(name_ref_index_at(which_nt)); } - symbolOop nt_signature_ref_at(int which_nt) { return symbol_at(signature_ref_index_at(which_nt)); } BasicType basic_type_for_signature_at(int which); @@ -425,18 +425,7 @@ int impl_klass_ref_index_at(int which, bool uncached); int impl_name_and_type_ref_index_at(int which, bool uncached); - // Takes either a constant pool cache index in possibly byte-swapped - // byte order (which comes from the bytecodes after rewriting) or, - // if "uncached" is true, a vanilla constant pool index - jint field_or_method_at(int which, bool uncached) { - int i = which; - if (!uncached && cache() != NULL) { - // change byte-ordering and go via cache - i = map_instruction_operand_to_index(which); - } - assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); - return *int_at_addr(i); - } + int remap_instruction_operand_from_cache(int operand); // Used while constructing constant pool (only by ClassFileParser) jint klass_index_at(int which) { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/cpCacheOop.cpp --- a/hotspot/src/share/vm/oops/cpCacheOop.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -28,21 +28,17 @@ // Implememtation of ConstantPoolCacheEntry -void ConstantPoolCacheEntry::set_initial_state(int index) { - if (constantPoolCacheOopDesc::is_secondary_index(index)) { - // Hack: The rewriter is trying to say that this entry itself - // will be a secondary entry. - int main_index = constantPoolCacheOopDesc::decode_secondary_index(index); - assert(0 <= main_index && main_index < 0x10000, "sanity check"); - _indices = (main_index << 16); - assert(main_entry_index() == main_index, ""); - return; - } +void ConstantPoolCacheEntry::initialize_entry(int index) { assert(0 < index && index < 0x10000, "sanity check"); _indices = index; assert(constant_pool_index() == index, ""); } +void ConstantPoolCacheEntry::initialize_secondary_entry(int main_index) { + assert(0 <= main_index && main_index < 0x10000, "sanity check"); + _indices = (main_index << 16); + assert(main_entry_index() == main_index, ""); +} int ConstantPoolCacheEntry::as_flags(TosState state, bool is_final, bool is_vfinal, bool is_volatile, @@ -223,10 +219,10 @@ void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, int extra_data) { - methodOop method = (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site()); + methodOop method = (methodOop) java_dyn_CallSite::vmmethod(call_site()); assert(method->is_method(), "must be initialized properly"); int param_size = method->size_of_parameters(); - assert(param_size > 1, "method argument size must include MH.this & initial dynamic receiver"); + assert(param_size >= 1, "method argument size must include MH.this"); param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) { // racing threads might be trying to install their own favorites @@ -439,7 +435,18 @@ void constantPoolCacheOopDesc::initialize(intArray& inverse_index_map) { assert(inverse_index_map.length() == length(), "inverse index map must have same length as cache"); - for (int i = 0; i < length(); i++) entry_at(i)->set_initial_state(inverse_index_map[i]); + for (int i = 0; i < length(); i++) { + ConstantPoolCacheEntry* e = entry_at(i); + int original_index = inverse_index_map[i]; + if ((original_index & Rewriter::_secondary_entry_tag) != 0) { + int main_index = (original_index - Rewriter::_secondary_entry_tag); + assert(!entry_at(main_index)->is_secondary_entry(), "valid main index"); + e->initialize_secondary_entry(main_index); + } else { + e->initialize_entry(original_index); + } + assert(entry_at(i) == e, "sanity"); + } } // RedefineClasses() API support: diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/cpCacheOop.hpp --- a/hotspot/src/share/vm/oops/cpCacheOop.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -154,7 +154,8 @@ }; // Initialization - void set_initial_state(int index); // sets entry to initial state + void initialize_entry(int original_index); // initialize primary entry + void initialize_secondary_entry(int main_index); // initialize secondary entry void set_field( // sets entry to resolved field state Bytecodes::Code get_code, // the bytecode used for reading the field @@ -251,6 +252,7 @@ // Code generation support static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); } + static ByteSize size_in_bytes() { return in_ByteSize(sizeof(ConstantPoolCacheEntry)); } static ByteSize indices_offset() { return byte_offset_of(ConstantPoolCacheEntry, _indices); } static ByteSize f1_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f1); } static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); } @@ -321,6 +323,7 @@ ConstantPoolCacheEntry* base() const { return (ConstantPoolCacheEntry*)((address)this + in_bytes(base_offset())); } friend class constantPoolCacheKlass; + friend class ConstantPoolCacheEntry; public: // Initialization @@ -329,7 +332,8 @@ // Secondary indexes. // They must look completely different from normal indexes. // The main reason is that byte swapping is sometimes done on normal indexes. - // Also, it is helpful for debugging to tell the two apart. + // Also, some of the CP accessors do different things for secondary indexes. + // Finally, it is helpful for debugging to tell the two apart. static bool is_secondary_index(int i) { return (i < 0); } static int decode_secondary_index(int i) { assert(is_secondary_index(i), ""); return ~i; } static int encode_secondary_index(int i) { assert(!is_secondary_index(i), ""); return ~i; } @@ -337,18 +341,35 @@ // Accessors void set_constant_pool(constantPoolOop pool) { oop_store_without_check((oop*)&_constant_pool, (oop)pool); } constantPoolOop constant_pool() const { return _constant_pool; } - ConstantPoolCacheEntry* entry_at(int i) const { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; } + // Fetches the entry at the given index. + // The entry may be either primary or secondary. + // In either case the index must not be encoded or byte-swapped in any way. + ConstantPoolCacheEntry* entry_at(int i) const { + assert(0 <= i && i < length(), "index out of bounds"); + return base() + i; + } + // Fetches the secondary entry referred to by index. + // The index may be a secondary index, and must not be byte-swapped. + ConstantPoolCacheEntry* secondary_entry_at(int i) const { + int raw_index = i; + if (is_secondary_index(i)) { // correct these on the fly + raw_index = decode_secondary_index(i); + } + assert(entry_at(raw_index)->is_secondary_entry(), "not a secondary entry"); + return entry_at(raw_index); + } + // Given a primary or secondary index, fetch the corresponding primary entry. + // Indirect through the secondary entry, if the index is encoded as a secondary index. + // The index must not be byte-swapped. ConstantPoolCacheEntry* main_entry_at(int i) const { - ConstantPoolCacheEntry* e; + int primary_index = i; if (is_secondary_index(i)) { // run through an extra level of indirection: - i = decode_secondary_index(i); - e = entry_at(i); - i = e->main_entry_index(); + int raw_index = decode_secondary_index(i); + primary_index = entry_at(raw_index)->main_entry_index(); } - e = entry_at(i); - assert(!e->is_secondary_entry(), "only one level of indirection"); - return e; + assert(!entry_at(primary_index)->is_secondary_entry(), "only one level of indirection"); + return entry_at(primary_index); } // GC support @@ -359,6 +380,12 @@ // Code generation static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); } + static ByteSize entry_offset(int raw_index) { + int index = raw_index; + if (is_secondary_index(raw_index)) + index = decode_secondary_index(raw_index); + return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index); + } // RedefineClasses() API support: // If any entry of this constantPoolCache points to any of diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/generateOopMap.cpp --- a/hotspot/src/share/vm/oops/generateOopMap.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/generateOopMap.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1556,13 +1556,13 @@ case Bytecodes::_getfield: do_field(true, false, itr->get_index_big(), itr->bci()); break; case Bytecodes::_putfield: do_field(false, false, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_invokevirtual: - case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_invokedynamic: do_method(false, true, itr->get_index_int(), itr->bci()); break; - case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; - case Bytecodes::_newarray: - case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; + case Bytecodes::_invokevirtual: + case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_invokedynamic: do_method(true, false, itr->get_index_int(), itr->bci()); break; + case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break; + case Bytecodes::_newarray: + case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break; case Bytecodes::_checkcast: do_checkcast(); break; case Bytecodes::_arraylength: case Bytecodes::_instanceof: pp(rCTS, vCTS); break; @@ -1900,11 +1900,9 @@ } void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) { - // Dig up signature for field in constant pool - constantPoolOop cp = _method->constants(); - int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx); - int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); // @@@@@ - symbolOop signature = cp->symbol_at(signatureIdx); + // Dig up signature for field in constant pool + constantPoolOop cp = _method->constants(); + symbolOop signature = cp->signature_ref_at(idx); // Parse method signature CellTypeState out[4]; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -2045,8 +2045,9 @@ // As we walk along, look for equalities between outer1 and class2. // Eventually, the walks will terminate as outer1 stops // at the top-level class around the original class. - symbolOop ignore_name; - klassOop next = outer1->compute_enclosing_class(ignore_name, CHECK_false); + bool ignore_inner_is_member; + klassOop next = outer1->compute_enclosing_class(&ignore_inner_is_member, + CHECK_false); if (next == NULL) break; if (next == class2()) return true; outer1 = instanceKlassHandle(THREAD, next); @@ -2055,8 +2056,9 @@ // Now do the same for class2. instanceKlassHandle outer2 = class2; for (;;) { - symbolOop ignore_name; - klassOop next = outer2->compute_enclosing_class(ignore_name, CHECK_false); + bool ignore_inner_is_member; + klassOop next = outer2->compute_enclosing_class(&ignore_inner_is_member, + CHECK_false); if (next == NULL) break; // Might as well check the new outer against all available values. if (next == class1()) return true; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -337,12 +337,12 @@ static bool is_same_class_package(oop class_loader1, symbolOop class_name1, oop class_loader2, symbolOop class_name2); // find an enclosing class (defined where original code was, in jvm.cpp!) - klassOop compute_enclosing_class(symbolOop& simple_name_result, TRAPS) { + klassOop compute_enclosing_class(bool* inner_is_member, TRAPS) { instanceKlassHandle self(THREAD, this->as_klassOop()); - return compute_enclosing_class_impl(self, simple_name_result, THREAD); + return compute_enclosing_class_impl(self, inner_is_member, THREAD); } static klassOop compute_enclosing_class_impl(instanceKlassHandle self, - symbolOop& simple_name_result, TRAPS); + bool* inner_is_member, TRAPS); // tell if two classes have the same enclosing class (at package level) bool is_same_package_member(klassOop class2, TRAPS) { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/instanceKlassKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -317,6 +317,11 @@ pm->claim_or_forward_breadth(sg_addr); } + oop* bsm_addr = ik->adr_bootstrap_method(); + if (PSScavenge::should_scavenge(bsm_addr)) { + pm->claim_or_forward_breadth(bsm_addr); + } + klassKlass::oop_copy_contents(pm, obj); } @@ -345,6 +350,11 @@ pm->claim_or_forward_depth(sg_addr); } + oop* bsm_addr = ik->adr_bootstrap_method(); + if (PSScavenge::should_scavenge(bsm_addr)) { + pm->claim_or_forward_depth(bsm_addr); + } + klassKlass::oop_copy_contents(pm, obj); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/instanceRefKlass.cpp --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -78,9 +78,9 @@ #ifndef SERIALGC template -static void specialized_oop_follow_contents(instanceRefKlass* ref, - ParCompactionManager* cm, - oop obj) { +void specialized_oop_follow_contents(instanceRefKlass* ref, + ParCompactionManager* cm, + oop obj) { T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); T heap_oop = oopDesc::load_heap_oop(referent_addr); debug_only( diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/objArrayKlass.cpp --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -127,16 +127,14 @@ // pointer delta is scaled to number of elements (length field in // objArrayOop) which we assume is 32 bit. assert(pd == (size_t)(int)pd, "length field overflow"); - const size_t done_word_len = objArrayOopDesc::array_size((int)pd); - bs->write_ref_array(MemRegion((HeapWord*)dst, done_word_len)); + bs->write_ref_array((HeapWord*)dst, pd); THROW(vmSymbols::java_lang_ArrayStoreException()); return; } } } } - const size_t word_len = objArrayOopDesc::array_size(length); - bs->write_ref_array(MemRegion((HeapWord*)dst, word_len)); + bs->write_ref_array((HeapWord*)dst, length); } void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/objArrayOop.hpp --- a/hotspot/src/share/vm/oops/objArrayOop.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/objArrayOop.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -37,6 +37,32 @@ return &((T*)base())[index]; } +private: + // Give size of objArrayOop in HeapWords minus the header + static int array_size(int length) { + const int OopsPerHeapWord = HeapWordSize/heapOopSize; + assert(OopsPerHeapWord >= 1 && (HeapWordSize % heapOopSize == 0), + "Else the following (new) computation would be in error"); +#ifdef ASSERT + // The old code is left in for sanity-checking; it'll + // go away pretty soon. XXX + // Without UseCompressedOops, this is simply: + // oop->length() * HeapWordsPerOop; + // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer. + // The oop elements are aligned up to wordSize + const int HeapWordsPerOop = heapOopSize/HeapWordSize; + int old_res; + if (HeapWordsPerOop > 0) { + old_res = length * HeapWordsPerOop; + } else { + old_res = align_size_up(length, OopsPerHeapWord)/OopsPerHeapWord; + } +#endif // ASSERT + int res = ((uint)length + OopsPerHeapWord - 1)/OopsPerHeapWord; + assert(res == old_res, "Inconsistency between old and new."); + return res; + } + public: // Returns the offset of the first element. static int base_offset_in_bytes() { @@ -67,27 +93,14 @@ // Sizing static int header_size() { return arrayOopDesc::header_size(T_OBJECT); } int object_size() { return object_size(length()); } - int array_size() { return array_size(length()); } static int object_size(int length) { // This returns the object size in HeapWords. - return align_object_size(header_size() + array_size(length)); - } - - // Give size of objArrayOop in HeapWords minus the header - static int array_size(int length) { - // Without UseCompressedOops, this is simply: - // oop->length() * HeapWordsPerOop; - // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer. - // The oop elements are aligned up to wordSize - const int HeapWordsPerOop = heapOopSize/HeapWordSize; - if (HeapWordsPerOop > 0) { - return length * HeapWordsPerOop; - } else { - const int OopsPerHeapWord = HeapWordSize/heapOopSize; - int word_len = align_size_up(length, OopsPerHeapWord)/OopsPerHeapWord; - return word_len; - } + uint asz = array_size(length); + uint osz = align_object_size(header_size() + asz); + assert(osz >= asz, "no overflow"); + assert((int)osz > 0, "no overflow"); + return (int)osz; } // special iterators for index ranges, returns size of object diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/oops/oop.hpp --- a/hotspot/src/share/vm/oops/oop.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/oops/oop.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -30,13 +30,12 @@ // no virtual functions allowed // store into oop with store check -template void oop_store(T* p, oop v); -template void oop_store(volatile T* p, oop v); +template inline void oop_store(T* p, oop v); +template inline void oop_store(volatile T* p, oop v); // store into oop without store check -template void oop_store_without_check(T* p, oop v); -template void oop_store_without_check(volatile T* p, oop v); - +template inline void oop_store_without_check(T* p, oop v); +template inline void oop_store_without_check(volatile T* p, oop v); extern bool always_do_update_barrier; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/c2_globals.cpp --- a/hotspot/src/share/vm/opto/c2_globals.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/c2_globals.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -25,4 +25,4 @@ # include "incls/_precompiled.incl" # include "incls/_c2_globals.cpp.incl" -C2_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG) +C2_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, MATERIALIZE_NOTPRODUCT_FLAG) diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/c2_globals.hpp --- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/c2_globals.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -26,7 +26,7 @@ // Defines all globals flags used by the server compiler. // -#define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \ +#define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct) \ \ notproduct(intx, CompileZapFirst, 0, \ "If +ZapDeadCompiledLocals, " \ @@ -394,6 +394,12 @@ product(bool, UseOptoBiasInlining, true, \ "Generate biased locking code in C2 ideal graph") \ \ + product(bool, OptimizeStringConcat, false, \ + "Optimize the construction of Strings by StringBuilder") \ + \ + notproduct(bool, PrintOptimizeStringConcat, false, \ + "Print information about transformations performed on Strings") \ + \ product(intx, ValueSearchLimit, 1000, \ "Recursion limit in PhaseMacroExpand::value_from_mem_phi") \ \ @@ -413,4 +419,4 @@ product(bool, BlockLayoutRotateLoops, true, \ "Allow back branches to be fall throughs in the block layour") \ -C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG) +C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG) diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/callGenerator.cpp --- a/hotspot/src/share/vm/opto/callGenerator.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/callGenerator.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -98,12 +98,21 @@ //---------------------------DirectCallGenerator------------------------------ // Internal class which handles all out-of-line calls w/o receiver type checks. class DirectCallGenerator : public CallGenerator { -public: - DirectCallGenerator(ciMethod* method) - : CallGenerator(method) + private: + CallStaticJavaNode* _call_node; + // Force separate memory and I/O projections for the exceptional + // paths to facilitate late inlinig. + bool _separate_io_proj; + + public: + DirectCallGenerator(ciMethod* method, bool separate_io_proj) + : CallGenerator(method), + _separate_io_proj(separate_io_proj) { } virtual JVMState* generate(JVMState* jvms); + + CallStaticJavaNode* call_node() const { return _call_node; } }; JVMState* DirectCallGenerator::generate(JVMState* jvms) { @@ -129,9 +138,10 @@ call->set_optimized_virtual(true); } kit.set_arguments_for_java_call(call); - kit.set_edges_for_java_call(call); - Node* ret = kit.set_results_for_java_call(call); + kit.set_edges_for_java_call(call, false, _separate_io_proj); + Node* ret = kit.set_results_for_java_call(call, _separate_io_proj); kit.push_node(method()->return_type()->basic_type(), ret); + _call_node = call; // Save the call node in case we need it later return kit.transfer_exceptions_into_jvms(); } @@ -238,9 +248,9 @@ return new ParseGenerator(m, expected_uses, true); } -CallGenerator* CallGenerator::for_direct_call(ciMethod* m) { +CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { assert(!m->is_abstract(), "for_direct_call mismatch"); - return new DirectCallGenerator(m); + return new DirectCallGenerator(m, separate_io_proj); } CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { @@ -248,6 +258,108 @@ return new VirtualCallGenerator(m, vtable_index); } +// Allow inlining decisions to be delayed +class LateInlineCallGenerator : public DirectCallGenerator { + CallGenerator* _inline_cg; + + public: + LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : + DirectCallGenerator(method, true), _inline_cg(inline_cg) {} + + virtual bool is_late_inline() const { return true; } + + // Convert the CallStaticJava into an inline + virtual void do_late_inline(); + + JVMState* generate(JVMState* jvms) { + // Record that this call site should be revisited once the main + // parse is finished. + Compile::current()->add_late_inline(this); + + // Emit the CallStaticJava and request separate projections so + // that the late inlining logic can distinguish between fall + // through and exceptional uses of the memory and io projections + // as is done for allocations and macro expansion. + return DirectCallGenerator::generate(jvms); + } + +}; + + +void LateInlineCallGenerator::do_late_inline() { + // Can't inline it + if (call_node() == NULL || call_node()->outcnt() == 0 || + call_node()->in(0) == NULL || call_node()->in(0)->is_top()) + return; + + CallStaticJavaNode* call = call_node(); + + // Make a clone of the JVMState that appropriate to use for driving a parse + Compile* C = Compile::current(); + JVMState* jvms = call->jvms()->clone_shallow(C); + uint size = call->req(); + SafePointNode* map = new (C, size) SafePointNode(size, jvms); + for (uint i1 = 0; i1 < size; i1++) { + map->init_req(i1, call->in(i1)); + } + + // Make sure the state is a MergeMem for parsing. + if (!map->in(TypeFunc::Memory)->is_MergeMem()) { + map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory))); + } + + // Make enough space for the expression stack and transfer the incoming arguments + int nargs = method()->arg_size(); + jvms->set_map(map); + map->ensure_stack(jvms, jvms->method()->max_stack()); + if (nargs > 0) { + for (int i1 = 0; i1 < nargs; i1++) { + map->set_req(i1 + jvms->argoff(), call->in(TypeFunc::Parms + i1)); + } + } + + CompileLog* log = C->log(); + if (log != NULL) { + log->head("late_inline method='%d'", log->identify(method())); + JVMState* p = jvms; + while (p != NULL) { + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); + p = p->caller(); + } + log->tail("late_inline"); + } + + // Setup default node notes to be picked up by the inlining + Node_Notes* old_nn = C->default_node_notes(); + if (old_nn != NULL) { + Node_Notes* entry_nn = old_nn->clone(C); + entry_nn->set_jvms(jvms); + C->set_default_node_notes(entry_nn); + } + + // Now perform the inling using the synthesized JVMState + JVMState* new_jvms = _inline_cg->generate(jvms); + if (new_jvms == NULL) return; // no change + if (C->failing()) return; + + // Capture any exceptional control flow + GraphKit kit(new_jvms); + + // Find the result object + Node* result = C->top(); + int result_size = method()->return_type()->size(); + if (result_size != 0 && !kit.stopped()) { + result = (result_size == 1) ? kit.pop() : kit.pop_pair(); + } + + kit.replace_call(call, result); +} + + +CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) { + return new LateInlineCallGenerator(method, inline_cg); +} + //---------------------------WarmCallGenerator-------------------------------- // Internal class which handles initial deferral of inlining decisions. @@ -315,70 +427,7 @@ } void WarmCallInfo::make_hot() { - Compile* C = Compile::current(); - // Replace the callnode with something better. - CallJavaNode* call = this->call()->as_CallJava(); - ciMethod* method = call->method(); - int nargs = method->arg_size(); - JVMState* jvms = call->jvms()->clone_shallow(C); - uint size = TypeFunc::Parms + MAX2(2, nargs); - SafePointNode* map = new (C, size) SafePointNode(size, jvms); - for (uint i1 = 0; i1 < (uint)(TypeFunc::Parms + nargs); i1++) { - map->init_req(i1, call->in(i1)); - } - jvms->set_map(map); - jvms->set_offsets(map->req()); - jvms->set_locoff(TypeFunc::Parms); - jvms->set_stkoff(TypeFunc::Parms); - GraphKit kit(jvms); - - JVMState* new_jvms = _hot_cg->generate(kit.jvms()); - if (new_jvms == NULL) return; // no change - if (C->failing()) return; - - kit.set_jvms(new_jvms); - Node* res = C->top(); - int res_size = method->return_type()->size(); - if (res_size != 0) { - kit.inc_sp(-res_size); - res = kit.argument(0); - } - GraphKit ekit(kit.combine_and_pop_all_exception_states()->jvms()); - - // Replace the call: - for (DUIterator i = call->outs(); call->has_out(i); i++) { - Node* n = call->out(i); - Node* nn = NULL; // replacement - if (n->is_Proj()) { - ProjNode* nproj = n->as_Proj(); - assert(nproj->_con < (uint)(TypeFunc::Parms + (res_size ? 1 : 0)), "sane proj"); - if (nproj->_con == TypeFunc::Parms) { - nn = res; - } else { - nn = kit.map()->in(nproj->_con); - } - if (nproj->_con == TypeFunc::I_O) { - for (DUIterator j = nproj->outs(); nproj->has_out(j); j++) { - Node* e = nproj->out(j); - if (e->Opcode() == Op_CreateEx) { - e->replace_by(ekit.argument(0)); - } else if (e->Opcode() == Op_Catch) { - for (DUIterator k = e->outs(); e->has_out(k); k++) { - CatchProjNode* p = e->out(j)->as_CatchProj(); - if (p->is_handler_proj()) { - p->replace_by(ekit.control()); - } else { - p->replace_by(kit.control()); - } - } - } - } - } - } - NOT_PRODUCT(if (!nn) n->dump(2)); - assert(nn != NULL, "don't know what to do with this user"); - n->replace_by(nn); - } + Unimplemented(); } void WarmCallInfo::make_cold() { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/callGenerator.hpp --- a/hotspot/src/share/vm/opto/callGenerator.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/callGenerator.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -57,6 +57,13 @@ // is_trap: Does not return to the caller. (E.g., uncommon trap.) virtual bool is_trap() const { return false; } + // is_late_inline: supports conversion of call into an inline + virtual bool is_late_inline() const { return false; } + // Replace the call with an inline version of the code + virtual void do_late_inline() { ShouldNotReachHere(); } + + virtual CallStaticJavaNode* call_node() const { ShouldNotReachHere(); return NULL; } + // Note: It is possible for a CG to be both inline and virtual. // (The hashCode intrinsic does a vtable check and an inlined fast path.) @@ -92,9 +99,12 @@ static CallGenerator* for_osr(ciMethod* m, int osr_bci); // How to generate vanilla out-of-line call sites: - static CallGenerator* for_direct_call(ciMethod* m); // static, special + static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false); // static, special static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface + // How to generate a replace a direct call with an inline version + static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg); + // How to make a call but defer the decision whether to inline or not. static CallGenerator* for_warm_call(WarmCallInfo* ci, CallGenerator* if_cold, diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/callnode.cpp --- a/hotspot/src/share/vm/opto/callnode.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/callnode.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -693,6 +693,84 @@ } +void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj) { + projs->fallthrough_proj = NULL; + projs->fallthrough_catchproj = NULL; + projs->fallthrough_ioproj = NULL; + projs->catchall_ioproj = NULL; + projs->catchall_catchproj = NULL; + projs->fallthrough_memproj = NULL; + projs->catchall_memproj = NULL; + projs->resproj = NULL; + projs->exobj = NULL; + + for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) { + ProjNode *pn = fast_out(i)->as_Proj(); + if (pn->outcnt() == 0) continue; + switch (pn->_con) { + case TypeFunc::Control: + { + // For Control (fallthrough) and I_O (catch_all_index) we have CatchProj -> Catch -> Proj + projs->fallthrough_proj = pn; + DUIterator_Fast jmax, j = pn->fast_outs(jmax); + const Node *cn = pn->fast_out(j); + if (cn->is_Catch()) { + ProjNode *cpn = NULL; + for (DUIterator_Fast kmax, k = cn->fast_outs(kmax); k < kmax; k++) { + cpn = cn->fast_out(k)->as_Proj(); + assert(cpn->is_CatchProj(), "must be a CatchProjNode"); + if (cpn->_con == CatchProjNode::fall_through_index) + projs->fallthrough_catchproj = cpn; + else { + assert(cpn->_con == CatchProjNode::catch_all_index, "must be correct index."); + projs->catchall_catchproj = cpn; + } + } + } + break; + } + case TypeFunc::I_O: + if (pn->_is_io_use) + projs->catchall_ioproj = pn; + else + projs->fallthrough_ioproj = pn; + for (DUIterator j = pn->outs(); pn->has_out(j); j++) { + Node* e = pn->out(j); + if (e->Opcode() == Op_CreateEx && e->in(0)->is_CatchProj()) { + assert(projs->exobj == NULL, "only one"); + projs->exobj = e; + } + } + break; + case TypeFunc::Memory: + if (pn->_is_io_use) + projs->catchall_memproj = pn; + else + projs->fallthrough_memproj = pn; + break; + case TypeFunc::Parms: + projs->resproj = pn; + break; + default: + assert(false, "unexpected projection from allocation node."); + } + } + + // The resproj may not exist because the result couuld be ignored + // and the exception object may not exist if an exception handler + // swallows the exception but all the other must exist and be found. + assert(projs->fallthrough_proj != NULL, "must be found"); + assert(projs->fallthrough_catchproj != NULL, "must be found"); + assert(projs->fallthrough_memproj != NULL, "must be found"); + assert(projs->fallthrough_ioproj != NULL, "must be found"); + assert(projs->catchall_catchproj != NULL, "must be found"); + if (separate_io_proj) { + assert(projs->catchall_memproj != NULL, "must be found"); + assert(projs->catchall_ioproj != NULL, "must be found"); + } +} + + //============================================================================= uint CallJavaNode::size_of() const { return sizeof(*this); } uint CallJavaNode::cmp( const Node &n ) const { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/callnode.hpp --- a/hotspot/src/share/vm/opto/callnode.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/callnode.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -470,6 +470,23 @@ #endif }; + +// Simple container for the outgoing projections of a call. Useful +// for serious surgery on calls. +class CallProjections : public StackObj { +public: + Node* fallthrough_proj; + Node* fallthrough_catchproj; + Node* fallthrough_memproj; + Node* fallthrough_ioproj; + Node* catchall_catchproj; + Node* catchall_memproj; + Node* catchall_ioproj; + Node* resproj; + Node* exobj; +}; + + //------------------------------CallNode--------------------------------------- // Call nodes now subsume the function of debug nodes at callsites, so they // contain the functionality of a full scope chain of debug nodes. @@ -521,6 +538,11 @@ // or returns NULL if there is no one. Node *result_cast(); + // Collect all the interesting edges from a call for use in + // replacing the call by something else. Used by macro expansion + // and the late inlining support. + void extract_projections(CallProjections* projs, bool separate_io_proj); + virtual uint match_edge(uint idx) const; #ifndef PRODUCT @@ -529,6 +551,7 @@ #endif }; + //------------------------------CallJavaNode----------------------------------- // Make a static or dynamic subroutine call node using Java calling // convention. (The "Java" calling convention is the compiler's calling diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -224,6 +224,32 @@ } +void Compile::gvn_replace_by(Node* n, Node* nn) { + for (DUIterator_Last imin, i = n->last_outs(imin); i >= imin; ) { + Node* use = n->last_out(i); + bool is_in_table = initial_gvn()->hash_delete(use); + uint uses_found = 0; + for (uint j = 0; j < use->len(); j++) { + if (use->in(j) == n) { + if (j < use->req()) + use->set_req(j, nn); + else + use->set_prec(j, nn); + uses_found++; + } + } + if (is_in_table) { + // reinsert into table + initial_gvn()->hash_find_insert(use); + } + record_for_igvn(use); + i -= uses_found; // we deleted 1 or more copies of this edge + } +} + + + + // Identify all nodes that are reachable from below, useful. // Use breadth-first pass that records state in a Unique_Node_List, // recursive traversal is slower. @@ -554,6 +580,28 @@ rethrow_exceptions(kit.transfer_exceptions_into_jvms()); } + if (!failing() && has_stringbuilder()) { + { + // remove useless nodes to make the usage analysis simpler + ResourceMark rm; + PhaseRemoveUseless pru(initial_gvn(), &for_igvn); + } + + { + ResourceMark rm; + print_method("Before StringOpts", 3); + PhaseStringOpts pso(initial_gvn(), &for_igvn); + print_method("After StringOpts", 3); + } + + // now inline anything that we skipped the first time around + while (_late_inlines.length() > 0) { + CallGenerator* cg = _late_inlines.pop(); + cg->do_late_inline(); + } + } + assert(_late_inlines.length() == 0, "should have been processed"); + print_method("Before RemoveUseless", 3); // Remove clutter produced by parsing. @@ -820,6 +868,7 @@ _fixed_slots = 0; set_has_split_ifs(false); set_has_loops(has_method() && method()->has_loops()); // first approximation + set_has_stringbuilder(false); _deopt_happens = true; // start out assuming the worst _trap_can_recompile = false; // no traps emitted yet _major_progress = true; // start out assuming good things will happen @@ -1803,6 +1852,7 @@ !n->is_Phi() && // a few noisely useless nodes !n->is_Proj() && !n->is_MachTemp() && + !n->is_SafePointScalarObject() && !n->is_Catch() && // Would be nice to print exception table targets !n->is_MergeMem() && // Not very interesting !n->is_top() && // Debug info table constants @@ -2240,6 +2290,30 @@ break; } + case Op_Proj: { + if (OptimizeStringConcat) { + ProjNode* p = n->as_Proj(); + if (p->_is_io_use) { + // Separate projections were used for the exception path which + // are normally removed by a late inline. If it wasn't inlined + // then they will hang around and should just be replaced with + // the original one. + Node* proj = NULL; + // Replace with just one + for (SimpleDUIterator i(p->in(0)); i.has_next(); i.next()) { + Node *use = i.get(); + if (use->is_Proj() && p != use && use->as_Proj()->_con == p->_con) { + proj = use; + break; + } + } + assert(p != NULL, "must be found"); + p->subsume_by(proj); + } + } + break; + } + case Op_Phi: if (n->as_Phi()->bottom_type()->isa_narrowoop()) { // The EncodeP optimization may create Phi with the same edges diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -149,6 +149,7 @@ bool _has_loops; // True if the method _may_ have some loops bool _has_split_ifs; // True if the method _may_ have some split-if bool _has_unsafe_access; // True if the method _may_ produce faults in unsafe loads or stores. + bool _has_stringbuilder; // True StringBuffers or StringBuilders are allocated uint _trap_hist[trapHistLength]; // Cumulative traps bool _trap_can_recompile; // Have we emitted a recompiling trap? uint _decompile_count; // Cumulative decompilation counts. @@ -219,6 +220,9 @@ Unique_Node_List* _for_igvn; // Initial work-list for next round of Iterative GVN WarmCallInfo* _warm_calls; // Sorted work-list for heat-based inlining. + GrowableArray _late_inlines; // List of CallGenerators to be revisited after + // main parsing has finished. + // Matching, CFG layout, allocation, code generation PhaseCFG* _cfg; // Results of CFG finding bool _select_24_bit_instr; // We selected an instruction with a 24-bit result @@ -298,6 +302,8 @@ void set_has_split_ifs(bool z) { _has_split_ifs = z; } bool has_unsafe_access() const { return _has_unsafe_access; } void set_has_unsafe_access(bool z) { _has_unsafe_access = z; } + bool has_stringbuilder() const { return _has_stringbuilder; } + void set_has_stringbuilder(bool z) { _has_stringbuilder = z; } void set_trap_count(uint r, uint c) { assert(r < trapHistLength, "oob"); _trap_hist[r] = c; } uint trap_count(uint r) const { assert(r < trapHistLength, "oob"); return _trap_hist[r]; } bool trap_can_recompile() const { return _trap_can_recompile; } @@ -475,6 +481,7 @@ // Decide how to build a call. // The profile factor is a discount to apply to this site's interp. profile. CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, JVMState* jvms, bool allow_inline, float profile_factor); + bool should_delay_inlining(ciMethod* call_method, JVMState* jvms); // Report if there were too many traps at a current method and bci. // Report if a trap was recorded, and/or PerMethodTrapLimit was exceeded. @@ -495,6 +502,11 @@ void set_initial_gvn(PhaseGVN *gvn) { _initial_gvn = gvn; } void set_for_igvn(Unique_Node_List *for_igvn) { _for_igvn = for_igvn; } + // Replace n by nn using initial_gvn, calling hash_delete and + // record_for_igvn as needed. + void gvn_replace_by(Node* n, Node* nn); + + void identify_useful_nodes(Unique_Node_List &useful); void remove_useless_nodes (Unique_Node_List &useful); @@ -502,6 +514,9 @@ void set_warm_calls(WarmCallInfo* l) { _warm_calls = l; } WarmCallInfo* pop_warm_call(); + // Record this CallGenerator for inlining at the end of parsing. + void add_late_inline(CallGenerator* cg) { _late_inlines.push(cg); } + // Matching, CFG layout, allocation, code generation PhaseCFG* cfg() { return _cfg; } bool select_24_bit_instr() const { return _select_24_bit_instr; } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/doCall.cpp --- a/hotspot/src/share/vm/opto/doCall.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/doCall.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -128,6 +128,12 @@ if (allow_inline) { CallGenerator* cg = CallGenerator::for_inline(call_method, expected_uses); + if (require_inline && cg != NULL && should_delay_inlining(call_method, jvms)) { + // Delay the inlining of this method to give us the + // opportunity to perform some high level optimizations + // first. + return CallGenerator::for_late_inline(call_method, cg); + } if (cg == NULL) { // Fall through. } else if (require_inline || !InlineWarmCalls) { @@ -225,10 +231,63 @@ } else { // Class Hierarchy Analysis or Type Profile reveals a unique target, // or it is a static or special call. - return CallGenerator::for_direct_call(call_method); + return CallGenerator::for_direct_call(call_method, should_delay_inlining(call_method, jvms)); } } +// Return true for methods that shouldn't be inlined early so that +// they are easier to analyze and optimize as intrinsics. +bool Compile::should_delay_inlining(ciMethod* call_method, JVMState* jvms) { + if (has_stringbuilder()) { + + if ((call_method->holder() == C->env()->StringBuilder_klass() || + call_method->holder() == C->env()->StringBuffer_klass()) && + (jvms->method()->holder() == C->env()->StringBuilder_klass() || + jvms->method()->holder() == C->env()->StringBuffer_klass())) { + // Delay SB calls only when called from non-SB code + return false; + } + + switch (call_method->intrinsic_id()) { + case vmIntrinsics::_StringBuilder_void: + case vmIntrinsics::_StringBuilder_int: + case vmIntrinsics::_StringBuilder_String: + case vmIntrinsics::_StringBuilder_append_char: + case vmIntrinsics::_StringBuilder_append_int: + case vmIntrinsics::_StringBuilder_append_String: + case vmIntrinsics::_StringBuilder_toString: + case vmIntrinsics::_StringBuffer_void: + case vmIntrinsics::_StringBuffer_int: + case vmIntrinsics::_StringBuffer_String: + case vmIntrinsics::_StringBuffer_append_char: + case vmIntrinsics::_StringBuffer_append_int: + case vmIntrinsics::_StringBuffer_append_String: + case vmIntrinsics::_StringBuffer_toString: + case vmIntrinsics::_Integer_toString: + return true; + + case vmIntrinsics::_String_String: + { + Node* receiver = jvms->map()->in(jvms->argoff() + 1); + if (receiver->is_Proj() && receiver->in(0)->is_CallStaticJava()) { + CallStaticJavaNode* csj = receiver->in(0)->as_CallStaticJava(); + ciMethod* m = csj->method(); + if (m != NULL && + (m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString || + m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString)) + // Delay String.(new SB()) + return true; + } + return false; + } + + default: + return false; + } + } + return false; +} + // uncommon-trap call-sites where callee is unloaded, uninitialized or will not link bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* klass) { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -537,11 +537,13 @@ } const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr(); - // Do NOT remove the next call: ensure an new alias index is allocated - // for the instance type + // Do NOT remove the next line: ensure a new alias index is allocated + // for the instance type. Note: C++ will not remove it since the call + // has side effect. int alias_idx = _compile->get_alias_index(tinst); igvn->set_type(addp, tinst); // record the allocation in the node map + assert(ptnode_adr(addp->_idx)->_node != NULL, "should be registered"); set_map(addp->_idx, get_map(base->_idx)); // Set addp's Base and Address to 'base'. @@ -617,9 +619,14 @@ const TypePtr *atype = C->get_adr_type(alias_idx); result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype); C->copy_node_notes_to(result, orig_phi); - set_map_phi(orig_phi->_idx, result); igvn->set_type(result, result->bottom_type()); record_for_optimizer(result); + + debug_only(Node* pn = ptnode_adr(orig_phi->_idx)->_node;) + assert(pn == NULL || pn == orig_phi, "wrong node"); + set_map(orig_phi->_idx, result); + ptnode_adr(orig_phi->_idx)->_node = orig_phi; + new_created = true; return result; } @@ -710,6 +717,81 @@ } // +// Move memory users to their memory slices. +// +void ConnectionGraph::move_inst_mem(Node* n, GrowableArray &orig_phis, PhaseGVN *igvn) { + Compile* C = _compile; + + const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr(); + assert(tp != NULL, "ptr type"); + int alias_idx = C->get_alias_index(tp); + int general_idx = C->get_general_index(alias_idx); + + // Move users first + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* use = n->fast_out(i); + if (use->is_MergeMem()) { + MergeMemNode* mmem = use->as_MergeMem(); + assert(n == mmem->memory_at(alias_idx), "should be on instance memory slice"); + if (n != mmem->memory_at(general_idx) || alias_idx == general_idx) { + continue; // Nothing to do + } + // Replace previous general reference to mem node. + uint orig_uniq = C->unique(); + Node* m = find_inst_mem(n, general_idx, orig_phis, igvn); + assert(orig_uniq == C->unique(), "no new nodes"); + mmem->set_memory_at(general_idx, m); + --imax; + --i; + } else if (use->is_MemBar()) { + assert(!use->is_Initialize(), "initializing stores should not be moved"); + if (use->req() > MemBarNode::Precedent && + use->in(MemBarNode::Precedent) == n) { + // Don't move related membars. + record_for_optimizer(use); + continue; + } + tp = use->as_MemBar()->adr_type()->isa_ptr(); + if (tp != NULL && C->get_alias_index(tp) == alias_idx || + alias_idx == general_idx) { + continue; // Nothing to do + } + // Move to general memory slice. + uint orig_uniq = C->unique(); + Node* m = find_inst_mem(n, general_idx, orig_phis, igvn); + assert(orig_uniq == C->unique(), "no new nodes"); + igvn->hash_delete(use); + imax -= use->replace_edge(n, m); + igvn->hash_insert(use); + record_for_optimizer(use); + --i; +#ifdef ASSERT + } else if (use->is_Mem()) { + if (use->Opcode() == Op_StoreCM && use->in(MemNode::OopStore) == n) { + // Don't move related cardmark. + continue; + } + // Memory nodes should have new memory input. + tp = igvn->type(use->in(MemNode::Address))->isa_ptr(); + assert(tp != NULL, "ptr type"); + int idx = C->get_alias_index(tp); + assert(get_map(use->_idx) != NULL || idx == alias_idx, + "Following memory nodes should have new memory input or be on the same memory slice"); + } else if (use->is_Phi()) { + // Phi nodes should be split and moved already. + tp = use->as_Phi()->adr_type()->isa_ptr(); + assert(tp != NULL, "ptr type"); + int idx = C->get_alias_index(tp); + assert(idx == alias_idx, "Following Phi nodes should be on the same memory slice"); + } else { + use->dump(); + assert(false, "should not be here"); +#endif + } + } +} + +// // Search memory chain of "mem" to find a MemNode whose address // is the specified alias index. // @@ -774,10 +856,18 @@ C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) { Node *un = result->as_Phi()->unique_input(phase); if (un != NULL) { + orig_phis.append_if_missing(result->as_Phi()); result = un; } else { break; } + } else if (result->is_ClearArray()) { + if (!ClearArrayNode::step_through(&result, (uint)tinst->instance_id(), phase)) { + // Can not bypass initialization of the instance + // we are looking for. + break; + } + // Otherwise skip it (the call updated 'result' value). } else if (result->Opcode() == Op_SCMemProj) { assert(result->in(0)->is_LoadStore(), "sanity"); const Type *at = phase->type(result->in(0)->in(MemNode::Address)); @@ -807,7 +897,6 @@ return result; } - // // Convert the types of unescaped object to instance types where possible, // propagate the new type information through the graph, and update memory @@ -899,12 +988,13 @@ // void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) { GrowableArray memnode_worklist; - GrowableArray mergemem_worklist; GrowableArray orig_phis; + PhaseGVN *igvn = _compile->initial_gvn(); uint new_index_start = (uint) _compile->num_alias_types(); - VectorSet visited(Thread::current()->resource_area()); - VectorSet ptset(Thread::current()->resource_area()); + Arena* arena = Thread::current()->resource_area(); + VectorSet visited(arena); + VectorSet ptset(arena); // Phase 1: Process possible allocations from alloc_worklist. @@ -980,6 +1070,8 @@ // - non-escaping // - eligible to be a unique type // - not determined to be ineligible by escape analysis + assert(ptnode_adr(alloc->_idx)->_node != NULL && + ptnode_adr(n->_idx)->_node != NULL, "should be registered"); set_map(alloc->_idx, n); set_map(n->_idx, alloc); const TypeOopPtr *t = igvn->type(n)->isa_oopptr(); @@ -1024,7 +1116,7 @@ alloc_worklist.append_if_missing(addp2); } alloc_worklist.append_if_missing(use); - } else if (use->is_Initialize()) { + } else if (use->is_MemBar()) { memnode_worklist.append_if_missing(use); } } @@ -1034,10 +1126,12 @@ PointsTo(ptset, get_addp_base(n), igvn); assert(ptset.Size() == 1, "AddP address is unique"); uint elem = ptset.getelem(); // Allocation node's index - if (elem == _phantom_object) + if (elem == _phantom_object) { + assert(false, "escaped allocation"); continue; // Assume the value was set outside this method. + } Node *base = get_map(elem); // CheckCastPP node - if (!split_AddP(n, base, igvn)) continue; // wrong type + if (!split_AddP(n, base, igvn)) continue; // wrong type from dead path tinst = igvn->type(base)->isa_oopptr(); } else if (n->is_Phi() || n->is_CheckCastPP() || @@ -1052,8 +1146,10 @@ PointsTo(ptset, n, igvn); if (ptset.Size() == 1) { uint elem = ptset.getelem(); // Allocation node's index - if (elem == _phantom_object) + if (elem == _phantom_object) { + assert(false, "escaped allocation"); continue; // Assume the value was set outside this method. + } Node *val = get_map(elem); // CheckCastPP node TypeNode *tn = n->as_Type(); tinst = igvn->type(val)->isa_oopptr(); @@ -1068,8 +1164,7 @@ tn_t = tn_type->isa_oopptr(); } - if (tn_t != NULL && - tinst->cast_to_instance_id(TypeOopPtr::InstanceBot)->higher_equal(tn_t)) { + if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) { if (tn_type->isa_narrowoop()) { tn_type = tinst->make_narrowoop(); } else { @@ -1081,33 +1176,25 @@ igvn->hash_insert(tn); record_for_optimizer(n); } else { - continue; // wrong type + assert(tn_type == TypePtr::NULL_PTR || + tn_t != NULL && !tinst->klass()->is_subtype_of(tn_t->klass()), + "unexpected type"); + continue; // Skip dead path with different type } } } else { + debug_only(n->dump();) + assert(false, "EA: unexpected node"); continue; } - // push users on appropriate worklist + // push allocation's users on appropriate worklist for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node *use = n->fast_out(i); if(use->is_Mem() && use->in(MemNode::Address) == n) { - memnode_worklist.append_if_missing(use); - } else if (use->is_Initialize()) { + // Load/store to instance's field memnode_worklist.append_if_missing(use); - } else if (use->is_MergeMem()) { - mergemem_worklist.append_if_missing(use); - } else if (use->is_SafePoint() && tinst != NULL) { - // Look for MergeMem nodes for calls which reference unique allocation - // (through CheckCastPP nodes) even for debug info. - Node* m = use->in(TypeFunc::Memory); - uint iid = tinst->instance_id(); - while (m->is_Proj() && m->in(0)->is_SafePoint() && - m->in(0) != use && !m->in(0)->_idx != iid) { - m = m->in(0)->in(TypeFunc::Memory); - } - if (m->is_MergeMem()) { - mergemem_worklist.append_if_missing(m); - } + } else if (use->is_MemBar()) { + memnode_worklist.append_if_missing(use); } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes Node* addp2 = find_second_addp(use, n); if (addp2 != NULL) { @@ -1120,6 +1207,29 @@ use->is_DecodeN() || (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) { alloc_worklist.append_if_missing(use); +#ifdef ASSERT + } else if (use->is_Mem()) { + assert(use->in(MemNode::Address) != n, "EA: missing allocation reference path"); + } else if (use->is_MergeMem()) { + assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); + } else if (use->is_SafePoint()) { + // Look for MergeMem nodes for calls which reference unique allocation + // (through CheckCastPP nodes) even for debug info. + Node* m = use->in(TypeFunc::Memory); + if (m->is_MergeMem()) { + assert(_mergemem_worklist.contains(m->as_MergeMem()), "EA: missing MergeMem node in the worklist"); + } + } else { + uint op = use->Opcode(); + if (!(op == Op_CmpP || op == Op_Conv2B || + op == Op_CastP2X || op == Op_StoreCM || + op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || + op == Op_StrEquals || op == Op_StrIndexOf)) { + n->dump(); + use->dump(); + assert(false, "EA: missing allocation reference path"); + } +#endif } } @@ -1137,19 +1247,16 @@ Node *n = memnode_worklist.pop(); if (visited.test_set(n->_idx)) continue; - if (n->is_Phi()) { - assert(n->as_Phi()->adr_type() != TypePtr::BOTTOM, "narrow memory slice required"); - // we don't need to do anything, but the users must be pushed if we haven't processed - // this Phi before - } else if (n->is_Initialize()) { - // we don't need to do anything, but the users of the memory projection must be pushed - n = n->as_Initialize()->proj_out(TypeFunc::Memory); + if (n->is_Phi() || n->is_ClearArray()) { + // we don't need to do anything, but the users must be pushed + } else if (n->is_MemBar()) { // Initialize, MemBar nodes + // we don't need to do anything, but the users must be pushed + n = n->as_MemBar()->proj_out(TypeFunc::Memory); if (n == NULL) continue; } else { assert(n->is_Mem(), "memory node required."); Node *addr = n->in(MemNode::Address); - assert(addr->is_AddP(), "AddP required"); const Type *addr_t = igvn->type(addr); if (addr_t == Type::TOP) continue; @@ -1161,6 +1268,10 @@ return; } if (mem != n->in(MemNode::Memory)) { + // We delay the memory edge update since we need old one in + // MergeMem code below when instances memory slices are separated. + debug_only(Node* pn = ptnode_adr(n->_idx)->_node;) + assert(pn == NULL || pn == n, "wrong node"); set_map(n->_idx, mem); ptnode_adr(n->_idx)->_node = n; } @@ -1181,36 +1292,55 @@ // push user on appropriate worklist for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node *use = n->fast_out(i); - if (use->is_Phi()) { + if (use->is_Phi() || use->is_ClearArray()) { memnode_worklist.append_if_missing(use); } else if(use->is_Mem() && use->in(MemNode::Memory) == n) { + if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores + continue; memnode_worklist.append_if_missing(use); - } else if (use->is_Initialize()) { + } else if (use->is_MemBar()) { memnode_worklist.append_if_missing(use); +#ifdef ASSERT + } else if(use->is_Mem()) { + assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); } else if (use->is_MergeMem()) { - mergemem_worklist.append_if_missing(use); + assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); + } else { + uint op = use->Opcode(); + if (!(op == Op_StoreCM || + (op == Op_CallLeaf && use->as_CallLeaf()->_name != NULL && + strcmp(use->as_CallLeaf()->_name, "g1_wb_pre") == 0) || + op == Op_AryEq || op == Op_StrComp || + op == Op_StrEquals || op == Op_StrIndexOf)) { + n->dump(); + use->dump(); + assert(false, "EA: missing memory path"); + } +#endif } } } // Phase 3: Process MergeMem nodes from mergemem_worklist. - // Walk each memory moving the first node encountered of each + // Walk each memory slice moving the first node encountered of each // instance type to the the input corresponding to its alias index. - while (mergemem_worklist.length() != 0) { - Node *n = mergemem_worklist.pop(); - assert(n->is_MergeMem(), "MergeMem node required."); - if (visited.test_set(n->_idx)) - continue; - MergeMemNode *nmm = n->as_MergeMem(); + uint length = _mergemem_worklist.length(); + for( uint next = 0; next < length; ++next ) { + MergeMemNode* nmm = _mergemem_worklist.at(next); + assert(!visited.test_set(nmm->_idx), "should not be visited before"); // Note: we don't want to use MergeMemStream here because we only want to - // scan inputs which exist at the start, not ones we add during processing. + // scan inputs which exist at the start, not ones we add during processing. + // Note 2: MergeMem may already contains instance memory slices added + // during find_inst_mem() call when memory nodes were processed above. + igvn->hash_delete(nmm); uint nslices = nmm->req(); - igvn->hash_delete(nmm); for (uint i = Compile::AliasIdxRaw+1; i < nslices; i++) { Node* mem = nmm->in(i); Node* cur = NULL; if (mem == NULL || mem->is_top()) continue; + // First, update mergemem by moving memory nodes to corresponding slices + // if their type became more precise since this mergemem was created. while (mem->is_Mem()) { const Type *at = igvn->type(mem->in(MemNode::Address)); if (at != Type::TOP) { @@ -1229,7 +1359,7 @@ } nmm->set_memory_at(i, (cur != NULL) ? cur : mem); // Find any instance of the current type if we haven't encountered - // a value of the instance along the chain. + // already a memory slice of the instance along the memory chain. for (uint ni = new_index_start; ni < new_index_end; ni++) { if((uint)_compile->get_general_index(ni) == i) { Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni); @@ -1245,11 +1375,11 @@ } // Find the rest of instances values for (uint ni = new_index_start; ni < new_index_end; ni++) { - const TypeOopPtr *tinst = igvn->C->get_adr_type(ni)->isa_oopptr(); + const TypeOopPtr *tinst = _compile->get_adr_type(ni)->isa_oopptr(); Node* result = step_through_mergemem(nmm, ni, tinst); if (result == nmm->base_memory()) { // Didn't find instance memory, search through general slice recursively. - result = nmm->memory_at(igvn->C->get_general_index(ni)); + result = nmm->memory_at(_compile->get_general_index(ni)); result = find_inst_mem(result, ni, orig_phis, igvn); if (_compile->failing()) { return; @@ -1259,41 +1389,6 @@ } igvn->hash_insert(nmm); record_for_optimizer(nmm); - - // Propagate new memory slices to following MergeMem nodes. - for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { - Node *use = n->fast_out(i); - if (use->is_Call()) { - CallNode* in = use->as_Call(); - if (in->proj_out(TypeFunc::Memory) != NULL) { - Node* m = in->proj_out(TypeFunc::Memory); - for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { - Node* mm = m->fast_out(j); - if (mm->is_MergeMem()) { - mergemem_worklist.append_if_missing(mm); - } - } - } - if (use->is_Allocate()) { - use = use->as_Allocate()->initialization(); - if (use == NULL) { - continue; - } - } - } - if (use->is_Initialize()) { - InitializeNode* in = use->as_Initialize(); - if (in->proj_out(TypeFunc::Memory) != NULL) { - Node* m = in->proj_out(TypeFunc::Memory); - for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { - Node* mm = m->fast_out(j); - if (mm->is_MergeMem()) { - mergemem_worklist.append_if_missing(mm); - } - } - } - } - } } // Phase 4: Update the inputs of non-instance memory Phis and @@ -1322,19 +1417,48 @@ } // Update the memory inputs of MemNodes with the value we computed - // in Phase 2. + // in Phase 2 and move stores memory users to corresponding memory slices. +#ifdef ASSERT + visited.Clear(); + Node_Stack old_mems(arena, _compile->unique() >> 2); +#endif for (uint i = 0; i < nodes_size(); i++) { Node *nmem = get_map(i); if (nmem != NULL) { Node *n = ptnode_adr(i)->_node; - if (n != NULL && n->is_Mem()) { + assert(n != NULL, "sanity"); + if (n->is_Mem()) { +#ifdef ASSERT + Node* old_mem = n->in(MemNode::Memory); + if (!visited.test_set(old_mem->_idx)) { + old_mems.push(old_mem, old_mem->outcnt()); + } +#endif + assert(n->in(MemNode::Memory) != nmem, "sanity"); + if (!n->is_Load()) { + // Move memory users of a store first. + move_inst_mem(n, orig_phis, igvn); + } + // Now update memory input igvn->hash_delete(n); n->set_req(MemNode::Memory, nmem); igvn->hash_insert(n); record_for_optimizer(n); + } else { + assert(n->is_Allocate() || n->is_CheckCastPP() || + n->is_AddP() || n->is_Phi(), "unknown node used for set_map()"); } } } +#ifdef ASSERT + // Verify that memory was split correctly + while (old_mems.is_nonempty()) { + Node* old_mem = old_mems.node(); + uint old_cnt = old_mems.index(); + old_mems.pop(); + assert(old_cnt = old_mem->outcnt(), "old mem could be lost"); + } +#endif } bool ConnectionGraph::has_candidates(Compile *C) { @@ -1381,8 +1505,20 @@ ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { has_allocations = true; } - if(n->is_AddP()) - cg_worklist.append(n->_idx); + if(n->is_AddP()) { + // Collect address nodes which directly reference an allocation. + // Use them during stage 3 below to build initial connection graph + // field edges. Other field edges could be added after StoreP/LoadP + // nodes are processed during stage 4 below. + Node* base = get_addp_base(n); + if(base->is_Proj() && base->in(0)->is_Allocate()) { + cg_worklist.append(n->_idx); + } + } else if (n->is_MergeMem()) { + // Collect all MergeMem nodes to add memory slices for + // scalar replaceable objects in split_unique_types(). + _mergemem_worklist.append(n->as_MergeMem()); + } for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node* m = n->fast_out(i); // Get user worklist_init.push(m); @@ -1423,12 +1559,13 @@ } } - VectorSet ptset(Thread::current()->resource_area()); + Arena* arena = Thread::current()->resource_area(); + VectorSet ptset(arena); GrowableArray deferred_edges; - VectorSet visited(Thread::current()->resource_area()); + VectorSet visited(arena); - // 5. Remove deferred edges from the graph and collect - // information needed for type splitting. + // 5. Remove deferred edges from the graph and adjust + // escape state of nonescaping objects. cg_length = cg_worklist.length(); for( uint next = 0; next < cg_length; ++next ) { int ni = cg_worklist.at(next); @@ -1438,98 +1575,9 @@ remove_deferred(ni, &deferred_edges, &visited); Node *n = ptn->_node; if (n->is_AddP()) { - // Search for objects which are not scalar replaceable. - // Mark their escape state as ArgEscape to propagate the state - // to referenced objects. - // Note: currently there are no difference in compiler optimizations - // for ArgEscape objects and NoEscape objects which are not - // scalar replaceable. - - int offset = ptn->offset(); - Node *base = get_addp_base(n); - ptset.Clear(); - PointsTo(ptset, base, igvn); - int ptset_size = ptset.Size(); - - // Check if a field's initializing value is recorded and add - // a corresponding NULL field's value if it is not recorded. - // Connection Graph does not record a default initialization by NULL - // captured by Initialize node. - // - // Note: it will disable scalar replacement in some cases: - // - // Point p[] = new Point[1]; - // p[0] = new Point(); // Will be not scalar replaced - // - // but it will save us from incorrect optimizations in next cases: - // - // Point p[] = new Point[1]; - // if ( x ) p[0] = new Point(); // Will be not scalar replaced - // - // Without a control flow analysis we can't distinguish above cases. - // - if (offset != Type::OffsetBot && ptset_size == 1) { - uint elem = ptset.getelem(); // Allocation node's index - // It does not matter if it is not Allocation node since - // only non-escaping allocations are scalar replaced. - if (ptnode_adr(elem)->_node->is_Allocate() && - ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) { - AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate(); - InitializeNode* ini = alloc->initialization(); - Node* value = NULL; - if (ini != NULL) { - BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT; - Node* store = ini->find_captured_store(offset, type2aelembytes(ft), igvn); - if (store != NULL && store->is_Store()) - value = store->in(MemNode::ValueIn); - } - if (value == NULL || value != ptnode_adr(value->_idx)->_node) { - // A field's initializing value was not recorded. Add NULL. - uint null_idx = UseCompressedOops ? _noop_null : _oop_null; - add_pointsto_edge(ni, null_idx); - } - } - } - - // An object is not scalar replaceable if the field which may point - // to it has unknown offset (unknown element of an array of objects). - // - if (offset == Type::OffsetBot) { - uint e_cnt = ptn->edge_count(); - for (uint ei = 0; ei < e_cnt; ei++) { - uint npi = ptn->edge_target(ei); - set_escape_state(npi, PointsToNode::ArgEscape); - ptnode_adr(npi)->_scalar_replaceable = false; - } - } - - // Currently an object is not scalar replaceable if a LoadStore node - // access its field since the field value is unknown after it. - // - bool has_LoadStore = false; - for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { - Node *use = n->fast_out(i); - if (use->is_LoadStore()) { - has_LoadStore = true; - break; - } - } - // An object is not scalar replaceable if the address points - // to unknown field (unknown element for arrays, offset is OffsetBot). - // - // Or the address may point to more then one object. This may produce - // the false positive result (set scalar_replaceable to false) - // since the flow-insensitive escape analysis can't separate - // the case when stores overwrite the field's value from the case - // when stores happened on different control branches. - // - if (ptset_size > 1 || ptset_size != 0 && - (has_LoadStore || offset == Type::OffsetBot)) { - for( VectorSetI j(&ptset); j.test(); ++j ) { - set_escape_state(j.elem, PointsToNode::ArgEscape); - ptnode_adr(j.elem)->_scalar_replaceable = false; - } - } + // Search for objects which are not scalar replaceable + // and adjust their escape state. + verify_escape_state(ni, ptset, igvn); } } } @@ -1646,6 +1694,150 @@ return has_non_escaping_obj; } +// Search for objects which are not scalar replaceable. +void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase) { + PointsToNode* ptn = ptnode_adr(nidx); + Node* n = ptn->_node; + assert(n->is_AddP(), "Should be called for AddP nodes only"); + // Search for objects which are not scalar replaceable. + // Mark their escape state as ArgEscape to propagate the state + // to referenced objects. + // Note: currently there are no difference in compiler optimizations + // for ArgEscape objects and NoEscape objects which are not + // scalar replaceable. + + Compile* C = _compile; + + int offset = ptn->offset(); + Node* base = get_addp_base(n); + ptset.Clear(); + PointsTo(ptset, base, phase); + int ptset_size = ptset.Size(); + + // Check if a oop field's initializing value is recorded and add + // a corresponding NULL field's value if it is not recorded. + // Connection Graph does not record a default initialization by NULL + // captured by Initialize node. + // + // Note: it will disable scalar replacement in some cases: + // + // Point p[] = new Point[1]; + // p[0] = new Point(); // Will be not scalar replaced + // + // but it will save us from incorrect optimizations in next cases: + // + // Point p[] = new Point[1]; + // if ( x ) p[0] = new Point(); // Will be not scalar replaced + // + // Do a simple control flow analysis to distinguish above cases. + // + if (offset != Type::OffsetBot && ptset_size == 1) { + uint elem = ptset.getelem(); // Allocation node's index + // It does not matter if it is not Allocation node since + // only non-escaping allocations are scalar replaced. + if (ptnode_adr(elem)->_node->is_Allocate() && + ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) { + AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate(); + InitializeNode* ini = alloc->initialization(); + + // Check only oop fields. + const Type* adr_type = n->as_AddP()->bottom_type(); + BasicType basic_field_type = T_INT; + if (adr_type->isa_instptr()) { + ciField* field = C->alias_type(adr_type->isa_instptr())->field(); + if (field != NULL) { + basic_field_type = field->layout_type(); + } else { + // Ignore non field load (for example, klass load) + } + } else if (adr_type->isa_aryptr()) { + const Type* elemtype = adr_type->isa_aryptr()->elem(); + basic_field_type = elemtype->array_element_basic_type(); + } else { + // Raw pointers are used for initializing stores so skip it. + assert(adr_type->isa_rawptr() && base->is_Proj() && + (base->in(0) == alloc),"unexpected pointer type"); + } + if (basic_field_type == T_OBJECT || + basic_field_type == T_NARROWOOP || + basic_field_type == T_ARRAY) { + Node* value = NULL; + if (ini != NULL) { + BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT; + Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase); + if (store != NULL && store->is_Store()) { + value = store->in(MemNode::ValueIn); + } else if (ptn->edge_count() > 0) { // Are there oop stores? + // Check for a store which follows allocation without branches. + // For example, a volatile field store is not collected + // by Initialize node. TODO: it would be nice to use idom() here. + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + store = n->fast_out(i); + if (store->is_Store() && store->in(0) != NULL) { + Node* ctrl = store->in(0); + while(!(ctrl == ini || ctrl == alloc || ctrl == NULL || + ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() || + ctrl->is_IfTrue() || ctrl->is_IfFalse())) { + ctrl = ctrl->in(0); + } + if (ctrl == ini || ctrl == alloc) { + value = store->in(MemNode::ValueIn); + break; + } + } + } + } + } + if (value == NULL || value != ptnode_adr(value->_idx)->_node) { + // A field's initializing value was not recorded. Add NULL. + uint null_idx = UseCompressedOops ? _noop_null : _oop_null; + add_pointsto_edge(nidx, null_idx); + } + } + } + } + + // An object is not scalar replaceable if the field which may point + // to it has unknown offset (unknown element of an array of objects). + // + if (offset == Type::OffsetBot) { + uint e_cnt = ptn->edge_count(); + for (uint ei = 0; ei < e_cnt; ei++) { + uint npi = ptn->edge_target(ei); + set_escape_state(npi, PointsToNode::ArgEscape); + ptnode_adr(npi)->_scalar_replaceable = false; + } + } + + // Currently an object is not scalar replaceable if a LoadStore node + // access its field since the field value is unknown after it. + // + bool has_LoadStore = false; + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node *use = n->fast_out(i); + if (use->is_LoadStore()) { + has_LoadStore = true; + break; + } + } + // An object is not scalar replaceable if the address points + // to unknown field (unknown element for arrays, offset is OffsetBot). + // + // Or the address may point to more then one object. This may produce + // the false positive result (set scalar_replaceable to false) + // since the flow-insensitive escape analysis can't separate + // the case when stores overwrite the field's value from the case + // when stores happened on different control branches. + // + if (ptset_size > 1 || ptset_size != 0 && + (has_LoadStore || offset == Type::OffsetBot)) { + for( VectorSetI j(&ptset); j.test(); ++j ) { + set_escape_state(j.elem, PointsToNode::ArgEscape); + ptnode_adr(j.elem)->_scalar_replaceable = false; + } + } +} + void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { switch (call->Opcode()) { @@ -1657,6 +1849,7 @@ assert(false, "should be done already"); break; #endif + case Op_CallLeaf: case Op_CallLeafNoFP: { // Stub calls, objects do not escape but they are not scale replaceable. @@ -1667,9 +1860,23 @@ const Type* at = d->field_at(i); Node *arg = call->in(i)->uncast(); const Type *aat = phase->type(arg); - if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr()) { + if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() && + ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { + assert(aat == Type::TOP || aat == TypePtr::NULL_PTR || aat->isa_ptr() != NULL, "expecting an Ptr"); +#ifdef ASSERT + if (!(call->Opcode() == Op_CallLeafNoFP && + call->as_CallLeaf()->_name != NULL && + (strstr(call->as_CallLeaf()->_name, "arraycopy") != 0) || + call->as_CallLeaf()->_name != NULL && + (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || + strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 )) + ) { + call->dump(); + assert(false, "EA: unexpected CallLeaf"); + } +#endif set_escape_state(arg->_idx, PointsToNode::ArgEscape); if (arg->is_AddP()) { // @@ -1706,9 +1913,10 @@ for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { const Type* at = d->field_at(i); int k = i - TypeFunc::Parms; + Node *arg = call->in(i)->uncast(); - if (at->isa_oopptr() != NULL) { - Node *arg = call->in(i)->uncast(); + if (at->isa_oopptr() != NULL && + ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { bool global_escapes = false; bool fields_escapes = false; @@ -1942,20 +2150,23 @@ record_for_optimizer(n); _processed.set(n->_idx); } else { - // Have to process call's arguments first. + // Don't mark as processed since call's arguments have to be processed. PointsToNode::NodeType nt = PointsToNode::UnknownType; + PointsToNode::EscapeState es = PointsToNode::UnknownEscape; // Check if a call returns an object. const TypeTuple *r = n->as_Call()->tf()->range(); - if (n->is_CallStaticJava() && r->cnt() > TypeFunc::Parms && + if (r->cnt() > TypeFunc::Parms && + r->field_at(TypeFunc::Parms)->isa_ptr() && n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { - // Note: use isa_ptr() instead of isa_oopptr() here because - // the _multianewarray functions return a TypeRawPtr. - if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) { - nt = PointsToNode::JavaObject; + nt = PointsToNode::JavaObject; + if (!n->is_CallStaticJava()) { + // Since the called mathod is statically unknown assume + // the worst case that the returned value globally escapes. + es = PointsToNode::GlobalEscape; } } - add_node(n, nt, PointsToNode::UnknownEscape, false); + add_node(n, nt, es, false); } return; } @@ -2088,18 +2299,27 @@ } case Op_Proj: { - // we are only interested in the result projection from a call + // we are only interested in the oop result projection from a call if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { - add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); - process_call_result(n->as_Proj(), phase); - if (!_processed.test(n->_idx)) { - // The call's result may need to be processed later if the call - // returns it's argument and the argument is not processed yet. - _delayed_worklist.push(n); + const TypeTuple *r = n->in(0)->as_Call()->tf()->range(); + assert(r->cnt() > TypeFunc::Parms, "sanity"); + if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) { + add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); + int ti = n->in(0)->_idx; + // The call may not be registered yet (since not all its inputs are registered) + // if this is the projection from backbranch edge of Phi. + if (ptnode_adr(ti)->node_type() != PointsToNode::UnknownType) { + process_call_result(n->as_Proj(), phase); + } + if (!_processed.test(n->_idx)) { + // The call's result may need to be processed later if the call + // returns it's argument and the argument is not processed yet. + _delayed_worklist.push(n); + } + break; } - } else { - _processed.set(n->_idx); } + _processed.set(n->_idx); break; } case Op_Return: @@ -2160,6 +2380,15 @@ } break; } + case Op_AryEq: + case Op_StrComp: + case Op_StrEquals: + case Op_StrIndexOf: + { + // char[] arrays passed to string intrinsics are not scalar replaceable. + add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false); + break; + } case Op_ThreadLocal: { add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true); @@ -2174,6 +2403,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { uint n_idx = n->_idx; + assert(ptnode_adr(n_idx)->_node != NULL, "node should be registered"); // Don't set processed bit for AddP, LoadP, StoreP since // they may need more then one pass to process. @@ -2211,6 +2441,7 @@ case Op_DecodeN: { int ti = n->in(1)->_idx; + assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "all nodes should be registered"); if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { add_pointsto_edge(n_idx, ti); } else { @@ -2250,7 +2481,6 @@ #endif Node* adr = n->in(MemNode::Address)->uncast(); - const Type *adr_type = phase->type(adr); Node* adr_base; if (adr->is_AddP()) { adr_base = get_addp_base(adr); @@ -2302,13 +2532,19 @@ } case Op_Proj: { - // we are only interested in the result projection from a call + // we are only interested in the oop result projection from a call if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { - process_call_result(n->as_Proj(), phase); - assert(_processed.test(n_idx), "all call results should be processed"); - } else { - assert(false, "Op_Proj"); + assert(ptnode_adr(n->in(0)->_idx)->node_type() != PointsToNode::UnknownType, + "all nodes should be registered"); + const TypeTuple *r = n->in(0)->as_Call()->tf()->range(); + assert(r->cnt() > TypeFunc::Parms, "sanity"); + if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) { + process_call_result(n->as_Proj(), phase); + assert(_processed.test(n_idx), "all call results should be processed"); + break; + } } + assert(false, "Op_Proj"); break; } case Op_Return: @@ -2320,6 +2556,7 @@ } #endif int ti = n->in(TypeFunc::Parms)->_idx; + assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "node should be registered"); if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { add_pointsto_edge(n_idx, ti); } else { @@ -2354,14 +2591,38 @@ } break; } + case Op_AryEq: + case Op_StrComp: + case Op_StrEquals: + case Op_StrIndexOf: + { + // char[] arrays passed to string intrinsic do not escape but + // they are not scalar replaceable. Adjust escape state for them. + // Start from in(2) edge since in(1) is memory edge. + for (uint i = 2; i < n->req(); i++) { + Node* adr = n->in(i)->uncast(); + const Type *at = phase->type(adr); + if (!adr->is_top() && at->isa_ptr()) { + assert(at == Type::TOP || at == TypePtr::NULL_PTR || + at->isa_ptr() != NULL, "expecting an Ptr"); + if (adr->is_AddP()) { + adr = get_addp_base(adr); + } + // Mark as ArgEscape everything "adr" could point to. + set_escape_state(adr->_idx, PointsToNode::ArgEscape); + } + } + _processed.set(n_idx); + break; + } case Op_ThreadLocal: { assert(false, "Op_ThreadLocal"); break; } default: - ; - // nothing to do + // This method should be called only for EA specific nodes. + ShouldNotReachHere(); } } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/escape.hpp --- a/hotspot/src/share/vm/opto/escape.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/escape.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -210,6 +210,8 @@ Unique_Node_List _delayed_worklist; // Nodes to be processed before // the call build_connection_graph(). + GrowableArray _mergemem_worklist; // List of all MergeMem nodes + VectorSet _processed; // Records which nodes have been // processed. @@ -289,7 +291,7 @@ bool split_AddP(Node *addp, Node *base, PhaseGVN *igvn); PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray &orig_phi_worklist, PhaseGVN *igvn, bool &new_created); PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray &orig_phi_worklist, PhaseGVN *igvn); - Node *find_mem(Node *mem, int alias_idx, PhaseGVN *igvn); + void move_inst_mem(Node* n, GrowableArray &orig_phis, PhaseGVN *igvn); Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray &orig_phi_worklist, PhaseGVN *igvn); // Propagate unique types created for unescaped allocated objects @@ -298,7 +300,6 @@ // manage entries in _node_map void set_map(int idx, Node *n) { _node_map.map(idx, n); } - void set_map_phi(int idx, PhiNode *p) { _node_map.map(idx, (Node *) p); } Node *get_map(int idx) { return _node_map[idx]; } PhiNode *get_map_phi(int idx) { Node *phi = _node_map[idx]; @@ -315,6 +316,9 @@ // Set the escape state of a node void set_escape_state(uint ni, PointsToNode::EscapeState es); + // Search for objects which are not scalar replaceable. + void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase); + public: ConnectionGraph(Compile *C); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/graphKit.cpp --- a/hotspot/src/share/vm/opto/graphKit.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/graphKit.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1351,8 +1351,8 @@ } //------------------------------set_all_memory_call---------------------------- -void GraphKit::set_all_memory_call(Node* call) { - Node* newmem = _gvn.transform( new (C, 1) ProjNode(call, TypeFunc::Memory) ); +void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) { + Node* newmem = _gvn.transform( new (C, 1) ProjNode(call, TypeFunc::Memory, separate_io_proj) ); set_all_memory(newmem); } @@ -1573,7 +1573,7 @@ //---------------------------set_edges_for_java_call--------------------------- // Connect a newly created call into the current JVMS. // A return value node (if any) is returned from set_edges_for_java_call. -void GraphKit::set_edges_for_java_call(CallJavaNode* call, bool must_throw) { +void GraphKit::set_edges_for_java_call(CallJavaNode* call, bool must_throw, bool separate_io_proj) { // Add the predefined inputs: call->init_req( TypeFunc::Control, control() ); @@ -1595,13 +1595,13 @@ // Re-use the current map to produce the result. set_control(_gvn.transform(new (C, 1) ProjNode(call, TypeFunc::Control))); - set_i_o( _gvn.transform(new (C, 1) ProjNode(call, TypeFunc::I_O ))); - set_all_memory_call(xcall); + set_i_o( _gvn.transform(new (C, 1) ProjNode(call, TypeFunc::I_O , separate_io_proj))); + set_all_memory_call(xcall, separate_io_proj); //return xcall; // no need, caller already has it } -Node* GraphKit::set_results_for_java_call(CallJavaNode* call) { +Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_proj) { if (stopped()) return top(); // maybe the call folded up? // Capture the return value, if any. @@ -1614,8 +1614,15 @@ // Note: Since any out-of-line call can produce an exception, // we always insert an I_O projection from the call into the result. - make_slow_call_ex(call, env()->Throwable_klass(), false); - + make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj); + + if (separate_io_proj) { + // The caller requested separate projections be used by the fall + // through and exceptional paths, so replace the projections for + // the fall through path. + set_i_o(_gvn.transform( new (C, 1) ProjNode(call, TypeFunc::I_O) )); + set_all_memory(_gvn.transform( new (C, 1) ProjNode(call, TypeFunc::Memory) )); + } return ret; } @@ -1678,6 +1685,64 @@ } } + +// Replace the call with the current state of the kit. +void GraphKit::replace_call(CallNode* call, Node* result) { + JVMState* ejvms = NULL; + if (has_exceptions()) { + ejvms = transfer_exceptions_into_jvms(); + } + + SafePointNode* final_state = stop(); + + // Find all the needed outputs of this call + CallProjections callprojs; + call->extract_projections(&callprojs, true); + + // Replace all the old call edges with the edges from the inlining result + C->gvn_replace_by(callprojs.fallthrough_catchproj, final_state->in(TypeFunc::Control)); + C->gvn_replace_by(callprojs.fallthrough_memproj, final_state->in(TypeFunc::Memory)); + C->gvn_replace_by(callprojs.fallthrough_ioproj, final_state->in(TypeFunc::I_O)); + + // Replace the result with the new result if it exists and is used + if (callprojs.resproj != NULL && result != NULL) { + C->gvn_replace_by(callprojs.resproj, result); + } + + if (ejvms == NULL) { + // No exception edges to simply kill off those paths + C->gvn_replace_by(callprojs.catchall_catchproj, C->top()); + C->gvn_replace_by(callprojs.catchall_memproj, C->top()); + C->gvn_replace_by(callprojs.catchall_ioproj, C->top()); + + // Replace the old exception object with top + if (callprojs.exobj != NULL) { + C->gvn_replace_by(callprojs.exobj, C->top()); + } + } else { + GraphKit ekit(ejvms); + + // Load my combined exception state into the kit, with all phis transformed: + SafePointNode* ex_map = ekit.combine_and_pop_all_exception_states(); + + Node* ex_oop = ekit.use_exception_state(ex_map); + + C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control()); + C->gvn_replace_by(callprojs.catchall_memproj, ekit.reset_memory()); + C->gvn_replace_by(callprojs.catchall_ioproj, ekit.i_o()); + + // Replace the old exception object with the newly created one + if (callprojs.exobj != NULL) { + C->gvn_replace_by(callprojs.exobj, ex_oop); + } + } + + // Disconnect the call from the graph + call->disconnect_inputs(NULL); + C->gvn_replace_by(call, C->top()); +} + + //------------------------------increment_counter------------------------------ // for statistics: increment a VM counter by 1 @@ -3459,4 +3524,3 @@ sync_kit(ideal); } #undef __ - diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/graphKit.hpp --- a/hotspot/src/share/vm/opto/graphKit.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/graphKit.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -279,6 +279,34 @@ } Node* basic_plus_adr(Node* base, Node* ptr, Node* offset); + + // Some convenient shortcuts for common nodes + Node* IfTrue(IfNode* iff) { return _gvn.transform(new (C,1) IfTrueNode(iff)); } + Node* IfFalse(IfNode* iff) { return _gvn.transform(new (C,1) IfFalseNode(iff)); } + + Node* AddI(Node* l, Node* r) { return _gvn.transform(new (C,3) AddINode(l, r)); } + Node* SubI(Node* l, Node* r) { return _gvn.transform(new (C,3) SubINode(l, r)); } + Node* MulI(Node* l, Node* r) { return _gvn.transform(new (C,3) MulINode(l, r)); } + Node* DivI(Node* ctl, Node* l, Node* r) { return _gvn.transform(new (C,3) DivINode(ctl, l, r)); } + + Node* AndI(Node* l, Node* r) { return _gvn.transform(new (C,3) AndINode(l, r)); } + Node* OrI(Node* l, Node* r) { return _gvn.transform(new (C,3) OrINode(l, r)); } + Node* XorI(Node* l, Node* r) { return _gvn.transform(new (C,3) XorINode(l, r)); } + + Node* MaxI(Node* l, Node* r) { return _gvn.transform(new (C,3) MaxINode(l, r)); } + Node* MinI(Node* l, Node* r) { return _gvn.transform(new (C,3) MinINode(l, r)); } + + Node* LShiftI(Node* l, Node* r) { return _gvn.transform(new (C,3) LShiftINode(l, r)); } + Node* RShiftI(Node* l, Node* r) { return _gvn.transform(new (C,3) RShiftINode(l, r)); } + Node* URShiftI(Node* l, Node* r) { return _gvn.transform(new (C,3) URShiftINode(l, r)); } + + Node* CmpI(Node* l, Node* r) { return _gvn.transform(new (C,3) CmpINode(l, r)); } + Node* CmpL(Node* l, Node* r) { return _gvn.transform(new (C,3) CmpLNode(l, r)); } + Node* CmpP(Node* l, Node* r) { return _gvn.transform(new (C,3) CmpPNode(l, r)); } + Node* Bool(Node* cmp, BoolTest::mask relop) { return _gvn.transform(new (C,2) BoolNode(cmp, relop)); } + + Node* AddP(Node* b, Node* a, Node* o) { return _gvn.transform(new (C,4) AddPNode(b, a, o)); } + // Convert between int and long, and size_t. // (See macros ConvI2X, etc., in type.hpp for ConvI2X, etc.) Node* ConvI2L(Node* offset); @@ -400,7 +428,7 @@ void set_all_memory(Node* newmem); // Create a memory projection from the call, then set_all_memory. - void set_all_memory_call(Node* call); + void set_all_memory_call(Node* call, bool separate_io_proj = false); // Create a LoadNode, reading from the parser's memory state. // (Note: require_atomic_access is useful only with T_LONG.) @@ -543,12 +571,12 @@ // Transform the call, and update the basics: control, i_o, memory. // (The next step is usually to call set_results_for_java_call.) void set_edges_for_java_call(CallJavaNode* call, - bool must_throw = false); + bool must_throw = false, bool separate_io_proj = false); // Finish up a java call that was started by set_edges_for_java_call. // Call add_exception on any throw arising from the call. // Return the call result (transformed). - Node* set_results_for_java_call(CallJavaNode* call); + Node* set_results_for_java_call(CallJavaNode* call, bool separate_io_proj = false); // Similar to set_edges_for_java_call, but simplified for runtime calls. void set_predefined_output_for_runtime_call(Node* call) { @@ -559,6 +587,11 @@ const TypePtr* hook_mem); Node* set_predefined_input_for_runtime_call(SafePointNode* call); + // Replace the call with the current state of the kit. Requires + // that the call was generated with separate io_projs so that + // exceptional control flow can be handled properly. + void replace_call(CallNode* call, Node* result); + // helper functions for statistics void increment_counter(address counter_addr); // increment a debug counter void increment_counter(Node* counter_addr); // increment a debug counter diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/lcm.cpp --- a/hotspot/src/share/vm/opto/lcm.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/lcm.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -616,8 +616,9 @@ assert(cfg->_bbs[oop_store->_idx]->_dom_depth <= this->_dom_depth, "oop_store must dominate card-mark"); } } - if( n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_MemBarAcquire && - n->req() > TypeFunc::Parms ) { + if( n->is_Mach() && n->req() > TypeFunc::Parms && + (n->as_Mach()->ideal_Opcode() == Op_MemBarAcquire || + n->as_Mach()->ideal_Opcode() == Op_MemBarVolatile) ) { // MemBarAcquire could be created without Precedent edge. // del_req() replaces the specified edge with the last input edge // and then removes the last edge. If the specified edge > number of diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/loopnode.cpp --- a/hotspot/src/share/vm/opto/loopnode.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1279,7 +1279,8 @@ // Visit all children, looking for Phis for (DUIterator i = cl->outs(); cl->has_out(i); i++) { Node *out = cl->out(i); - if (!out->is_Phi() || out == phi) continue; // Looking for other phis + // Look for other phis (secondary IVs). Skip dead ones + if (!out->is_Phi() || out == phi || !phase->has_node(out)) continue; PhiNode* phi2 = out->as_Phi(); Node *incr2 = phi2->in( LoopNode::LoopBackControl ); // Look for induction variables of the form: X += constant diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/macro.cpp --- a/hotspot/src/share/vm/opto/macro.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/macro.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -316,6 +316,21 @@ assert(adr_idx == Compile::AliasIdxRaw, "address must match or be raw"); } mem = mem->in(MemNode::Memory); + } else if (mem->is_ClearArray()) { + if (!ClearArrayNode::step_through(&mem, alloc->_idx, phase)) { + // Can not bypass initialization of the instance + // we are looking. + debug_only(intptr_t offset;) + assert(alloc == AllocateNode::Ideal_allocation(mem->in(3), phase, offset), "sanity"); + InitializeNode* init = alloc->as_Allocate()->initialization(); + // We are looking for stored value, return Initialize node + // or memory edge from Allocate node. + if (init != NULL) + return init; + else + return alloc->in(TypeFunc::Memory); // It will produce zero value (see callers). + } + // Otherwise skip it (the call updated 'mem' value). } else if (mem->Opcode() == Op_SCMemProj) { assert(mem->in(0)->is_LoadStore(), "sanity"); const TypePtr* atype = mem->in(0)->in(MemNode::Address)->bottom_type()->is_ptr(); @@ -823,6 +838,18 @@ Node *n = use->last_out(k); uint oc2 = use->outcnt(); if (n->is_Store()) { +#ifdef ASSERT + // Verify that there is no dependent MemBarVolatile nodes, + // they should be removed during IGVN, see MemBarNode::Ideal(). + for (DUIterator_Fast pmax, p = n->fast_outs(pmax); + p < pmax; p++) { + Node* mb = n->fast_out(p); + assert(mb->is_Initialize() || !mb->is_MemBar() || + mb->req() <= MemBarNode::Precedent || + mb->in(MemBarNode::Precedent) != n, + "MemBarVolatile should be eliminated for non-escaping object"); + } +#endif _igvn.replace_node(n, n->in(MemNode::Memory)); } else { eliminate_card_mark(n); @@ -912,15 +939,29 @@ return false; } + CompileLog* log = C->log(); + if (log != NULL) { + Node* klass = alloc->in(AllocateNode::KlassNode); + const TypeKlassPtr* tklass = _igvn.type(klass)->is_klassptr(); + log->head("eliminate_allocation type='%d'", + log->identify(tklass->klass())); + JVMState* p = alloc->jvms(); + while (p != NULL) { + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); + p = p->caller(); + } + log->tail("eliminate_allocation"); + } + process_users_of_allocation(alloc); #ifndef PRODUCT -if (PrintEliminateAllocations) { - if (alloc->is_AllocateArray()) - tty->print_cr("++++ Eliminated: %d AllocateArray", alloc->_idx); - else - tty->print_cr("++++ Eliminated: %d Allocate", alloc->_idx); -} + if (PrintEliminateAllocations) { + if (alloc->is_AllocateArray()) + tty->print_cr("++++ Eliminated: %d AllocateArray", alloc->_idx); + else + tty->print_cr("++++ Eliminated: %d Allocate", alloc->_idx); + } #endif return true; @@ -1639,6 +1680,18 @@ } // if (!oldbox->is_eliminated()) } // if (alock->is_Lock() && !lock->is_coarsened()) + CompileLog* log = C->log(); + if (log != NULL) { + log->head("eliminate_lock lock='%d'", + alock->is_Lock()); + JVMState* p = alock->jvms(); + while (p != NULL) { + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); + p = p->caller(); + } + log->tail("eliminate_lock"); + } + #ifndef PRODUCT if (PrintEliminateLocks) { if (alock->is_Lock()) { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/matcher.cpp --- a/hotspot/src/share/vm/opto/matcher.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1832,67 +1832,23 @@ case Op_Binary: // These are introduced in the Post_Visit state. ShouldNotReachHere(); break; - case Op_StoreB: // Do match these, despite no ideal reg - case Op_StoreC: - case Op_StoreCM: - case Op_StoreD: - case Op_StoreF: - case Op_StoreI: - case Op_StoreL: - case Op_StoreP: - case Op_StoreN: - case Op_Store16B: - case Op_Store8B: - case Op_Store4B: - case Op_Store8C: - case Op_Store4C: - case Op_Store2C: - case Op_Store4I: - case Op_Store2I: - case Op_Store2L: - case Op_Store4F: - case Op_Store2F: - case Op_Store2D: case Op_ClearArray: case Op_SafePoint: mem_op = true; break; - case Op_LoadB: - case Op_LoadUS: - case Op_LoadD: - case Op_LoadF: - case Op_LoadI: - case Op_LoadKlass: - case Op_LoadNKlass: - case Op_LoadL: - case Op_LoadS: - case Op_LoadP: - case Op_LoadN: - case Op_LoadRange: - case Op_LoadD_unaligned: - case Op_LoadL_unaligned: - case Op_Load16B: - case Op_Load8B: - case Op_Load4B: - case Op_Load4C: - case Op_Load2C: - case Op_Load8C: - case Op_Load8S: - case Op_Load4S: - case Op_Load2S: - case Op_Load4I: - case Op_Load2I: - case Op_Load2L: - case Op_Load4F: - case Op_Load2F: - case Op_Load2D: - mem_op = true; - // Must be root of match tree due to prior load conflict - if( C->subsume_loads() == false ) { - set_shared(n); + default: + if( n->is_Store() ) { + // Do match stores, despite no ideal reg + mem_op = true; + break; + } + if( n->is_Mem() ) { // Loads and LoadStores + mem_op = true; + // Loads must be root of match tree due to prior load conflict + if( C->subsume_loads() == false ) + set_shared(n); } // Fall into default case - default: if( !n->ideal_reg() ) set_dontcare(n); // Unmatchable Nodes } // end_switch @@ -1913,15 +1869,15 @@ continue; // for(int i = ...) } - // Clone addressing expressions as they are "free" in most instructions + if( mop == Op_AddP && m->in(AddPNode::Base)->Opcode() == Op_DecodeN ) { + // Bases used in addresses must be shared but since + // they are shared through a DecodeN they may appear + // to have a single use so force sharing here. + set_shared(m->in(AddPNode::Base)->in(1)); + } + + // Clone addressing expressions as they are "free" in memory access instructions if( mem_op && i == MemNode::Address && mop == Op_AddP ) { - if (m->in(AddPNode::Base)->Opcode() == Op_DecodeN) { - // Bases used in addresses must be shared but since - // they are shared through a DecodeN they may appear - // to have a single use so force sharing here. - set_shared(m->in(AddPNode::Base)->in(1)); - } - // Some inputs for address expression are not put on stack // to avoid marking them as shared and forcing them into register // if they are used only in address expressions. diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/memnode.cpp --- a/hotspot/src/share/vm/opto/memnode.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/memnode.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -123,6 +123,13 @@ } else { assert(false, "unexpected projection"); } + } else if (result->is_ClearArray()) { + if (!ClearArrayNode::step_through(&result, instance_id, phase)) { + // Can not bypass initialization of the instance + // we are looking for. + break; + } + // Otherwise skip it (the call updated 'result' value). } else if (result->is_MergeMem()) { result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty); } @@ -255,6 +262,13 @@ return NodeSentinel; // caller will return NULL } + // Do NOT remove or optimize the next lines: ensure a new alias index + // is allocated for an oop pointer type before Escape Analysis. + // Note: C++ will not remove it since the call has side effect. + if ( t_adr->isa_oopptr() ) { + int alias_idx = phase->C->get_alias_index(t_adr->is_ptr()); + } + #ifdef ASSERT Node* base = NULL; if (address->is_AddP()) @@ -530,6 +544,15 @@ } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) { mem = mem->in(0)->in(TypeFunc::Memory); continue; // (a) advance through independent MemBar memory + } else if (mem->is_ClearArray()) { + if (ClearArrayNode::step_through(&mem, (uint)addr_t->instance_id(), phase)) { + // (the call updated 'mem' value) + continue; // (a) advance through independent allocation memory + } else { + // Can not bypass initialization of the instance + // we are looking for. + return mem; + } } else if (mem->is_MergeMem()) { int alias_idx = phase->C->get_alias_index(adr_type()); mem = mem->as_MergeMem()->memory_at(alias_idx); @@ -1496,6 +1519,8 @@ } } } else if (tp->base() == Type::InstPtr) { + const TypeInstPtr* tinst = tp->is_instptr(); + ciKlass* klass = tinst->klass(); assert( off != Type::OffsetBot || // arrays can be cast to Objects tp->is_oopptr()->klass()->is_java_lang_Object() || @@ -1503,6 +1528,25 @@ phase->C->has_unsafe_access(), "Field accesses must be precise" ); // For oop loads, we expect the _type to be precise + if (OptimizeStringConcat && klass == phase->C->env()->String_klass() && + adr->is_AddP() && off != Type::OffsetBot) { + // For constant Strings treat the fields as compile time constants. + Node* base = adr->in(AddPNode::Base); + if (base->Opcode() == Op_ConP) { + const TypeOopPtr* t = phase->type(base)->isa_oopptr(); + ciObject* string = t->const_oop(); + ciConstant constant = string->as_instance()->field_value_by_offset(off); + if (constant.basic_type() == T_INT) { + return TypeInt::make(constant.as_int()); + } else if (constant.basic_type() == T_ARRAY) { + if (adr->bottom_type()->is_ptr_to_narrowoop()) { + return TypeNarrowOop::make_from_constant(constant.as_object()); + } else { + return TypeOopPtr::make_from_constant(constant.as_object()); + } + } + } + } } else if (tp->base() == Type::KlassPtr) { assert( off != Type::OffsetBot || // arrays can be cast to Objects @@ -2426,6 +2470,31 @@ return mem; } +//----------------------------step_through---------------------------------- +// Return allocation input memory edge if it is different instance +// or itself if it is the one we are looking for. +bool ClearArrayNode::step_through(Node** np, uint instance_id, PhaseTransform* phase) { + Node* n = *np; + assert(n->is_ClearArray(), "sanity"); + intptr_t offset; + AllocateNode* alloc = AllocateNode::Ideal_allocation(n->in(3), phase, offset); + // This method is called only before Allocate nodes are expanded during + // macro nodes expansion. Before that ClearArray nodes are only generated + // in LibraryCallKit::generate_arraycopy() which follows allocations. + assert(alloc != NULL, "should have allocation"); + if (alloc->_idx == instance_id) { + // Can not bypass initialization of the instance we are looking for. + return false; + } + // Otherwise skip it. + InitializeNode* init = alloc->initialization(); + if (init != NULL) + *np = init->in(TypeFunc::Memory); + else + *np = alloc->in(TypeFunc::Memory); + return true; +} + //----------------------------clear_memory------------------------------------- // Generate code to initialize object storage to zero. Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, @@ -2599,7 +2668,30 @@ // Return a node which is more "ideal" than the current node. Strip out // control copies Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) { - return remove_dead_region(phase, can_reshape) ? this : NULL; + if (remove_dead_region(phase, can_reshape)) return this; + + // Eliminate volatile MemBars for scalar replaced objects. + if (can_reshape && req() == (Precedent+1) && + (Opcode() == Op_MemBarAcquire || Opcode() == Op_MemBarVolatile)) { + // Volatile field loads and stores. + Node* my_mem = in(MemBarNode::Precedent); + if (my_mem != NULL && my_mem->is_Mem()) { + const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr(); + // Check for scalar replaced object reference. + if( t_oop != NULL && t_oop->is_known_instance_field() && + t_oop->offset() != Type::OffsetBot && + t_oop->offset() != Type::OffsetTop) { + // Replace MemBar projections by its inputs. + PhaseIterGVN* igvn = phase->is_IterGVN(); + igvn->replace_node(proj_out(TypeFunc::Memory), in(TypeFunc::Memory)); + igvn->replace_node(proj_out(TypeFunc::Control), in(TypeFunc::Control)); + // Must return either the original node (now dead) or a new node + // (Do not return a top here, since that would break the uniqueness of top.) + return new (phase->C, 1) ConINode(TypeInt::ZERO); + } + } + } + return NULL; } //------------------------------Value------------------------------------------ diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/memnode.hpp --- a/hotspot/src/share/vm/opto/memnode.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/memnode.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -717,7 +717,10 @@ //------------------------------ClearArray------------------------------------- class ClearArrayNode: public Node { public: - ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base ) : Node(ctrl,arymem,word_cnt,base) {} + ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base ) + : Node(ctrl,arymem,word_cnt,base) { + init_class_id(Class_ClearArray); + } virtual int Opcode() const; virtual const Type *bottom_type() const { return Type::MEMORY; } // ClearArray modifies array elements, and so affects only the @@ -743,6 +746,9 @@ Node* start_offset, Node* end_offset, PhaseGVN* phase); + // Return allocation input memory edge if it is different instance + // or itself if it is the one we are looking for. + static bool step_through(Node** np, uint instance_id, PhaseTransform* phase); }; //------------------------------StrComp------------------------------------- diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/node.hpp --- a/hotspot/src/share/vm/opto/node.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/node.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -47,6 +47,7 @@ class CatchNode; class CatchProjNode; class CheckCastPPNode; +class ClearArrayNode; class CmpNode; class CodeBuffer; class ConstraintCastNode; @@ -599,8 +600,9 @@ DEFINE_CLASS_ID(BoxLock, Node, 10) DEFINE_CLASS_ID(Add, Node, 11) DEFINE_CLASS_ID(Mul, Node, 12) + DEFINE_CLASS_ID(ClearArray, Node, 13) - _max_classes = ClassMask_Mul + _max_classes = ClassMask_ClearArray }; #undef DEFINE_CLASS_ID @@ -661,18 +663,25 @@ return (_flags & Flag_is_Call) != 0; } + CallNode* isa_Call() const { + return is_Call() ? as_Call() : NULL; + } + CallNode *as_Call() const { // Only for CallNode (not for MachCallNode) assert((_class_id & ClassMask_Call) == Class_Call, "invalid node class"); return (CallNode*)this; } - #define DEFINE_CLASS_QUERY(type) \ - bool is_##type() const { \ + #define DEFINE_CLASS_QUERY(type) \ + bool is_##type() const { \ return ((_class_id & ClassMask_##type) == Class_##type); \ - } \ - type##Node *as_##type() const { \ - assert(is_##type(), "invalid node class"); \ - return (type##Node*)this; \ + } \ + type##Node *as_##type() const { \ + assert(is_##type(), "invalid node class"); \ + return (type##Node*)this; \ + } \ + type##Node* isa_##type() const { \ + return (is_##type()) ? as_##type() : NULL; \ } DEFINE_CLASS_QUERY(AbstractLock) @@ -691,6 +700,7 @@ DEFINE_CLASS_QUERY(CatchProj) DEFINE_CLASS_QUERY(CheckCastPP) DEFINE_CLASS_QUERY(ConstraintCast) + DEFINE_CLASS_QUERY(ClearArray) DEFINE_CLASS_QUERY(CMove) DEFINE_CLASS_QUERY(Cmp) DEFINE_CLASS_QUERY(CountedLoop) @@ -1249,6 +1259,24 @@ #undef I_VDUI_ONLY #undef VDUI_ONLY +// An Iterator that truly follows the iterator pattern. Doesn't +// support deletion but could be made to. +// +// for (SimpleDUIterator i(n); i.has_next(); i.next()) { +// Node* m = i.get(); +// +class SimpleDUIterator : public StackObj { + private: + Node* node; + DUIterator_Fast i; + DUIterator_Fast imax; + public: + SimpleDUIterator(Node* n): node(n), i(n->fast_outs(imax)) {} + bool has_next() { return i < imax; } + void next() { i++; } + Node* get() { return node->fast_out(i); } +}; + //----------------------------------------------------------------------------- // Map dense integer indices to Nodes. Uses classic doubling-array trick. @@ -1290,6 +1318,12 @@ public: Node_List() : Node_Array(Thread::current()->resource_area()), _cnt(0) {} Node_List(Arena *a) : Node_Array(a), _cnt(0) {} + bool contains(Node* n) { + for (uint e = 0; e < size(); e++) { + if (at(e) == n) return true; + } + return false; + } void insert( uint i, Node *n ) { Node_Array::insert(i,n); _cnt++; } void remove( uint i ) { Node_Array::remove(i); _cnt--; } void push( Node *b ) { map(_cnt++,b); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/parse1.cpp --- a/hotspot/src/share/vm/opto/parse1.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/parse1.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -231,12 +231,13 @@ // Use the raw liveness computation to make sure that unexpected // values don't propagate into the OSR frame. - MethodLivenessResult live_locals = method()->raw_liveness_at_bci(osr_bci()); + MethodLivenessResult live_locals = method()->liveness_at_bci(osr_bci()); if (!live_locals.is_valid()) { // Degenerate or breakpointed method. C->record_method_not_compilable("OSR in empty or breakpointed method"); return; } + MethodLivenessResult raw_live_locals = method()->raw_liveness_at_bci(osr_bci()); // Extract the needed locals from the interpreter frame. Node *locals_addr = basic_plus_adr(osr_buf, osr_buf, (max_locals-1)*wordSize); @@ -316,6 +317,10 @@ continue; } } + if (type->basic_type() == T_ADDRESS && !raw_live_locals.at(index)) { + // Skip type check for dead address locals + continue; + } set_local(index, check_interpreter_type(l, type, bad_type_exit)); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/parse3.cpp --- a/hotspot/src/share/vm/opto/parse3.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/parse3.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -240,19 +240,19 @@ // membar is dependent on the store, keeping any other membars generated // below from floating up past the store. int adr_idx = C->get_alias_index(adr_type); - insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx); + insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx, store); // Now place a membar for AliasIdxBot for the unknown yet-to-be-parsed // volatile alias indices. Skip this if the membar is redundant. if (adr_idx != Compile::AliasIdxBot) { - insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot); + insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot, store); } // Finally, place alias-index-specific membars for each volatile index // that isn't the adr_idx membar. Typically there's only 1 or 2. for( int i = Compile::AliasIdxRaw; i < C->num_alias_types(); i++ ) { if (i != adr_idx && C->alias_type(i)->is_volatile()) { - insert_mem_bar_volatile(Op_MemBarVolatile, i); + insert_mem_bar_volatile(Op_MemBarVolatile, i, store); } } } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/parseHelper.cpp --- a/hotspot/src/share/vm/opto/parseHelper.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/parseHelper.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -221,6 +221,14 @@ // Push resultant oop onto stack push(obj); + + // Keep track of whether opportunities exist for StringBuilder + // optimizations. + if (OptimizeStringConcat && + (klass == C->env()->StringBuilder_klass() || + klass == C->env()->StringBuffer_klass())) { + C->set_has_stringbuilder(true); + } } #ifndef PRODUCT diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/phase.hpp --- a/hotspot/src/share/vm/opto/phase.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/phase.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -44,6 +44,7 @@ BlockLayout, // Linear ordering of blocks Register_Allocation, // Register allocation, duh LIVE, // Dragon-book LIVE range problem + StringOpts, // StringBuilder related optimizations Interference_Graph, // Building the IFG Coalesce, // Coalescing copies Ideal_Loop, // Find idealized trip-counted loops diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/phaseX.hpp --- a/hotspot/src/share/vm/opto/phaseX.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/phaseX.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -345,7 +345,11 @@ Node *hash_find(const Node *n) { return _table.hash_find(n); } // Used after parsing to eliminate values that are no longer in program - void remove_useless_nodes(VectorSet &useful) { _table.remove_useless_nodes(useful); } + void remove_useless_nodes(VectorSet &useful) { + _table.remove_useless_nodes(useful); + // this may invalidate cached cons so reset the cache + init_con_caches(); + } virtual ConNode* uncached_makecon(const Type* t); // override from PhaseTransform diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/stringopts.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/opto/stringopts.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,1395 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_stringopts.cpp.incl" + +#define __ kit. + +class StringConcat : public ResourceObj { + private: + PhaseStringOpts* _stringopts; + Node* _string_alloc; + AllocateNode* _begin; // The allocation the begins the pattern + CallStaticJavaNode* _end; // The final call of the pattern. Will either be + // SB.toString or or String.(SB.toString) + bool _multiple; // indicates this is a fusion of two or more + // separate StringBuilders + + Node* _arguments; // The list of arguments to be concatenated + GrowableArray _mode; // into a String along with a mode flag + // indicating how to treat the value. + + Node_List _control; // List of control nodes that will be deleted + Node_List _uncommon_traps; // Uncommon traps that needs to be rewritten + // to restart at the initial JVMState. + public: + // Mode for converting arguments to Strings + enum { + StringMode, + IntMode, + CharMode + }; + + StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): + _end(end), + _begin(NULL), + _multiple(false), + _string_alloc(NULL), + _stringopts(stringopts) { + _arguments = new (_stringopts->C, 1) Node(1); + _arguments->del_req(0); + } + + bool validate_control_flow(); + + void merge_add() { +#if 0 + // XXX This is place holder code for reusing an existing String + // allocation but the logic for checking the state safety is + // probably inadequate at the moment. + CallProjections endprojs; + sc->end()->extract_projections(&endprojs, false); + if (endprojs.resproj != NULL) { + for (SimpleDUIterator i(endprojs.resproj); i.has_next(); i.next()) { + CallStaticJavaNode *use = i.get()->isa_CallStaticJava(); + if (use != NULL && use->method() != NULL && + use->method()->holder() == C->env()->String_klass() && + use->method()->name() == ciSymbol::object_initializer_name() && + use->in(TypeFunc::Parms + 1) == endprojs.resproj) { + // Found useless new String(sb.toString()) so reuse the newly allocated String + // when creating the result instead of allocating a new one. + sc->set_string_alloc(use->in(TypeFunc::Parms)); + sc->set_end(use); + } + } + } +#endif + } + + StringConcat* merge(StringConcat* other, Node* arg); + + void set_allocation(AllocateNode* alloc) { + _begin = alloc; + } + + void append(Node* value, int mode) { + _arguments->add_req(value); + _mode.append(mode); + } + void push(Node* value, int mode) { + _arguments->ins_req(0, value); + _mode.insert_before(0, mode); + } + void push_string(Node* value) { + push(value, StringMode); + } + void push_int(Node* value) { + push(value, IntMode); + } + void push_char(Node* value) { + push(value, CharMode); + } + + Node* argument(int i) { + return _arguments->in(i); + } + void set_argument(int i, Node* value) { + _arguments->set_req(i, value); + } + int num_arguments() { + return _mode.length(); + } + int mode(int i) { + return _mode.at(i); + } + void add_control(Node* ctrl) { + assert(!_control.contains(ctrl), "only push once"); + _control.push(ctrl); + } + CallStaticJavaNode* end() { return _end; } + AllocateNode* begin() { return _begin; } + Node* string_alloc() { return _string_alloc; } + + void eliminate_unneeded_control(); + void eliminate_initialize(InitializeNode* init); + void eliminate_call(CallNode* call); + + void maybe_log_transform() { + CompileLog* log = _stringopts->C->log(); + if (log != NULL) { + log->head("replace_string_concat arguments='%d' string_alloc='%d' multiple='%d'", + num_arguments(), + _string_alloc != NULL, + _multiple); + JVMState* p = _begin->jvms(); + while (p != NULL) { + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); + p = p->caller(); + } + log->tail("replace_string_concat"); + } + } + + void convert_uncommon_traps(GraphKit& kit, const JVMState* jvms) { + for (uint u = 0; u < _uncommon_traps.size(); u++) { + Node* uct = _uncommon_traps.at(u); + + // Build a new call using the jvms state of the allocate + address call_addr = SharedRuntime::uncommon_trap_blob()->instructions_begin(); + const TypeFunc* call_type = OptoRuntime::uncommon_trap_Type(); + int size = call_type->domain()->cnt(); + const TypePtr* no_memory_effects = NULL; + Compile* C = _stringopts->C; + CallStaticJavaNode* call = new (C, size) CallStaticJavaNode(call_type, call_addr, "uncommon_trap", + jvms->bci(), no_memory_effects); + for (int e = 0; e < TypeFunc::Parms; e++) { + call->init_req(e, uct->in(e)); + } + // Set the trap request to record intrinsic failure if this trap + // is taken too many times. Ideally we would handle then traps by + // doing the original bookkeeping in the MDO so that if it caused + // the code to be thrown out we could still recompile and use the + // optimization. Failing the uncommon traps doesn't really mean + // that the optimization is a bad idea but there's no other way to + // do the MDO updates currently. + int trap_request = Deoptimization::make_trap_request(Deoptimization::Reason_intrinsic, + Deoptimization::Action_make_not_entrant); + call->init_req(TypeFunc::Parms, __ intcon(trap_request)); + kit.add_safepoint_edges(call); + + _stringopts->gvn()->transform(call); + C->gvn_replace_by(uct, call); + uct->disconnect_inputs(NULL); + } + } + + void cleanup() { + // disconnect the hook node + _arguments->disconnect_inputs(NULL); + } +}; + + +void StringConcat::eliminate_unneeded_control() { + eliminate_initialize(begin()->initialization()); + for (uint i = 0; i < _control.size(); i++) { + Node* n = _control.at(i); + if (n->is_Call()) { + if (n != _end) { + eliminate_call(n->as_Call()); + } + } else if (n->is_IfTrue()) { + Compile* C = _stringopts->C; + C->gvn_replace_by(n, n->in(0)->in(0)); + C->gvn_replace_by(n->in(0), C->top()); + } + } +} + + +StringConcat* StringConcat::merge(StringConcat* other, Node* arg) { + StringConcat* result = new StringConcat(_stringopts, _end); + for (uint x = 0; x < _control.size(); x++) { + Node* n = _control.at(x); + if (n->is_Call()) { + result->_control.push(n); + } + } + for (uint x = 0; x < other->_control.size(); x++) { + Node* n = other->_control.at(x); + if (n->is_Call()) { + result->_control.push(n); + } + } + assert(result->_control.contains(other->_end), "what?"); + assert(result->_control.contains(_begin), "what?"); + for (int x = 0; x < num_arguments(); x++) { + if (argument(x) == arg) { + // replace the toString result with the all the arguments that + // made up the other StringConcat + for (int y = 0; y < other->num_arguments(); y++) { + result->append(other->argument(y), other->mode(y)); + } + } else { + result->append(argument(x), mode(x)); + } + } + result->set_allocation(other->_begin); + result->_multiple = true; + return result; +} + + +void StringConcat::eliminate_call(CallNode* call) { + Compile* C = _stringopts->C; + CallProjections projs; + call->extract_projections(&projs, false); + if (projs.fallthrough_catchproj != NULL) { + C->gvn_replace_by(projs.fallthrough_catchproj, call->in(TypeFunc::Control)); + } + if (projs.fallthrough_memproj != NULL) { + C->gvn_replace_by(projs.fallthrough_memproj, call->in(TypeFunc::Memory)); + } + if (projs.catchall_memproj != NULL) { + C->gvn_replace_by(projs.catchall_memproj, C->top()); + } + if (projs.fallthrough_ioproj != NULL) { + C->gvn_replace_by(projs.fallthrough_ioproj, call->in(TypeFunc::I_O)); + } + if (projs.catchall_ioproj != NULL) { + C->gvn_replace_by(projs.catchall_ioproj, C->top()); + } + if (projs.catchall_catchproj != NULL) { + // EA can't cope with the partially collapsed graph this + // creates so put it on the worklist to be collapsed later. + for (SimpleDUIterator i(projs.catchall_catchproj); i.has_next(); i.next()) { + Node *use = i.get(); + int opc = use->Opcode(); + if (opc == Op_CreateEx || opc == Op_Region) { + _stringopts->record_dead_node(use); + } + } + C->gvn_replace_by(projs.catchall_catchproj, C->top()); + } + if (projs.resproj != NULL) { + C->gvn_replace_by(projs.resproj, C->top()); + } + C->gvn_replace_by(call, C->top()); +} + +void StringConcat::eliminate_initialize(InitializeNode* init) { + Compile* C = _stringopts->C; + + // Eliminate Initialize node. + assert(init->outcnt() <= 2, "only a control and memory projection expected"); + assert(init->req() <= InitializeNode::RawStores, "no pending inits"); + Node *ctrl_proj = init->proj_out(TypeFunc::Control); + if (ctrl_proj != NULL) { + C->gvn_replace_by(ctrl_proj, init->in(TypeFunc::Control)); + } + Node *mem_proj = init->proj_out(TypeFunc::Memory); + if (mem_proj != NULL) { + Node *mem = init->in(TypeFunc::Memory); + C->gvn_replace_by(mem_proj, mem); + } + C->gvn_replace_by(init, C->top()); + init->disconnect_inputs(NULL); +} + +Node_List PhaseStringOpts::collect_toString_calls() { + Node_List string_calls; + Node_List worklist; + + _visited.Clear(); + + // Prime the worklist + for (uint i = 1; i < C->root()->len(); i++) { + Node* n = C->root()->in(i); + if (n != NULL && !_visited.test_set(n->_idx)) { + worklist.push(n); + } + } + + while (worklist.size() > 0) { + Node* ctrl = worklist.pop(); + if (ctrl->is_CallStaticJava()) { + CallStaticJavaNode* csj = ctrl->as_CallStaticJava(); + ciMethod* m = csj->method(); + if (m != NULL && + (m->intrinsic_id() == vmIntrinsics::_StringBuffer_toString || + m->intrinsic_id() == vmIntrinsics::_StringBuilder_toString)) { + string_calls.push(csj); + } + } + if (ctrl->in(0) != NULL && !_visited.test_set(ctrl->in(0)->_idx)) { + worklist.push(ctrl->in(0)); + } + if (ctrl->is_Region()) { + for (uint i = 1; i < ctrl->len(); i++) { + if (ctrl->in(i) != NULL && !_visited.test_set(ctrl->in(i)->_idx)) { + worklist.push(ctrl->in(i)); + } + } + } + } + return string_calls; +} + + +StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) { + ciMethod* m = call->method(); + ciSymbol* string_sig; + ciSymbol* int_sig; + ciSymbol* char_sig; + if (m->holder() == C->env()->StringBuilder_klass()) { + string_sig = ciSymbol::String_StringBuilder_signature(); + int_sig = ciSymbol::int_StringBuilder_signature(); + char_sig = ciSymbol::char_StringBuilder_signature(); + } else if (m->holder() == C->env()->StringBuffer_klass()) { + string_sig = ciSymbol::String_StringBuffer_signature(); + int_sig = ciSymbol::int_StringBuffer_signature(); + char_sig = ciSymbol::char_StringBuffer_signature(); + } else { + return NULL; + } +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print("considering toString call in "); + call->jvms()->dump_spec(tty); tty->cr(); + } +#endif + + StringConcat* sc = new StringConcat(this, call); + + AllocateNode* alloc = NULL; + InitializeNode* init = NULL; + + // possible opportunity for StringBuilder fusion + CallStaticJavaNode* cnode = call; + while (cnode) { + Node* recv = cnode->in(TypeFunc::Parms)->uncast(); + if (recv->is_Proj()) { + recv = recv->in(0); + } + cnode = recv->isa_CallStaticJava(); + if (cnode == NULL) { + alloc = recv->isa_Allocate(); + if (alloc == NULL) { + break; + } + // Find the constructor call + Node* result = alloc->result_cast(); + if (result == NULL || !result->is_CheckCastPP()) { + // strange looking allocation +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print("giving up because allocation looks strange "); + alloc->jvms()->dump_spec(tty); tty->cr(); + } +#endif + break; + } + Node* constructor = NULL; + for (SimpleDUIterator i(result); i.has_next(); i.next()) { + CallStaticJavaNode *use = i.get()->isa_CallStaticJava(); + if (use != NULL && use->method() != NULL && + use->method()->name() == ciSymbol::object_initializer_name() && + use->method()->holder() == m->holder()) { + // Matched the constructor. + ciSymbol* sig = use->method()->signature()->as_symbol(); + if (sig == ciSymbol::void_method_signature() || + sig == ciSymbol::int_void_signature() || + sig == ciSymbol::string_void_signature()) { + if (sig == ciSymbol::string_void_signature()) { + // StringBuilder(String) so pick this up as the first argument + assert(use->in(TypeFunc::Parms + 1) != NULL, "what?"); + sc->push_string(use->in(TypeFunc::Parms + 1)); + } + // The int variant takes an initial size for the backing + // array so just treat it like the void version. + constructor = use; + } else { +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print("unexpected constructor signature: %s", sig->as_utf8()); + } +#endif + } + break; + } + } + if (constructor == NULL) { + // couldn't find constructor +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print("giving up because couldn't find constructor "); + alloc->jvms()->dump_spec(tty); + } +#endif + break; + } + + // Walked all the way back and found the constructor call so see + // if this call converted into a direct string concatenation. + sc->add_control(call); + sc->add_control(constructor); + sc->add_control(alloc); + sc->set_allocation(alloc); + if (sc->validate_control_flow()) { + return sc; + } else { + return NULL; + } + } else if (cnode->method() == NULL) { + break; + } else if (cnode->method()->holder() == m->holder() && + cnode->method()->name() == ciSymbol::append_name() && + (cnode->method()->signature()->as_symbol() == string_sig || + cnode->method()->signature()->as_symbol() == char_sig || + cnode->method()->signature()->as_symbol() == int_sig)) { + sc->add_control(cnode); + Node* arg = cnode->in(TypeFunc::Parms + 1); + if (cnode->method()->signature()->as_symbol() == int_sig) { + sc->push_int(arg); + } else if (cnode->method()->signature()->as_symbol() == char_sig) { + sc->push_char(arg); + } else { + if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) { + CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava(); + if (csj->method() != NULL && + csj->method()->holder() == C->env()->Integer_klass() && + csj->method()->name() == ciSymbol::toString_name()) { + sc->add_control(csj); + sc->push_int(csj->in(TypeFunc::Parms)); + continue; + } + } + sc->push_string(arg); + } + continue; + } else { + // some unhandled signature +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print("giving up because encountered unexpected signature "); + cnode->tf()->dump(); tty->cr(); + cnode->in(TypeFunc::Parms + 1)->dump(); + } +#endif + break; + } + } + return NULL; +} + + +PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*): + Phase(StringOpts), + _gvn(gvn), + _visited(Thread::current()->resource_area()) { + + assert(OptimizeStringConcat, "shouldn't be here"); + + size_table_field = C->env()->Integer_klass()->get_field_by_name(ciSymbol::make("sizeTable"), + ciSymbol::make("[I"), true); + if (size_table_field == NULL) { + // Something wrong so give up. + assert(false, "why can't we find Integer.sizeTable?"); + return; + } + + // Collect the types needed to talk about the various slices of memory + const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), + false, NULL, 0); + + const TypePtr* value_field_type = string_type->add_offset(java_lang_String::value_offset_in_bytes()); + const TypePtr* offset_field_type = string_type->add_offset(java_lang_String::offset_offset_in_bytes()); + const TypePtr* count_field_type = string_type->add_offset(java_lang_String::count_offset_in_bytes()); + + value_field_idx = C->get_alias_index(value_field_type); + count_field_idx = C->get_alias_index(count_field_type); + offset_field_idx = C->get_alias_index(offset_field_type); + char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS); + + // For each locally allocated StringBuffer see if the usages can be + // collapsed into a single String construction. + + // Run through the list of allocation looking for SB.toString to see + // if it's possible to fuse the usage of the SB into a single String + // construction. + GrowableArray concats; + Node_List toStrings = collect_toString_calls(); + while (toStrings.size() > 0) { + StringConcat* sc = build_candidate(toStrings.pop()->as_CallStaticJava()); + if (sc != NULL) { + concats.push(sc); + } + } + + // try to coalesce separate concats + restart: + for (int c = 0; c < concats.length(); c++) { + StringConcat* sc = concats.at(c); + for (int i = 0; i < sc->num_arguments(); i++) { + Node* arg = sc->argument(i); + if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) { + CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava(); + if (csj->method() != NULL && + (csj->method()->holder() == C->env()->StringBuffer_klass() || + csj->method()->holder() == C->env()->StringBuilder_klass()) && + csj->method()->name() == ciSymbol::toString_name()) { + for (int o = 0; o < concats.length(); o++) { + if (c == o) continue; + StringConcat* other = concats.at(o); + if (other->end() == csj) { +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print_cr("considering stacked concats"); + } +#endif + + StringConcat* merged = sc->merge(other, arg); + if (merged->validate_control_flow()) { +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print_cr("stacking would succeed"); + } +#endif + if (c < o) { + concats.remove_at(o); + concats.at_put(c, merged); + } else { + concats.remove_at(c); + concats.at_put(o, merged); + } + goto restart; + } else { +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print_cr("stacking would fail"); + } +#endif + } + } + } + } + } + } + } + + + for (int c = 0; c < concats.length(); c++) { + StringConcat* sc = concats.at(c); + replace_string_concat(sc); + } + + remove_dead_nodes(); +} + +void PhaseStringOpts::record_dead_node(Node* dead) { + dead_worklist.push(dead); +} + +void PhaseStringOpts::remove_dead_nodes() { + // Delete any dead nodes to make things clean enough that escape + // analysis doesn't get unhappy. + while (dead_worklist.size() > 0) { + Node* use = dead_worklist.pop(); + int opc = use->Opcode(); + switch (opc) { + case Op_Region: { + uint i = 1; + for (i = 1; i < use->req(); i++) { + if (use->in(i) != C->top()) { + break; + } + } + if (i >= use->req()) { + for (SimpleDUIterator i(use); i.has_next(); i.next()) { + Node* m = i.get(); + if (m->is_Phi()) { + dead_worklist.push(m); + } + } + C->gvn_replace_by(use, C->top()); + } + break; + } + case Op_AddP: + case Op_CreateEx: { + // Recurisvely clean up references to CreateEx so EA doesn't + // get unhappy about the partially collapsed graph. + for (SimpleDUIterator i(use); i.has_next(); i.next()) { + Node* m = i.get(); + if (m->is_AddP()) { + dead_worklist.push(m); + } + } + C->gvn_replace_by(use, C->top()); + break; + } + case Op_Phi: + if (use->in(0) == C->top()) { + C->gvn_replace_by(use, C->top()); + } + break; + } + } +} + + +bool StringConcat::validate_control_flow() { + // We found all the calls and arguments now lets see if it's + // safe to transform the graph as we would expect. + + // Check to see if this resulted in too many uncommon traps previously + if (Compile::current()->too_many_traps(_begin->jvms()->method(), _begin->jvms()->bci(), + Deoptimization::Reason_intrinsic)) { + return false; + } + + // Walk backwards over the control flow from toString to the + // allocation and make sure all the control flow is ok. This + // means it's either going to be eliminated once the calls are + // removed or it can safely be transformed into an uncommon + // trap. + + int null_check_count = 0; + Unique_Node_List ctrl_path; + + assert(_control.contains(_begin), "missing"); + assert(_control.contains(_end), "missing"); + + // Collect the nodes that we know about and will eliminate into ctrl_path + for (uint i = 0; i < _control.size(); i++) { + // Push the call and it's control projection + Node* n = _control.at(i); + if (n->is_Allocate()) { + AllocateNode* an = n->as_Allocate(); + InitializeNode* init = an->initialization(); + ctrl_path.push(init); + ctrl_path.push(init->as_Multi()->proj_out(0)); + } + if (n->is_Call()) { + CallNode* cn = n->as_Call(); + ctrl_path.push(cn); + ctrl_path.push(cn->proj_out(0)); + ctrl_path.push(cn->proj_out(0)->unique_out()); + ctrl_path.push(cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0)); + } else { + ShouldNotReachHere(); + } + } + + // Skip backwards through the control checking for unexpected contro flow + Node* ptr = _end; + bool fail = false; + while (ptr != _begin) { + if (ptr->is_Call() && ctrl_path.member(ptr)) { + ptr = ptr->in(0); + } else if (ptr->is_CatchProj() && ctrl_path.member(ptr)) { + ptr = ptr->in(0)->in(0)->in(0); + assert(ctrl_path.member(ptr), "should be a known piece of control"); + } else if (ptr->is_IfTrue()) { + IfNode* iff = ptr->in(0)->as_If(); + BoolNode* b = iff->in(1)->isa_Bool(); + Node* cmp = b->in(1); + Node* v1 = cmp->in(1); + Node* v2 = cmp->in(2); + Node* otherproj = iff->proj_out(1 - ptr->as_Proj()->_con); + + // Null check of the return of append which can simply be eliminated + if (b->_test._test == BoolTest::ne && + v2->bottom_type() == TypePtr::NULL_PTR && + v1->is_Proj() && ctrl_path.member(v1->in(0))) { + // NULL check of the return value of the append + null_check_count++; + if (otherproj->outcnt() == 1) { + CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava(); + if (call != NULL && call->_name != NULL && strcmp(call->_name, "uncommon_trap") == 0) { + ctrl_path.push(call); + } + } + _control.push(ptr); + ptr = ptr->in(0)->in(0); + continue; + } + + // A test which leads to an uncommon trap which should be safe. + // Later this trap will be converted into a trap that restarts + // at the beginning. + if (otherproj->outcnt() == 1) { + CallStaticJavaNode* call = otherproj->unique_out()->isa_CallStaticJava(); + if (call != NULL && call->_name != NULL && strcmp(call->_name, "uncommon_trap") == 0) { + // control flow leads to uct so should be ok + _uncommon_traps.push(call); + ctrl_path.push(call); + ptr = ptr->in(0)->in(0); + continue; + } + } + +#ifndef PRODUCT + // Some unexpected control flow we don't know how to handle. + if (PrintOptimizeStringConcat) { + tty->print_cr("failing with unknown test"); + b->dump(); + cmp->dump(); + v1->dump(); + v2->dump(); + tty->cr(); + } +#endif + break; + } else if (ptr->is_Proj() && ptr->in(0)->is_Initialize()) { + ptr = ptr->in(0)->in(0); + } else if (ptr->is_Region()) { + Node* copy = ptr->as_Region()->is_copy(); + if (copy != NULL) { + ptr = copy; + continue; + } + if (ptr->req() == 3 && + ptr->in(1) != NULL && ptr->in(1)->is_Proj() && + ptr->in(2) != NULL && ptr->in(2)->is_Proj() && + ptr->in(1)->in(0) == ptr->in(2)->in(0) && + ptr->in(1)->in(0) != NULL && ptr->in(1)->in(0)->is_If()) { + // Simple diamond. + // XXX should check for possibly merging stores. simple data merges are ok. + ptr = ptr->in(1)->in(0)->in(0); + continue; + } +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print_cr("fusion would fail for region"); + _begin->dump(); + ptr->dump(2); + } +#endif + fail = true; + break; + } else { + // other unknown control + if (!fail) { +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print_cr("fusion would fail for"); + _begin->dump(); + } +#endif + fail = true; + } +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + ptr->dump(); + } +#endif + ptr = ptr->in(0); + } + } +#ifndef PRODUCT + if (PrintOptimizeStringConcat && fail) { + tty->cr(); + } +#endif + if (fail) return !fail; + + // Validate that all these results produced are contained within + // this cluster of objects. First collect all the results produced + // by calls in the region. + _stringopts->_visited.Clear(); + Node_List worklist; + Node* final_result = _end->proj_out(TypeFunc::Parms); + for (uint i = 0; i < _control.size(); i++) { + CallNode* cnode = _control.at(i)->isa_Call(); + if (cnode != NULL) { + _stringopts->_visited.test_set(cnode->_idx); + } + Node* result = cnode != NULL ? cnode->proj_out(TypeFunc::Parms) : NULL; + if (result != NULL && result != final_result) { + worklist.push(result); + } + } + + Node* last_result = NULL; + while (worklist.size() > 0) { + Node* result = worklist.pop(); + if (_stringopts->_visited.test_set(result->_idx)) + continue; + for (SimpleDUIterator i(result); i.has_next(); i.next()) { + Node *use = i.get(); + if (ctrl_path.member(use)) { + // already checked this + continue; + } + int opc = use->Opcode(); + if (opc == Op_CmpP || opc == Op_Node) { + ctrl_path.push(use); + continue; + } + if (opc == Op_CastPP || opc == Op_CheckCastPP) { + for (SimpleDUIterator j(use); j.has_next(); j.next()) { + worklist.push(j.get()); + } + worklist.push(use->in(1)); + ctrl_path.push(use); + continue; + } +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + if (result != last_result) { + last_result = result; + tty->print_cr("extra uses for result:"); + last_result->dump(); + } + use->dump(); + } +#endif + fail = true; + break; + } + } + +#ifndef PRODUCT + if (PrintOptimizeStringConcat && !fail) { + ttyLocker ttyl; + tty->cr(); + tty->print("fusion would succeed (%d %d) for ", null_check_count, _uncommon_traps.size()); + _begin->jvms()->dump_spec(tty); tty->cr(); + for (int i = 0; i < num_arguments(); i++) { + argument(i)->dump(); + } + _control.dump(); + tty->cr(); + } +#endif + + return !fail; +} + +Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) { + const TypeKlassPtr* klass_type = TypeKlassPtr::make(field->holder()); + Node* klass_node = __ makecon(klass_type); + BasicType bt = field->layout_type(); + ciType* field_klass = field->type(); + + const Type *type; + if( bt == T_OBJECT ) { + if (!field->type()->is_loaded()) { + type = TypeInstPtr::BOTTOM; + } else if (field->is_constant()) { + // This can happen if the constant oop is non-perm. + ciObject* con = field->constant_value().as_object(); + // Do not "join" in the previous type; it doesn't add value, + // and may yield a vacuous result if the field is of interface type. + type = TypeOopPtr::make_from_constant(con)->isa_oopptr(); + assert(type != NULL, "field singleton type must be consistent"); + } else { + type = TypeOopPtr::make_from_klass(field_klass->as_klass()); + } + } else { + type = Type::get_const_basic_type(bt); + } + + return kit.make_load(NULL, kit.basic_plus_adr(klass_node, field->offset_in_bytes()), + type, T_OBJECT, + C->get_alias_index(klass_type->add_offset(field->offset_in_bytes()))); +} + +Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) { + RegionNode *final_merge = new (C, 3) RegionNode(3); + kit.gvn().set_type(final_merge, Type::CONTROL); + Node* final_size = new (C, 3) PhiNode(final_merge, TypeInt::INT); + kit.gvn().set_type(final_size, TypeInt::INT); + + IfNode* iff = kit.create_and_map_if(kit.control(), + __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne), + PROB_FAIR, COUNT_UNKNOWN); + Node* is_min = __ IfFalse(iff); + final_merge->init_req(1, is_min); + final_size->init_req(1, __ intcon(11)); + + kit.set_control(__ IfTrue(iff)); + if (kit.stopped()) { + final_merge->init_req(2, C->top()); + final_size->init_req(2, C->top()); + } else { + + // int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); + RegionNode *r = new (C, 3) RegionNode(3); + kit.gvn().set_type(r, Type::CONTROL); + Node *phi = new (C, 3) PhiNode(r, TypeInt::INT); + kit.gvn().set_type(phi, TypeInt::INT); + Node *size = new (C, 3) PhiNode(r, TypeInt::INT); + kit.gvn().set_type(size, TypeInt::INT); + Node* chk = __ CmpI(arg, __ intcon(0)); + Node* p = __ Bool(chk, BoolTest::lt); + IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_FAIR, COUNT_UNKNOWN); + Node* lessthan = __ IfTrue(iff); + Node* greaterequal = __ IfFalse(iff); + r->init_req(1, lessthan); + phi->init_req(1, __ SubI(__ intcon(0), arg)); + size->init_req(1, __ intcon(1)); + r->init_req(2, greaterequal); + phi->init_req(2, arg); + size->init_req(2, __ intcon(0)); + kit.set_control(r); + C->record_for_igvn(r); + C->record_for_igvn(phi); + C->record_for_igvn(size); + + // for (int i=0; ; i++) + // if (x <= sizeTable[i]) + // return i+1; + RegionNode *loop = new (C, 3) RegionNode(3); + loop->init_req(1, kit.control()); + kit.gvn().set_type(loop, Type::CONTROL); + + Node *index = new (C, 3) PhiNode(loop, TypeInt::INT); + index->init_req(1, __ intcon(0)); + kit.gvn().set_type(index, TypeInt::INT); + kit.set_control(loop); + Node* sizeTable = fetch_static_field(kit, size_table_field); + + Node* value = kit.load_array_element(NULL, sizeTable, index, TypeAryPtr::INTS); + C->record_for_igvn(value); + Node* limit = __ CmpI(phi, value); + Node* limitb = __ Bool(limit, BoolTest::le); + IfNode* iff2 = kit.create_and_map_if(kit.control(), limitb, PROB_MIN, COUNT_UNKNOWN); + Node* lessEqual = __ IfTrue(iff2); + Node* greater = __ IfFalse(iff2); + + loop->init_req(2, greater); + index->init_req(2, __ AddI(index, __ intcon(1))); + + kit.set_control(lessEqual); + C->record_for_igvn(loop); + C->record_for_igvn(index); + + final_merge->init_req(2, kit.control()); + final_size->init_req(2, __ AddI(__ AddI(index, size), __ intcon(1))); + } + + kit.set_control(final_merge); + C->record_for_igvn(final_merge); + C->record_for_igvn(final_size); + + return final_size; +} + +void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, Node* start, Node* end) { + RegionNode *final_merge = new (C, 4) RegionNode(4); + kit.gvn().set_type(final_merge, Type::CONTROL); + Node *final_mem = PhiNode::make(final_merge, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS); + kit.gvn().set_type(final_mem, Type::MEMORY); + + // need to handle Integer.MIN_VALUE specially because negating doesn't make it positive + { + // i == MIN_VALUE + IfNode* iff = kit.create_and_map_if(kit.control(), + __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne), + PROB_FAIR, COUNT_UNKNOWN); + + Node* old_mem = kit.memory(char_adr_idx); + + kit.set_control(__ IfFalse(iff)); + if (kit.stopped()) { + // Statically not equal to MIN_VALUE so this path is dead + final_merge->init_req(3, kit.control()); + } else { + copy_string(kit, __ makecon(TypeInstPtr::make(C->env()->the_min_jint_string())), + char_array, start); + final_merge->init_req(3, kit.control()); + final_mem->init_req(3, kit.memory(char_adr_idx)); + } + + kit.set_control(__ IfTrue(iff)); + kit.set_memory(old_mem, char_adr_idx); + } + + + // Simplified version of Integer.getChars + + // int q, r; + // int charPos = index; + Node* charPos = end; + + // char sign = 0; + + Node* i = arg; + Node* sign = __ intcon(0); + + // if (i < 0) { + // sign = '-'; + // i = -i; + // } + { + IfNode* iff = kit.create_and_map_if(kit.control(), + __ Bool(__ CmpI(arg, __ intcon(0)), BoolTest::lt), + PROB_FAIR, COUNT_UNKNOWN); + + RegionNode *merge = new (C, 3) RegionNode(3); + kit.gvn().set_type(merge, Type::CONTROL); + i = new (C, 3) PhiNode(merge, TypeInt::INT); + kit.gvn().set_type(i, TypeInt::INT); + sign = new (C, 3) PhiNode(merge, TypeInt::INT); + kit.gvn().set_type(sign, TypeInt::INT); + + merge->init_req(1, __ IfTrue(iff)); + i->init_req(1, __ SubI(__ intcon(0), arg)); + sign->init_req(1, __ intcon('-')); + merge->init_req(2, __ IfFalse(iff)); + i->init_req(2, arg); + sign->init_req(2, __ intcon(0)); + + kit.set_control(merge); + + C->record_for_igvn(merge); + C->record_for_igvn(i); + C->record_for_igvn(sign); + } + + // for (;;) { + // q = i / 10; + // r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... + // buf [--charPos] = digits [r]; + // i = q; + // if (i == 0) break; + // } + + { + RegionNode *head = new (C, 3) RegionNode(3); + head->init_req(1, kit.control()); + kit.gvn().set_type(head, Type::CONTROL); + Node *i_phi = new (C, 3) PhiNode(head, TypeInt::INT); + i_phi->init_req(1, i); + kit.gvn().set_type(i_phi, TypeInt::INT); + charPos = PhiNode::make(head, charPos); + kit.gvn().set_type(charPos, TypeInt::INT); + Node *mem = PhiNode::make(head, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS); + kit.gvn().set_type(mem, Type::MEMORY); + kit.set_control(head); + kit.set_memory(mem, char_adr_idx); + + Node* q = __ DivI(kit.null(), i_phi, __ intcon(10)); + Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)), + __ LShiftI(q, __ intcon(1)))); + Node* m1 = __ SubI(charPos, __ intcon(1)); + Node* ch = __ AddI(r, __ intcon('0')); + + Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), + ch, T_CHAR, char_adr_idx); + + + IfNode* iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne), + PROB_FAIR, COUNT_UNKNOWN); + Node* ne = __ IfTrue(iff); + Node* eq = __ IfFalse(iff); + + head->init_req(2, ne); + mem->init_req(2, st); + i_phi->init_req(2, q); + charPos->init_req(2, m1); + + charPos = m1; + + kit.set_control(eq); + kit.set_memory(st, char_adr_idx); + + C->record_for_igvn(head); + C->record_for_igvn(mem); + C->record_for_igvn(i_phi); + C->record_for_igvn(charPos); + } + + { + // if (sign != 0) { + // buf [--charPos] = sign; + // } + IfNode* iff = kit.create_and_map_if(kit.control(), + __ Bool(__ CmpI(sign, __ intcon(0)), BoolTest::ne), + PROB_FAIR, COUNT_UNKNOWN); + + final_merge->init_req(2, __ IfFalse(iff)); + final_mem->init_req(2, kit.memory(char_adr_idx)); + + kit.set_control(__ IfTrue(iff)); + if (kit.stopped()) { + final_merge->init_req(1, C->top()); + final_mem->init_req(1, C->top()); + } else { + Node* m1 = __ SubI(charPos, __ intcon(1)); + Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR), + sign, T_CHAR, char_adr_idx); + + final_merge->init_req(1, kit.control()); + final_mem->init_req(1, st); + } + + kit.set_control(final_merge); + kit.set_memory(final_mem, char_adr_idx); + + C->record_for_igvn(final_merge); + C->record_for_igvn(final_mem); + } +} + + +Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) { + Node* string = str; + Node* offset = kit.make_load(NULL, + kit.basic_plus_adr(string, string, java_lang_String::offset_offset_in_bytes()), + TypeInt::INT, T_INT, offset_field_idx); + Node* count = kit.make_load(NULL, + kit.basic_plus_adr(string, string, java_lang_String::count_offset_in_bytes()), + TypeInt::INT, T_INT, count_field_idx); + const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull, + TypeAry::make(TypeInt::CHAR,TypeInt::POS), + ciTypeArrayKlass::make(T_CHAR), true, 0); + Node* value = kit.make_load(NULL, + kit.basic_plus_adr(string, string, java_lang_String::value_offset_in_bytes()), + value_type, T_OBJECT, value_field_idx); + + // copy the contents + if (offset->is_Con() && count->is_Con() && value->is_Con() && count->get_int() < unroll_string_copy_length) { + // For small constant strings just emit individual stores. + // A length of 6 seems like a good space/speed tradeof. + int c = count->get_int(); + int o = offset->get_int(); + const TypeOopPtr* t = kit.gvn().type(value)->isa_oopptr(); + ciTypeArray* value_array = t->const_oop()->as_type_array(); + for (int e = 0; e < c; e++) { + __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), + __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx); + start = __ AddI(start, __ intcon(1)); + } + } else { + Node* src_ptr = kit.array_element_address(value, offset, T_CHAR); + Node* dst_ptr = kit.array_element_address(char_array, start, T_CHAR); + Node* c = count; + Node* extra = NULL; +#ifdef _LP64 + c = __ ConvI2L(c); + extra = C->top(); +#endif + Node* call = kit.make_runtime_call(GraphKit::RC_LEAF|GraphKit::RC_NO_FP, + OptoRuntime::fast_arraycopy_Type(), + CAST_FROM_FN_PTR(address, StubRoutines::jshort_disjoint_arraycopy()), + "jshort_disjoint_arraycopy", TypeAryPtr::CHARS, + src_ptr, dst_ptr, c, extra); + start = __ AddI(start, count); + } + return start; +} + + +void PhaseStringOpts::replace_string_concat(StringConcat* sc) { + // Log a little info about the transformation + sc->maybe_log_transform(); + + // pull the JVMState of the allocation into a SafePointNode to serve as + // as a shim for the insertion of the new code. + JVMState* jvms = sc->begin()->jvms()->clone_shallow(C); + uint size = sc->begin()->req(); + SafePointNode* map = new (C, size) SafePointNode(size, jvms); + + // copy the control and memory state from the final call into our + // new starting state. This allows any preceeding tests to feed + // into the new section of code. + for (uint i1 = 0; i1 < TypeFunc::Parms; i1++) { + map->init_req(i1, sc->end()->in(i1)); + } + // blow away old allocation arguments + for (uint i1 = TypeFunc::Parms; i1 < jvms->debug_start(); i1++) { + map->init_req(i1, C->top()); + } + // Copy the rest of the inputs for the JVMState + for (uint i1 = jvms->debug_start(); i1 < sc->begin()->req(); i1++) { + map->init_req(i1, sc->begin()->in(i1)); + } + // Make sure the memory state is a MergeMem for parsing. + if (!map->in(TypeFunc::Memory)->is_MergeMem()) { + map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory))); + } + + jvms->set_map(map); + map->ensure_stack(jvms, jvms->method()->max_stack()); + + + // disconnect all the old StringBuilder calls from the graph + sc->eliminate_unneeded_control(); + + // At this point all the old work has been completely removed from + // the graph and the saved JVMState exists at the point where the + // final toString call used to be. + GraphKit kit(jvms); + + // There may be uncommon traps which are still using the + // intermediate states and these need to be rewritten to point at + // the JVMState at the beginning of the transformation. + sc->convert_uncommon_traps(kit, jvms); + + // Now insert the logic to compute the size of the string followed + // by all the logic to construct array and resulting string. + + Node* null_string = __ makecon(TypeInstPtr::make(C->env()->the_null_string())); + + // Create a region for the overflow checks to merge into. + int args = MAX2(sc->num_arguments(), 1); + RegionNode* overflow = new (C, args) RegionNode(args); + kit.gvn().set_type(overflow, Type::CONTROL); + + // Create a hook node to hold onto the individual sizes since they + // are need for the copying phase. + Node* string_sizes = new (C, args) Node(args); + + Node* length = __ intcon(0); + for (int argi = 0; argi < sc->num_arguments(); argi++) { + Node* arg = sc->argument(argi); + switch (sc->mode(argi)) { + case StringConcat::IntMode: { + Node* string_size = int_stringSize(kit, arg); + + // accumulate total + length = __ AddI(length, string_size); + + // Cache this value for the use by int_toString + string_sizes->init_req(argi, string_size); + break; + } + case StringConcat::StringMode: { + const Type* type = kit.gvn().type(arg); + if (type == TypePtr::NULL_PTR) { + // replace the argument with the null checked version + arg = null_string; + sc->set_argument(argi, arg); + } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) { + // s = s != null ? s : "null"; + // length = length + (s.count - s.offset); + RegionNode *r = new (C, 3) RegionNode(3); + kit.gvn().set_type(r, Type::CONTROL); + Node *phi = new (C, 3) PhiNode(r, type->join(TypeInstPtr::NOTNULL)); + kit.gvn().set_type(phi, phi->bottom_type()); + Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); + IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); + Node* notnull = __ IfTrue(iff); + Node* isnull = __ IfFalse(iff); + r->init_req(1, notnull); + phi->init_req(1, arg); + r->init_req(2, isnull); + phi->init_req(2, null_string); + kit.set_control(r); + C->record_for_igvn(r); + C->record_for_igvn(phi); + // replace the argument with the null checked version + arg = phi; + sc->set_argument(argi, arg); + } + // Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset), + // TypeInt::INT, T_INT, offset_field_idx); + Node* count = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, java_lang_String::count_offset_in_bytes()), + TypeInt::INT, T_INT, count_field_idx); + length = __ AddI(length, count); + string_sizes->init_req(argi, NULL); + break; + } + case StringConcat::CharMode: { + // one character only + length = __ AddI(length, __ intcon(1)); + break; + } + default: + ShouldNotReachHere(); + } + if (argi > 0) { + // Check that the sum hasn't overflowed + IfNode* iff = kit.create_and_map_if(kit.control(), + __ Bool(__ CmpI(length, __ intcon(0)), BoolTest::lt), + PROB_MIN, COUNT_UNKNOWN); + kit.set_control(__ IfFalse(iff)); + overflow->set_req(argi, __ IfTrue(iff)); + } + } + + { + // Hook + PreserveJVMState pjvms(&kit); + kit.set_control(overflow); + kit.uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_make_not_entrant); + } + + // length now contains the number of characters needed for the + // char[] so create a new AllocateArray for the char[] + Node* char_array = NULL; + { + PreserveReexecuteState preexecs(&kit); + // The original jvms is for an allocation of either a String or + // StringBuffer so no stack adjustment is necessary for proper + // reexecution. If we deoptimize in the slow path the bytecode + // will be reexecuted and the char[] allocation will be thrown away. + kit.jvms()->set_should_reexecute(true); + char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))), + length, 1); + } + + // Mark the allocation so that zeroing is skipped since the code + // below will overwrite the entire array + AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn); + char_alloc->maybe_set_complete(_gvn); + + // Now copy the string representations into the final char[] + Node* start = __ intcon(0); + for (int argi = 0; argi < sc->num_arguments(); argi++) { + Node* arg = sc->argument(argi); + switch (sc->mode(argi)) { + case StringConcat::IntMode: { + Node* end = __ AddI(start, string_sizes->in(argi)); + // getChars words backwards so pass the ending point as well as the start + int_getChars(kit, arg, char_array, start, end); + start = end; + break; + } + case StringConcat::StringMode: { + start = copy_string(kit, arg, char_array, start); + break; + } + case StringConcat::CharMode: { + __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR), + arg, T_CHAR, char_adr_idx); + start = __ AddI(start, __ intcon(1)); + break; + } + default: + ShouldNotReachHere(); + } + } + + // If we're not reusing an existing String allocation then allocate one here. + Node* result = sc->string_alloc(); + if (result == NULL) { + PreserveReexecuteState preexecs(&kit); + // The original jvms is for an allocation of either a String or + // StringBuffer so no stack adjustment is necessary for proper + // reexecution. + kit.jvms()->set_should_reexecute(true); + result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass()))); + } + + // Intialize the string + kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::offset_offset_in_bytes()), + __ intcon(0), T_INT, offset_field_idx); + kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::count_offset_in_bytes()), + length, T_INT, count_field_idx); + kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::value_offset_in_bytes()), + char_array, T_OBJECT, value_field_idx); + + // hook up the outgoing control and result + kit.replace_call(sc->end(), result); + + // Unhook any hook nodes + string_sizes->disconnect_inputs(NULL); + sc->cleanup(); +} diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/stringopts.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/opto/stringopts.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +class StringConcat; + +class PhaseStringOpts : public Phase { + friend class StringConcat; + + private: + PhaseGVN* _gvn; + + // List of dead nodes to clean up aggressively at the end + Unique_Node_List dead_worklist; + + // Memory slices needed for code gen + int char_adr_idx; + int value_field_idx; + int count_field_idx; + int offset_field_idx; + + // Integer.sizeTable - used for int to String conversion + ciField* size_table_field; + + // A set for use by various stages + VectorSet _visited; + + // Collect a list of all SB.toString calls + Node_List collect_toString_calls(); + + // Examine the use of the SB alloc to see if it can be replace with + // a single string construction. + StringConcat* build_candidate(CallStaticJavaNode* call); + + // Replace all the SB calls in concat with an optimization String allocation + void replace_string_concat(StringConcat* concat); + + // Load the value of a static field, performing any constant folding. + Node* fetch_static_field(GraphKit& kit, ciField* field); + + // Compute the number of characters required to represent the int value + Node* int_stringSize(GraphKit& kit, Node* value); + + // Copy the characters representing value into char_array starting at start + void int_getChars(GraphKit& kit, Node* value, Node* char_array, Node* start, Node* end); + + // Copy of the contents of the String str into char_array starting at index start. + Node* copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start); + + // Clean up any leftover nodes + void record_dead_node(Node* node); + void remove_dead_nodes(); + + PhaseGVN* gvn() { return _gvn; } + + enum { + // max length of constant string copy unrolling in copy_string + unroll_string_copy_length = 6 + }; + + public: + PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List* worklist); +}; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1921,6 +1921,11 @@ } // Match AddP(base, AddP(ptr, k*iv [+ invariant]), constant) Node* base = adr->in(AddPNode::Base); + //unsafe reference could not be aligned appropriately without runtime checking + if (base == NULL || base->bottom_type() == Type::TOP) { + assert(!valid(), "unsafe access"); + return; + } for (int i = 0; i < 3; i++) { if (!scaled_iv_plus_offset(adr->in(AddPNode::Offset))) { assert(!valid(), "too complex"); diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/opto/type.hpp --- a/hotspot/src/share/vm/opto/type.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/opto/type.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -847,9 +847,6 @@ // Constant pointer to array static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot); - // Convenience - static const TypeAryPtr *make(ciObject* o); - // Return a 'ptr' version of this type virtual const Type *cast_to_ptr_type(PTR ptr) const; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -3231,6 +3231,21 @@ jint result = JNI_ERR; DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result); + // We're about to use Atomic::xchg for synchronization. Some Zero + // platforms use the GCC builtin __sync_lock_test_and_set for this, + // but __sync_lock_test_and_set is not guaranteed to do what we want + // on all architectures. So we check it works before relying on it. +#if defined(ZERO) && defined(ASSERT) + { + jint a = 0xcafebabe; + jint b = Atomic::xchg(0xdeadbeef, &a); + void *c = &a; + void *d = Atomic::xchg_ptr(&b, &c); + assert(a == 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works"); + assert(c == &b && d == &a, "Atomic::xchg_ptr() works"); + } +#endif // ZERO && ASSERT + // At the moment it's only possible to have one Java VM, // since some of the runtime state is in global variables. diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1318,19 +1318,20 @@ return NULL; } - symbolOop simple_name = NULL; + bool inner_is_member = false; klassOop outer_klass = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)) - )->compute_enclosing_class(simple_name, CHECK_NULL); + )->compute_enclosing_class(&inner_is_member, CHECK_NULL); if (outer_klass == NULL) return NULL; // already a top-level class - if (simple_name == NULL) return NULL; // an anonymous class (inside a method) + if (!inner_is_member) return NULL; // an anonymous class (inside a method) return (jclass) JNIHandles::make_local(env, Klass::cast(outer_klass)->java_mirror()); } JVM_END // should be in instanceKlass.cpp, but is here for historical reasons klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle k, - symbolOop& simple_name_result, TRAPS) { + bool* inner_is_member, + TRAPS) { Thread* thread = THREAD; const int inner_class_info_index = inner_class_inner_class_info_offset; const int outer_class_info_index = inner_class_outer_class_info_offset; @@ -1347,8 +1348,7 @@ bool found = false; klassOop ok; instanceKlassHandle outer_klass; - bool inner_is_member = false; - int simple_name_index = 0; + *inner_is_member = false; // Find inner_klass attribute for (int i = 0; i < i_length && !found; i += inner_class_next_offset) { @@ -1364,8 +1364,7 @@ if (found && ooff != 0) { ok = i_cp->klass_at(ooff, CHECK_NULL); outer_klass = instanceKlassHandle(thread, ok); - simple_name_index = noff; - inner_is_member = true; + *inner_is_member = true; } } } @@ -1377,7 +1376,7 @@ if (encl_method_class_idx != 0) { ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL); outer_klass = instanceKlassHandle(thread, ok); - inner_is_member = false; + *inner_is_member = false; } } @@ -1387,9 +1386,7 @@ // Throws an exception if outer klass has not declared k as an inner klass // We need evidence that each klass knows about the other, or else // the system could allow a spoof of an inner class to gain access rights. - Reflection::check_for_inner_class(outer_klass, k, inner_is_member, CHECK_NULL); - - simple_name_result = (inner_is_member ? i_cp->symbol_at(simple_name_index) : symbolOop(NULL)); + Reflection::check_for_inner_class(outer_klass, k, *inner_is_member, CHECK_NULL); return outer_klass(); } @@ -2257,10 +2254,8 @@ switch (cp->tag_at(cp_index).value()) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Methodref: + case JVM_CONSTANT_NameAndType: // for invokedynamic return cp->uncached_name_ref_at(cp_index)->as_utf8(); - case JVM_CONSTANT_NameAndType: - // for invokedynamic - return cp->nt_name_ref_at(cp_index)->as_utf8(); default: fatal("JVM_GetCPMethodNameUTF: illegal constant"); } @@ -2277,10 +2272,8 @@ switch (cp->tag_at(cp_index).value()) { case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_Methodref: + case JVM_CONSTANT_NameAndType: // for invokedynamic return cp->uncached_signature_ref_at(cp_index)->as_utf8(); - case JVM_CONSTANT_NameAndType: - // for invokedynamic - return cp->nt_signature_ref_at(cp_index)->as_utf8(); default: fatal("JVM_GetCPMethodSignatureUTF: illegal constant"); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jvmtiEnv.cpp --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,15 +32,15 @@ // FIXLATER: hook into JvmtiTrace #define TraceJVMTICalls false -JvmtiEnv::JvmtiEnv() : JvmtiEnvBase() { +JvmtiEnv::JvmtiEnv(jint version) : JvmtiEnvBase(version) { } JvmtiEnv::~JvmtiEnv() { } JvmtiEnv* -JvmtiEnv::create_a_jvmti() { - return new JvmtiEnv(); +JvmtiEnv::create_a_jvmti(jint version) { + return new JvmtiEnv(version); } // VM operation class to copy jni function table at safepoint. @@ -411,8 +411,15 @@ if (phase == JVMTI_PHASE_ONLOAD) { Arguments::append_sysclasspath(segment); return JVMTI_ERROR_NONE; - } else { - assert(phase == JVMTI_PHASE_LIVE, "sanity check"); + } else if (use_version_1_0_semantics()) { + // This JvmtiEnv requested version 1.0 semantics and this function + // is only allowed in the ONLOAD phase in version 1.0 so we need to + // return an error here. + return JVMTI_ERROR_WRONG_PHASE; + } else if (phase == JVMTI_PHASE_LIVE) { + // The phase is checked by the wrapper that called this function, + // but this thread could be racing with the thread that is + // terminating the VM so we check one more time. // create the zip entry ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); @@ -433,6 +440,8 @@ } ClassLoader::add_to_list(zip_entry); return JVMTI_ERROR_NONE; + } else { + return JVMTI_ERROR_WRONG_PHASE; } } /* end AddToBootstrapClassLoaderSearch */ @@ -451,11 +460,12 @@ } } return JVMTI_ERROR_NONE; - } else { + } else if (phase == JVMTI_PHASE_LIVE) { + // The phase is checked by the wrapper that called this function, + // but this thread could be racing with the thread that is + // terminating the VM so we check one more time. HandleMark hm; - assert(phase == JVMTI_PHASE_LIVE, "sanity check"); - // create the zip entry (which will open the zip file and hence // check that the segment is indeed a zip file). ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); @@ -504,6 +514,8 @@ } return JVMTI_ERROR_NONE; + } else { + return JVMTI_ERROR_WRONG_PHASE; } } /* end AddToSystemClassLoaderSearch */ @@ -2863,6 +2875,14 @@ // is_obsolete_ptr - pre-checked for NULL jvmtiError JvmtiEnv::IsMethodObsolete(methodOop method_oop, jboolean* is_obsolete_ptr) { + if (use_version_1_0_semantics() && + get_capabilities()->can_redefine_classes == 0) { + // This JvmtiEnv requested version 1.0 semantics and this function + // requires the can_redefine_classes capability in version 1.0 so + // we need to return an error here. + return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; + } + if (method_oop == NULL || method_oop->is_obsolete()) { *is_obsolete_ptr = true; } else { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jvmtiEnvBase.cpp --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -123,7 +123,26 @@ } -JvmtiEnvBase::JvmtiEnvBase() : _env_event_enable() { +bool +JvmtiEnvBase::use_version_1_0_semantics() { + int major, minor, micro; + + JvmtiExport::decode_version_values(_version, &major, &minor, µ); + return major == 1 && minor == 0; // micro version doesn't matter here +} + + +bool +JvmtiEnvBase::use_version_1_1_semantics() { + int major, minor, micro; + + JvmtiExport::decode_version_values(_version, &major, &minor, µ); + return major == 1 && minor == 1; // micro version doesn't matter here +} + + +JvmtiEnvBase::JvmtiEnvBase(jint version) : _env_event_enable() { + _version = version; _env_local_storage = NULL; _tag_map = NULL; _native_method_prefix_count = 0; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jvmtiEnvBase.hpp --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,6 +76,7 @@ jvmtiEnv _jvmti_external; jint _magic; + jint _version; // version value passed to JNI GetEnv() JvmtiEnvBase* _next; bool _is_retransformable; const void *_env_local_storage; // per env agent allocated data. @@ -91,7 +92,7 @@ int _native_method_prefix_count; protected: - JvmtiEnvBase(); + JvmtiEnvBase(jint version); ~JvmtiEnvBase(); void dispose(); void env_dispose(); @@ -122,6 +123,9 @@ bool is_valid(); + bool use_version_1_0_semantics(); // agent asked for version 1.0 + bool use_version_1_1_semantics(); // agent asked for version 1.1 + bool is_retransformable() { return _is_retransformable; } static ByteSize jvmti_external_offset() { diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jvmtiExport.cpp --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Wed Jul 05 17:05:01 2017 +0200 @@ -319,7 +319,27 @@ jint JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) { - /* To Do: add version checks */ + // The JVMTI_VERSION_INTERFACE_JVMTI part of the version number + // has already been validated in JNI GetEnv(). + int major, minor, micro; + + // micro version doesn't matter here (yet?) + decode_version_values(version, &major, &minor, µ); + switch (major) { + case 1: + switch (minor) { + case 0: // version 1.0. is recognized + case 1: // version 1.1. is recognized + break; + + default: + return JNI_EVERSION; // unsupported minor version number + } + break; + + default: + return JNI_EVERSION; // unsupported major version number + } if (JvmtiEnv::get_phase() == JVMTI_PHASE_LIVE) { JavaThread* current_thread = (JavaThread*) ThreadLocalStorage::thread(); @@ -328,13 +348,13 @@ __ENTRY(jvmtiEnv*, JvmtiExport::get_jvmti_interface, current_thread) debug_only(VMNativeEntryWrapper __vew;) - JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(); + JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(version); *penv = jvmti_env->jvmti_external(); // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv* return JNI_OK; } else if (JvmtiEnv::get_phase() == JVMTI_PHASE_ONLOAD) { // not live, no thread to transition - JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(); + JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(version); *penv = jvmti_env->jvmti_external(); // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv* return JNI_OK; @@ -345,6 +365,15 @@ } } + +void +JvmtiExport::decode_version_values(jint version, int * major, int * minor, + int * micro) { + *major = (version & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR; + *minor = (version & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR; + *micro = (version & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO; +} + void JvmtiExport::enter_primordial_phase() { JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL); } diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jvmtiExport.hpp --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,6 +236,8 @@ static bool is_jvmti_version(jint version) { return (version & JVMTI_VERSION_MASK) == JVMTI_VERSION_VALUE; } static bool is_jvmdi_version(jint version) { return (version & JVMTI_VERSION_MASK) == JVMDI_VERSION_VALUE; } static jint get_jvmti_interface(JavaVM *jvm, void **penv, jint version); + static void decode_version_values(jint version, int * major, int * minor, + int * micro); // single stepping management methods static void at_single_stepping_point(JavaThread *thread, methodOop method, address location) KERNEL_RETURN; diff -r 4b85cf247673 -r df0a816d95ef hotspot/src/share/vm/prims/jvmtiHpp.xsl --- a/hotspot/src/share/vm/prims/jvmtiHpp.xsl Thu Dec 17 14:10:29 2009 -0800 +++ b/hotspot/src/share/vm/prims/jvmtiHpp.xsl Wed Jul 05 17:05:01 2017 +0200 @@ -1,6 +1,6 @@ + + + diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/nbproject/project.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/nbproject/project.properties Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,92 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# - Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# - Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# - Neither the name of Sun Microsystems nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +application.title=classanalyzer +application.vendor=mchung +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form + +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources + +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results + +cp.extra=${tools.jar} + +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} + +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/classanalyzer.jar +dist.javadoc.dir=${dist.dir}/javadoc + +excludes= + +file.reference.tools.jar=${jdk.home}/lib/tools.jar +file.reference.tools-src=src +includes=** +jar.compress=false +javac.classpath=\ + ${file.reference.tools.jar} +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath= +javadoc.author=false +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=false +javadoc.use=false +javadoc.version=false +main.class=com.sun.classanalyzer.ClassAnalyzer +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=JDK_1.6 +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs=-Xmx256m +run.test.classpath= +source.encoding=UTF-8 +src.dir=${file.reference.tools-src} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/nbproject/project.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/nbproject/project.xml Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,45 @@ + + + + + org.netbeans.modules.java.j2seproject + + + classanalyzer + + + + + + + + diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotatedDependency.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotatedDependency.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,627 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ +package com.sun.classanalyzer; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.Map; + +import com.sun.classanalyzer.Module.Reference; +import java.util.LinkedList; +import java.util.TreeMap; + +/** + * + * @author Mandy Chung + */ +public abstract class AnnotatedDependency implements Comparable { + + final Klass from; + final List classes; + protected boolean optional; + String description; + Klass.Method method; + private List filters = null; + + public AnnotatedDependency(Klass klass) { + this(klass, false); + } + + public AnnotatedDependency(Klass klass, boolean optional) { + this.from = klass; + this.classes = new ArrayList(); + this.optional = optional; + } + + abstract String getTag(); + + abstract boolean isDynamic(); + + void setMethod(Klass.Method m) { + this.method = m; + } + + void addElement(String element, List value) { + if (element.equals("value")) { + addValue(value); + } else if (element.equals("description")) { + description = value.get(0); + } else if (element.equals("optional")) { + optional = value.get(0).equals("1") || Boolean.parseBoolean(value.get(0)); + } + } + + void addValue(List value) { + for (String s : value) { + if ((s = s.trim()).length() > 0) { + classes.add(s); + } + } + } + + List getValue() { + return classes; + } + + boolean isOptional() { + return optional; + } + + boolean isEmpty() { + return classes.isEmpty(); + } + + boolean matches(String classname) { + synchronized (this) { + // initialize filters + if (filters == null) { + filters = new ArrayList(); + for (String pattern : classes) { + filters.add(new Filter(pattern)); + } + + } + } + + for (Filter f : filters) { + if (f.matches(classname)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (String v : getValue()) { + if (sb.length() == 0) { + sb.append(getTag()); + sb.append("\n"); + } else { + sb.append("\n"); + } + sb.append(" "); + sb.append(from.getClassName()).append(" -> "); + sb.append(v); + } + return sb.toString(); + } + + @Override + public int compareTo(AnnotatedDependency o) { + if (from == o.from) { + if (this.getClass().getName().equals(o.getClass().getName())) { + String s1 = classes.isEmpty() ? "" : classes.get(0); + String s2 = o.classes.isEmpty() ? "" : o.classes.get(0); + return s1.compareTo(s2); + } else { + return this.getClass().getName().compareTo(o.getClass().getName()); + } + + } else { + return from.compareTo(o.from); + } + } + + @Override + public int hashCode() { + int hashcode = 7 + 73 * from.hashCode(); + for (String s : classes) { + hashcode ^= s.hashCode(); + } + return hashcode; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof AnnotatedDependency)) { + return false; + } + AnnotatedDependency other = (AnnotatedDependency) obj; + boolean ret = this.from.equals(other.from) && this.classes.size() == other.classes.size(); + if (ret == true) { + for (int i = 0; i < this.classes.size(); i++) { + ret = ret && this.classes.get(i).equals(other.classes.get(i)); + } + } + return ret; + } + + static class ClassForName extends AnnotatedDependency { + + public ClassForName(Klass klass, boolean optional) { + super(klass, optional); + } + + @Override + String getTag() { + if (this.optional) { + return TAG + "(optional)"; + } else { + return TAG; + } + } + + @Override + boolean isDynamic() { + return true; + } + static final String TYPE = "sun.annotation.ClassForName"; + static final String TAG = "@ClassForName"; + } + + static class NativeFindClass extends AnnotatedDependency { + + public NativeFindClass(Klass klass, boolean optional) { + super(klass, optional); + } + + @Override + String getTag() { + if (this.optional) { + return TAG + "(optional)"; + } else { + return TAG; + } + } + + @Override + boolean isDynamic() { + return true; + } + static final String TYPE = "sun.annotation.NativeFindClass"; + static final String TAG = "@NativeFindClass"; + } + + static class Provider extends AnnotatedDependency { + + private List services = new ArrayList(); + + Provider(Klass klass) { + super(klass, true); + } + + @Override + boolean isDynamic() { + return true; + } + + public List services() { + return services; + } + + @Override + void addElement(String element, List value) { + if (element.equals("service")) { + List configFiles = new ArrayList(); + for (String s : value) { + if ((s = s.trim()).length() > 0) { + configFiles.add(metaInfPath + s); + } + } + addValue(configFiles); + } + } + + @Override + void addValue(List value) { + for (String s : value) { + if ((s = s.trim()).length() > 0) { + if (s.startsWith("META-INF")) { + services.add(s); + readServiceConfiguration(s, classes); + } else { + throw new RuntimeException("invalid value" + s); + } + } + } + } + + boolean isEmpty() { + return services.isEmpty(); + } + static final String metaInfPath = + "META-INF" + File.separator + "services" + File.separator; + + static void readServiceConfiguration(String config, List names) { + BufferedReader br = null; + try { + InputStream is = ClassPath.open(config); + if (is != null) { + // Properties doesn't perserve the order of the input file + br = new BufferedReader(new InputStreamReader(is, "utf-8")); + int lc = 1; + while ((lc = parseLine(br, lc, names)) >= 0); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + } + } + + // Parse a single line from the given configuration file, adding the name + // on the line to the names list. + // + private static int parseLine(BufferedReader r, int lc, List names) throws IOException { + String ln = r.readLine(); + if (ln == null) { + return -1; + } + int ci = ln.indexOf('#'); + if (ci >= 0) { + ln = ln.substring(0, ci); + } + ln = ln.trim(); + int n = ln.length(); + if (n != 0) { + if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) { + throw new RuntimeException("Illegal configuration-file syntax"); + } + int cp = ln.codePointAt(0); + if (!Character.isJavaIdentifierStart(cp)) { + throw new RuntimeException("Illegal provider-class name: " + ln); + } + for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) { + cp = ln.codePointAt(i); + if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) { + throw new RuntimeException("Illegal provider-class name: " + ln); + } + } + if (!names.contains(ln)) { + names.add(ln); + } + } + return lc + 1; + } + + @Override + String getTag() { + return TAG; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof AnnotatedDependency)) { + return false; + } + Provider other = (Provider) obj; + boolean ret = this.from.equals(other.from) && + this.services.size() == other.services.size(); + if (ret == true) { + for (int i = 0; i < this.services.size(); i++) { + ret = ret && this.services.get(i).equals(other.services.get(i)); + } + } + return ret; + } + + @Override + public int hashCode() { + int hashcode = 7 + 73 * from.hashCode(); + for (String s : services) { + hashcode ^= s.hashCode(); + } + return hashcode; + } + + @Override + public List getValue() { + List result = new ArrayList(); + result.addAll(services); + return result; + } + static final String TYPE = "sun.annotation.Provider"; + static final String TAG = "@Provider"; + } + + static class OptionalDependency extends AnnotatedDependency { + + static boolean isOptional(Klass from, Klass to) { + synchronized (OptionalDependency.class) { + if (optionalDepsMap == null) { + // Build a map of classes to its optional dependencies + initDependencies(); + } + } + for (Reference ref : optionalDepsMap.keySet()) { + if (ref.referrer() == from && ref.referree() == to) { + return true; + } + } + return false; + } + + OptionalDependency(Klass klass) { + super(klass, true); + } + + @Override + boolean isDynamic() { + return false; + } + + @Override + String getTag() { + return TAG; + } + static final String TYPE = "sun.annotation.Optional"; + static final String TAG = "@Optional"; + } + + static class CompilerInline extends AnnotatedDependency { + + public CompilerInline(Klass klass) { + super(klass); + } + + @Override + String getTag() { + return TAG; + } + + @Override + boolean isDynamic() { + return false; + } + static final String TYPE = "sun.annotation.Inline"; + static final String TAG = "@Inline"; + } + + static class Filter { + + final String pattern; + final String regex; + + Filter(String pattern) { + this.pattern = pattern; + + boolean isRegex = false; + for (int i = 0; i < pattern.length(); i++) { + char p = pattern.charAt(i); + if (p == '*' || p == '[' || p == ']') { + isRegex = true; + break; + } + } + + if (isRegex) { + this.regex = convertToRegex(pattern); + } else { + this.regex = null; + } + } + + private String convertToRegex(String pattern) { + StringBuilder sb = new StringBuilder(); + int i = 0; + int index = 0; + int plen = pattern.length(); + while (i < plen) { + char p = pattern.charAt(i); + if (p == '*') { + sb.append("(").append(pattern.substring(index, i)).append(")"); + if (i + 1 < plen && pattern.charAt(i + 1) == '*') { + sb.append(".*"); + index = i + 2; + } else { + sb.append("[^\\.]*"); + index = i + 1; + } + } else if (p == '[') { + int j = i + 1; + while (j < plen) { + if (pattern.charAt(j) == ']') { + break; + } + j++; + } + if (j >= plen || pattern.charAt(j) != ']') { + throw new RuntimeException("Malformed pattern " + pattern); + } + sb.append("(").append(pattern.substring(index, i)).append(")"); + sb.append(pattern.substring(i, j + 1)); + index = j + 1; + i = j; + } + i++; + } + if (index < plen) { + sb.append("(").append(pattern.substring(index, plen)).append(")"); + } + return sb.toString(); + } + + boolean matches(String name) { + if (regex == null) { + // the pattern is not a regex + return name.equals(pattern); + } else { + return name.matches(regex); + } + } + } + + static boolean isValidType(String type) { + if (type.endsWith("(optional)")) { + int len = type.length() - "(optional)".length(); + type = type.substring(0, len); + } + return type.equals(ClassForName.TYPE) || type.equals(ClassForName.TAG) || + type.equals(NativeFindClass.TYPE) || type.equals(NativeFindClass.TAG) || + type.equals(Provider.TYPE) || type.equals(Provider.TAG) || + type.equals(CompilerInline.TYPE) || type.equals(CompilerInline.TAG) || + type.equals(OptionalDependency.TYPE) || type.equals(OptionalDependency.TAG); + } + + static AnnotatedDependency newAnnotatedDependency(String tag, String value, Klass klass) { + AnnotatedDependency dep = newAnnotatedDependency(tag, klass); + if (dep != null) { + dep.addValue(Collections.singletonList(value)); + } + return dep; + } + static List annotatedDependencies = new LinkedList(); + static List optionalDependencies = new LinkedList(); + + static AnnotatedDependency newAnnotatedDependency(String type, Klass klass) { + boolean optional = false; + if (type.endsWith("(optional)")) { + optional = true; + int len = type.length() - "(optional)".length(); + type = type.substring(0, len); + } + + if (type.equals(OptionalDependency.TYPE) || type.equals(OptionalDependency.TAG)) { + return newOptionalDependency(klass); + } + + AnnotatedDependency dep; + if (type.equals(ClassForName.TYPE) || type.equals(ClassForName.TAG)) { + dep = new ClassForName(klass, optional); + } else if (type.equals(NativeFindClass.TYPE) || type.equals(NativeFindClass.TAG)) { + dep = new NativeFindClass(klass, optional); + } else if (type.equals(Provider.TYPE) || type.equals(Provider.TAG)) { + dep = new Provider(klass); + } else if (type.equals(CompilerInline.TYPE) || type.equals(CompilerInline.TAG)) { + dep = new CompilerInline(klass); + } else { + return null; + } + klass.addAnnotatedDep(dep); + annotatedDependencies.add(dep); + return dep; + } + + static OptionalDependency newOptionalDependency(Klass klass) { + OptionalDependency dep = new OptionalDependency(klass); + optionalDependencies.add(dep); + return dep; + } + static Map> annotatedDepsMap = null; + static Map> optionalDepsMap = null; + + static Map> getReferences(Module m) { + // ensure it's initialized + initDependencies(); + + Map> result = new TreeMap>(); + for (Reference ref : annotatedDepsMap.keySet()) { + if (m.contains(ref.referrer()) && m.isModuleDependence(ref.referree())) { + result.put(ref, annotatedDepsMap.get(ref)); + } + } + return result; + } + + static Set getDependencies(Module m) { + // ensure it's initialized + initDependencies(); + + Set deps = new TreeSet(); + for (Reference ref : annotatedDepsMap.keySet()) { + if (m.contains(ref.referrer())) { + Module other = m.getModuleDependence(ref.referree()); + if (other != null) { + for (AnnotatedDependency ad : annotatedDepsMap.get(ref)) { + Module.Dependency d = new Module.Dependency(other, ad.isOptional(), ad.isDynamic()); + deps.add(d); + } + } + } + } + return deps; + } + + synchronized static void initDependencies() { + if (annotatedDepsMap != null) { + return; + } + + // Build a map of references to its dependencies + annotatedDepsMap = new TreeMap>(); + optionalDepsMap = new TreeMap>(); + + for (Klass k : Klass.getAllClasses()) { + for (AnnotatedDependency ad : annotatedDependencies) { + if (ad.matches(k.getClassName())) { + Reference ref = new Reference(ad.from, k); + Set set = annotatedDepsMap.get(ref); + if (set == null) { + set = new TreeSet(); + annotatedDepsMap.put(ref, set); + } + set.add(ad); + } + } + + for (AnnotatedDependency ad : optionalDependencies) { + if (ad.matches(k.getClassName())) { + Reference ref = new Reference(ad.from, k); + Set set = optionalDepsMap.get(ref); + if (set == null) { + set = new TreeSet(); + optionalDepsMap.put(ref, set); + } + set.add(ad); + } + } + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotationParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/AnnotationParser.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,293 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.classanalyzer; + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.Annotation; +import com.sun.tools.classfile.ExtendedAnnotation; +import com.sun.tools.classfile.Annotation.Annotation_element_value; +import com.sun.tools.classfile.Annotation.Array_element_value; +import com.sun.tools.classfile.Annotation.Class_element_value; +import com.sun.tools.classfile.Annotation.Enum_element_value; +import com.sun.tools.classfile.Annotation.Primitive_element_value; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Descriptor; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import java.util.ArrayList; +import java.util.List; + +import com.sun.classanalyzer.AnnotatedDependency.*; +import java.io.File; +import java.io.PrintWriter; +import java.util.Map; +import java.util.Set; + +/** + * + * @author Mandy Chung + */ +public class AnnotationParser { + + static boolean parseAnnotation = false; + static void setParseAnnotation(boolean newValue) { + parseAnnotation = newValue; + } + + private final ClassFileParser cfparser; + public AnnotationParser(ClassFileParser cfparser) { + this.cfparser = cfparser; + } + + private AnnotatedDependency addAnnotation(Annotation annot, Klass.Method method) { + String type = getType(annot.type_index); + AnnotatedDependency dep = AnnotatedDependency.newAnnotatedDependency(type, cfparser.this_klass); + if (dep != null) { + for (int i = 0; i < annot.num_element_value_pairs; i++) { + Element element = getElement(annot.element_value_pairs[i]); + dep.addElement(element.name, element.value); + } + dep.setMethod(method); + } + return dep; + } + + private AnnotatedDependency addAnnotation(ExtendedAnnotation annot, Klass.Method method) { + return addAnnotation(annot.annotation, method); + } + + class Element { + + String name; + List value; + + Element(String name) { + this.name = name; + this.value = new ArrayList(); + } + + void add(String v) { + value.add(v); + } + } + + Element getElement(Annotation.element_value_pair pair) { + Element element = new Element(getName(pair.element_name_index)); + evp.parse(pair.value, element); + return element; + } + + private String getType(int index) { + try { + Descriptor d = new Descriptor(index); + return d.getFieldType(cfparser.classfile.constant_pool); + } catch (ConstantPoolException ignore) { + } catch (InvalidDescriptor ignore) { + } + return "Unknown"; + } + + private String getName(int index) { + return cfparser.constantPoolParser.stringValue(index); + } + element_value_Parser evp = new element_value_Parser(); + + class element_value_Parser implements Annotation.element_value.Visitor { + + public Void parse(Annotation.element_value value, Element element) { + value.accept(this, element); + return null; + } + + public Void visitPrimitive(Primitive_element_value ev, Element element) { + String value = getName(ev.const_value_index); + element.add(value); + return null; + } + + public Void visitEnum(Enum_element_value ev, Element element) { + String value = getName(ev.type_name_index) + "." + getName(ev.const_name_index); + element.add(value); + return null; + } + + public Void visitClass(Class_element_value ev, Element element) { + String value = getName(ev.class_info_index) + ".class"; + element.add(value); + return null; + } + + public Void visitAnnotation(Annotation_element_value ev, Element element) { + // AnnotationParser.this.addAnnotation(ev.annotation_value); + throw new UnsupportedOperationException("Not supported: " + ev); + } + + public Void visitArray(Array_element_value ev, Element element) { + for (int i = 0; i < ev.num_values; i++) { + parse(ev.values[i], element); + } + return null; + } + } + + void parseAttributes(Attributes attributes, Klass.Method method) { + if (!parseAnnotation) { + return; + } + + visitRuntimeAnnotations((RuntimeVisibleAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleAnnotations), method); + visitRuntimeAnnotations((RuntimeInvisibleAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleAnnotations), method); + visitRuntimeTypeAnnotations((RuntimeVisibleTypeAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleTypeAnnotations), method); + visitRuntimeTypeAnnotations((RuntimeInvisibleTypeAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleTypeAnnotations), method); + visitRuntimeParameterAnnotations((RuntimeVisibleParameterAnnotations_attribute) attributes.get(Attribute.RuntimeVisibleParameterAnnotations), method); + visitRuntimeParameterAnnotations((RuntimeInvisibleParameterAnnotations_attribute) attributes.get(Attribute.RuntimeInvisibleParameterAnnotations), method); + } + + public void visitRuntimeAnnotations(RuntimeAnnotations_attribute attr, Klass.Method method) { + if (attr == null) { + return; + } + + for (int i = 0; i < attr.annotations.length; i++) { + addAnnotation(attr.annotations[i], method); + } + } + + public void visitRuntimeTypeAnnotations(RuntimeTypeAnnotations_attribute attr, Klass.Method method) { + if (attr == null) { + return; + } + + for (int i = 0; i < attr.annotations.length; i++) { + addAnnotation(attr.annotations[i], method); + } + } + + public void visitRuntimeParameterAnnotations(RuntimeParameterAnnotations_attribute attr, Klass.Method method) { + if (attr == null) { + return; + } + + for (int param = 0; param < attr.parameter_annotations.length; param++) { + for (int i = 0; i < attr.parameter_annotations[param].length; i++) { + addAnnotation(attr.parameter_annotations[param][i], method); + } + } + } + + void parseAttributes(Attributes attributes) { + parseAttributes(attributes, null); + } + + public static void main(String[] args) throws Exception { + String jdkhome = null; + String output = "."; + + // process arguments + int i = 0; + while (i < args.length) { + String arg = args[i++]; + if (arg.equals("-jdkhome")) { + if (i < args.length) { + jdkhome = args[i++]; + } else { + usage(); + } + } else if (arg.equals("-output")) { + output = args[i++]; + } else { + usage(); + } + } + if (jdkhome == null) { + usage(); + } + + // parse annotation and code attribute to find all references + // to Class.forName etc + CodeAttributeParser.setParseCodeAttribute(true); + AnnotationParser.setParseAnnotation(true); + + ClassPath.setJDKHome(jdkhome); + ClassPath.parseAllClassFiles(); + + PrintWriter writer = new PrintWriter(new File(output, "jdk7.depconfig")); + + try { + for (Klass k : Klass.getAllClasses()) { + for (AnnotatedDependency dep : k.getAnnotatedDeps()) { + if (dep.isEmpty()) { + continue; + } + writer.format("# %s \n", dep.method == null ? dep.from : dep.method); + writer.format("%s\n\n", dep); + } + } + } finally { + writer.close(); + } + + writer = new PrintWriter(new File(output, "optional.depconfig")); + try { + AnnotatedDependency prev = null; + for (AnnotatedDependency dep : AnnotatedDependency.optionalDependencies) { + if (prev != null && !dep.equals(prev)) { + writer.format("%s\n\n", prev); + } + writer.format("# %s \n", dep.method == null ? dep.from : dep.method); + prev = dep; + } + if (prev != null) { + writer.format("%s\n\n", prev); + } + } finally { + writer.close(); + } + + writer = new PrintWriter(new File(output, "runtime.references")); + try { + for (Map.Entry> entry : CodeAttributeParser.runtimeReferences.entrySet()) { + writer.format("References to %s\n", entry.getKey()); + Klass prev = null; + for (Klass.Method m : entry.getValue()) { + if (prev == null || prev != m.getKlass()) { + writer.format(" %-50s # %s\n", m.getKlass(), m); + } else if (prev == m.getKlass()) { + writer.format(" %-50s # %s\n", "", m); + } + prev = m.getKlass(); + } + } + } finally { + writer.close(); + } + } + + private static void usage() { + System.out.println("Usage: AnnotationParser "); + System.out.println("Options: "); + System.out.println("\t-jdkhome where all jars will be parsed"); + System.out.println("\t-depconfig "); + System.out.println("\t-optional "); + System.exit(-1); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/BootAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/BootAnalyzer.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,819 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ +package com.sun.classanalyzer; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.File; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; +import static com.sun.tools.classfile.ConstantPool.*; +import com.sun.tools.classfile.Instruction.TypeKind; +import com.sun.tools.classfile.Type.*; + +/** + * Generate the module config for the boot module with + * a given set of roots (classes or methods) and exclude list. + * + * This tool does method-level dependency analysis starting + * from the root set and follows references transitively as follows: + *
    + *
  • For a given class, it will parse the ClassFile to + * find its superclass and superinterfaces and also + * its static initializer <clinit>.
  • + *
  • For each method, it will parse its Code attribute + * to look for a Methodref, Fieldref, and InterfaceMethodref. + *
  • + *
  • For each Fieldref, it will include the type of + * the field in the dependency.
  • + *
  • For each MethodRef, it will follow all references in + * that method.
  • + *
  • For each InterfaceMethodref, it will follow all references in + * that method defined its implementation classes in + * the resulting dependency list.
  • + *
+ * + * Limitation: + *
    + *
  • For each Methodref, it only parses the method of + * the specified type. It doesn't analyze the class hierarchy + * and follow references of its subclasses since it ends up + * pulls in many unnecessary dependencies. For now, + * the list of subclasses and methods need to be listed in + * the root set.
  • + *
+ * + * @author Mandy Chung + */ +public class BootAnalyzer { + + public static void main(String[] args) throws Exception { + String jdkhome = null; + String config = null; + String output = "."; + boolean printClassList = false; + + // process arguments + int i = 0; + while (i < args.length) { + String arg = args[i++]; + if (arg.equals("-jdkhome")) { + if (i < args.length) { + jdkhome = args[i++]; + } else { + usage(); + } + } else if (arg.equals("-config")) { + config = args[i++]; + } else if (arg.equals("-output")) { + output = args[i++]; + } else if (arg.equals("-classlist")) { + printClassList = true; + } else { + usage(); + } + } + + + + if (jdkhome == null || config == null) { + usage(); + } + + File jre = new File(jdkhome, "jre"); + if (jre.exists()) { + ClassPath.setJDKHome(jdkhome); + } else { + File classes = new File(jdkhome, "classes"); + if (classes.exists()) { + ClassPath.setClassPath(classes.getCanonicalPath()); + } else { + throw new RuntimeException("Invalid jdkhome: " + jdkhome); + } + } + + parseConfigFile(config); + followRoots(); + + // create output directory if it doesn't exist + File dir = new File(output); + if (!dir.isDirectory()) { + if (!dir.exists()) { + boolean created = dir.mkdir(); + if (!created) { + throw new RuntimeException("Unable to create `" + dir + "'"); + } + } + } + + String bootmodule = "boot"; + String bootconfig = resolve(dir, bootmodule, "config"); + printBootConfig(bootconfig, bootmodule); + + List list = ModuleConfig.readConfigurationFile(bootconfig); + Module module = Module.addModule(list.get(0)); + for (Klass k : Klass.getAllClasses()) { + module.addKlass(k); + } + module.fixupDependencies(); + + if (printClassList) { + module.printClassListTo(resolve(dir, bootmodule, "classlist")); + module.printSummaryTo(resolve(dir, bootmodule, "summary")); + } + } + + // print boot.config file as an input to the ClassAnalyzer + private static void printBootConfig(String output, String bootmodule) throws IOException { + + File f = new File(output); + PrintWriter writer = new PrintWriter(f); + try { + int count = 0; + writer.format("module %s {%n", bootmodule); + for (Klass k : Klass.getAllClasses()) { + if (count++ == 0) { + writer.format("%4s%7s %s", "", "include", k); + } else { + writer.format(",%n"); + writer.format("%4s%7s %s", "", "", k); + } + } + writer.format(";%n}%n"); + } finally { + writer.close(); + } + } + + private static String resolve(File dir, String mname, String suffix) { + File f = new File(dir, mname + "." + suffix); + return f.toString(); + + } + static List methods = new LinkedList(); + static Deque pending = new ArrayDeque(); + static Deque interfaceMethodRefs = new ArrayDeque(); + static Filter filter = new Filter(); + + private static void followRoots() throws IOException { + MethodDescriptor md = null; + + while ((md = pending.poll()) != null) { + if (!methods.contains(md)) { + methods.add(md); + if (md.classname.isEmpty()) { + trace("Warning: class missing %s%n", md); + continue; + } + + if (filter.isExcluded(md.classname)) { + trace("excluded %s%n", md); + } else { + KlassInfo kinfo = getKlassInfo(md.classname); + if (kinfo.classname.contains("$")) { + int pos = kinfo.classname.lastIndexOf('$'); + String outer = kinfo.classname.substring(0, pos); + if (!cache.containsKey(outer)) { + trace(" include outer class %s%n", outer); + getKlassInfo(outer).ensureParse(); + } + } + + kinfo.ensureParse(); + if (md.methodname.length() > 0) { + if (filter.isExcluded(md.name)) { + trace("excluded %s%n", md); + } else { + if (md.interfaceMethodRef) { + trace("interface methodref %s%n", md); + interfaceMethodRefs.add(md); + } else { + List descriptors = kinfo.parse(md); + if (descriptors.isEmpty()) { + if (kinfo.getSuperclass() != null) { + String sn = kinfo.getSuperclass().classname; + MethodDescriptor superMD = new MethodDescriptor(sn + "." + md.methodname, md.descriptor, false); + if (!methods.contains(superMD) && !pending.contains(superMD)) { + trace(" delegated %s to %s%n", md, superMD); + pending.add(superMD); + } + } else if (kinfo.isClass()) { + trace(" %s (not found)%n", md); + } else { + trace(" %s (interface)%n", md); + } + } else { + if (md.descriptor.equals("*")) { + trace(" parsed %s : ", md.name); + for (String s : descriptors) { + trace(" %s", s); + } + trace("%n"); + } + } + } + } + } + } + } + if (pending.isEmpty()) { + for (Klass k : Klass.getAllClasses()) { + if (k.getFileSize() == 0) { + getKlassInfo(k.getClassName()).ensureParse(); + } + } + while ((md = interfaceMethodRefs.poll()) != null) { + addSubClassMethods(md); + } + } + } + } + + static void addSubClassMethods(MethodDescriptor md) throws IOException { + for (KlassInfo kinfo : getSubClasses(md.classname)) { + String methodname = kinfo.classname + "." + md.methodname; + MethodDescriptor other = new MethodDescriptor(methodname, md.descriptor, false); + if (!methods.contains(other) && !pending.contains(other)) { + trace("Warning: subclass from %s to %s%n", md.classname, other); + pending.add(other); + } + } + } + private final static String privilegedActionInterf = "java.security.PrivilegedAction"; + private final static String privilegedExceptionActionInterf = "java.security.PrivilegedExceptionAction"; + + static boolean isPrivilegedAction(String classname) { + if (classname.isEmpty()) { + return false; + } + KlassInfo kinfo = getKlassInfo(classname); + for (KlassInfo ki : kinfo.getInterfaces()) { + String interf = ki.classname; + if (interf.equals(privilegedActionInterf) || + interf.equals(privilegedExceptionActionInterf)) { + return true; + } + } + return false; + } + static Map cache = new HashMap(); + + static KlassInfo getKlassInfo(String classname) { + classname = classname.replace('/', '.'); + + KlassInfo kinfo = cache.get(classname); + if (kinfo == null) { + kinfo = new KlassInfo(classname); + cache.put(classname, kinfo); + } + return kinfo; + } + + static class KlassInfo { + + final String classname; + private ClassFileParser parser; + private KlassInfo superclass; + private List interfaces = new LinkedList(); + + KlassInfo(String classname) { + this.classname = classname; + } + + boolean isClass() { + ensureParse(); + return parser.classfile.isClass(); + } + + KlassInfo getSuperclass() { + ensureParse(); + return superclass; + } + + List getInterfaces() { + ensureParse(); + return java.util.Collections.unmodifiableList(interfaces); + } + + void ensureParse() { + try { + getClassFileParser(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + synchronized ClassFileParser getClassFileParser() throws IOException { + if (parser == null) { + parser = ClassPath.parserForClass(classname); + if (parser != null) { + parseClassFile(); + List descriptors = parse(new MethodDescriptor(classname + ".", "()V", false)); + } + } + return parser; + } + + List parse(MethodDescriptor md) { + ensureParse(); + try { + List descriptors = new LinkedList(); + for (Method m : parser.classfile.methods) { + String name = m.getName(parser.classfile.constant_pool); + String desc = parser.constantPoolParser.getDescriptor(m.descriptor.index); + if (name.equals(md.methodname)) { + if (md.descriptor.equals("*") || md.descriptor.equals(desc)) { + parseMethod(parser, m); + descriptors.add(desc); + } + } + } + return descriptors; + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + } + + private void parseClassFile() throws IOException { + parser.parseClassInfo(); + + ClassFile classfile = parser.classfile; + try { + if (classfile.super_class > 0) { + superclass = getKlassInfo(classfile.getSuperclassName()); + } + if (classfile.interfaces != null) { + for (int i = 0; i < classfile.interfaces.length; i++) { + interfaces.add(getKlassInfo(classfile.getInterfaceName(i))); + } + } + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + } + } + + static List getSubClasses(String classname) throws IOException { + List result = new LinkedList(); + List list = new LinkedList(); + list.addAll(cache.values()); + for (KlassInfo kinfo : list) { + if (kinfo.getSuperclass() != null && classname.equals(kinfo.getSuperclass().classname)) { + result.add(kinfo); + } + for (KlassInfo interf : kinfo.getInterfaces()) { + if (classname.equals(interf.classname)) { + result.add(kinfo); + } + } + } + return result; + } + + private static void parseConfigFile(String config) throws IOException { + FileInputStream in = new FileInputStream(config); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String line; + int lineNumber = 0; + while ((line = reader.readLine()) != null) { + lineNumber++; + if ((line = line.trim()).length() > 0) { + if (line.startsWith("#")) { + continue; + } + + String[] s = line.split("\\s+"); + if ("exclude".equals(s[0])) { + filter.exclude(s[1]); + } else { + String name = s[0].replace('/', '.'); + if (name.length() > 0) { + String classname = name.replace('/', '.'); + if (s.length == 2) { + // method name + int pos = classname.lastIndexOf('.'); + classname = classname.substring(0, pos); + } + + KlassInfo kinfo = getKlassInfo(classname); + if (kinfo.getClassFileParser() != null) { + // class exists + MethodDescriptor md = (s.length == 1) ? new MethodDescriptor(name) : new MethodDescriptor(name, s[1], false); + if (!pending.contains(md)) { + pending.add(md); + } + } else { + // class not found + trace("Class %s not found%n", classname); + } + } + } + } + } + + } finally { + in.close(); + } + } + + private static void parseMethod(ClassFileParser cfparser, Method m) { + Klass.Method kmethod = cfparser.parseMethod(m); + Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code); + if (c_attr != null) { + LineNumberTable_attribute lineNumTable = + (LineNumberTable_attribute) c_attr.attributes.get(Attribute.LineNumberTable); + InstructorVisitor visitor = new InstructorVisitor(cfparser, lineNumTable); + trace("parseMethod %s %s %n", cfparser.this_klass, kmethod); + for (Instruction instr : c_attr.getInstructions()) { + try { + instr.accept(visitor, kmethod); + } catch (ArrayIndexOutOfBoundsException e) { + throw new RuntimeException("error at or after byte " + instr.getPC()); + } + + } + + if (c_attr.exception_table_langth > 0) { + for (int i = 0; i < + c_attr.exception_table.length; i++) { + Code_attribute.Exception_data handler = c_attr.exception_table[i]; + int catch_type = handler.catch_type; + if (catch_type > 0) { + visitor.addConstantPoolRef(catch_type, kmethod, handler.start_pc); + } + + } + } + } + } + + static class MethodDescriptor { + + final String name; + final String classname; + final String methodname; + final String descriptor; + final boolean interfaceMethodRef; + + MethodDescriptor(String classname) { + this.classname = classname.replace('/', '.'); + this.name = this.classname; + this.methodname = ""; + this.descriptor = ""; + this.interfaceMethodRef = false; + if (this.classname.length() == 1) { + throw new RuntimeException("invalid " + this); + } + } + + MethodDescriptor(String name, String descriptor, boolean interfaceMethodRef) { + name = name.replace('/', '.'); + this.name = name; + int pos = name.lastIndexOf('.'); + this.classname = name.substring(0, pos); + this.methodname = name.substring(pos + 1, name.length()); + this.descriptor = descriptor; + this.interfaceMethodRef = interfaceMethodRef; + if (this.classname.length() == 1) { + throw new RuntimeException("invalid " + this); + } + } + + @Override + public boolean equals(Object obj) { + MethodDescriptor m = (MethodDescriptor) obj; + + return this.name.equals(m.name) && + this.descriptor.equals(m.descriptor); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0); + hash = 97 * hash + (this.descriptor != null ? this.descriptor.hashCode() : 0); + return hash; + } + + public String toString() { + if (descriptor.isEmpty()) { + return name; + } else { + return name + " : " + descriptor; + } + } + } + + static class Filter { + + private Set excludes = new TreeSet(); + + Filter exclude(String pattern) { + excludes.add(pattern); + return this; + } + + boolean isExcluded(String klass) { + for (String pattern : excludes) { + if (matches(klass, pattern)) { + return true; + } + } + return false; + } + + private boolean matches(String klass, String pattern) { + int pos = klass.lastIndexOf('.'); + String packageName = pos > 0 ? klass.substring(0, pos) : ""; + if (pattern.endsWith("**")) { + String p = pattern.substring(0, pattern.length() - 2); + return klass.startsWith(p); + } else if (pattern.endsWith("*")) { + pos = pattern.lastIndexOf('.'); + String pkg = pos > 0 ? pattern.substring(0, pos) : ""; + if (packageName.equals(pkg)) { + // package name has to be exact match + String p = pattern.substring(0, pattern.length() - 1); + return klass.startsWith(p); + } else { + return false; + } + } else { + // exact match or inner class + return klass.equals(pattern) || klass.startsWith(pattern + "$"); + } + } + } + + static class InstructorVisitor implements Instruction.KindVisitor { + + private final ClassFileParser parser; + private final LineNumberTable_attribute lineNumTable; + + InstructorVisitor(ClassFileParser parser, LineNumberTable_attribute lineNumTable) { + this.parser = parser; + this.lineNumTable = lineNumTable; + } + + int getLineNumber(int pc) { + if (lineNumTable != null) { + int start_pc = 0; + int lineno = 0; + for (int i = 0; i < lineNumTable.line_number_table_length; i++) { + int cur_start_pc = lineNumTable.line_number_table[i].start_pc; + if (pc == 0 && cur_start_pc == 0) { + return lineNumTable.line_number_table[i].line_number; + } else if (pc >= start_pc && pc < cur_start_pc) { + return lineno; + } + start_pc = cur_start_pc; + lineno = lineNumTable.line_number_table[i].line_number; + } + } + return 0; + } + + void addConstantPoolRef(int index, Klass.Method m, int pc) { + try { + CPInfo cpInfo = parser.classfile.constant_pool.get(index); + String name = cpInfo.accept(typeFinder, null); + if (name != null) { + trace(" %s %s at line %d%n", parser.constantPoolParser.tagName(index), name, getLineNumber(pc)); + } + } catch (InvalidIndex ex) { + throw new RuntimeException(ex); + } + } + + public Void visitNoOperands(Instruction instr, Klass.Method m) { + return null; + } + + public Void visitArrayType(Instruction instr, TypeKind kind, Klass.Method m) { + return null; + } + + public Void visitBranch(Instruction instr, int offset, Klass.Method m) { + return null; + } + + public Void visitConstantPoolRef(Instruction instr, int index, Klass.Method m) { + addConstantPoolRef(index, m, instr.getPC()); + return null; + } + + public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Klass.Method m) { + addConstantPoolRef(index, m, instr.getPC()); + return null; + } + + public Void visitLocal(Instruction instr, int index, Klass.Method m) { + return null; + } + + public Void visitLocalAndValue(Instruction instr, int index, int value, Klass.Method m) { + return null; + } + + public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Klass.Method m) { + return null; + } + + public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Klass.Method m) { + return null; + } + + public Void visitValue(Instruction instr, int value, Klass.Method m) { + return null; + } + + public Void visitUnknown(Instruction instr, Klass.Method m) { + return null; + } + private ConstantPool.Visitor typeFinder = new ConstantPool.Visitor() { + + String getClassName(CPRefInfo info, Void p) { + try { + return parser.checkClassName(info.getClassName()).replace('/', '.'); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + } + + boolean addReferencedClass(String name) { + if (Klass.findKlass(name) == null) { + MethodDescriptor md = new MethodDescriptor(name); + if (!methods.contains(md) && !pending.contains(md)) { + pending.add(md); + } + return true; + } + return false; + } + private String privilegedActionClass = ""; + + void cachePrivilegedAction(String classname) { + trace(" found PrivilegedAction %s%n", classname); + privilegedActionClass = classname; + } + + void doPrivilegedCall(String method) { + if (privilegedActionClass.length() > 0) { + MethodDescriptor md = new MethodDescriptor(privilegedActionClass + ".run", "*", false); + if (!methods.contains(md) && !pending.contains(md)) { + trace(" doPrivileged %s%n", md); + pending.add(md); + } + } + } + + private String addMethodDescriptor(CPRefInfo info, Void p) { + try { + String classname = getClassName(info, null); + String method = classname + "." + info.getNameAndTypeInfo().getName(); + String descriptor = info.getNameAndTypeInfo().getType(); + + if (method.endsWith(".") && isPrivilegedAction(classname)) { + cachePrivilegedAction(classname); + } + if (method.equals("java.security.AccessController.doPrivileged")) { + doPrivilegedCall(method); + return method; + } + + boolean interfaceMethodRef = info instanceof CONSTANT_InterfaceMethodref_info; + MethodDescriptor md = new MethodDescriptor(method, descriptor, interfaceMethodRef); + if (!methods.contains(md) && !pending.contains(md)) { + pending.add(md); + } + return method; + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + public String visitClass(CONSTANT_Class_info info, Void p) { + try { + String classname = parser.checkClassName(info.getName()).replace('/', '.'); + if (classname.length() > 0) { + addReferencedClass(classname); + } + return classname; + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + } + + public String visitDouble(CONSTANT_Double_info info, Void p) { + // skip + return null; + } + + public String visitFieldref(CONSTANT_Fieldref_info info, Void p) { + try { + String classname = getClassName(info, p); + if (classname.length() > 0) { + addReferencedClass(classname); + } + + String type = info.getNameAndTypeInfo().getType(); + String fieldType = parser.checkClassName(type).replace('/', '.'); + if (fieldType.length() > 0) { + addReferencedClass(classname); + } + return parser.constantPoolParser.stringValue(info); + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + public String visitFloat(CONSTANT_Float_info info, Void p) { + // skip + return null; + } + + public String visitInteger(CONSTANT_Integer_info info, Void p) { + // skip + return null; + } + + public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { + return addMethodDescriptor(info, p); + } + + public String visitLong(CONSTANT_Long_info info, Void p) { + // skip + return null; + } + + public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) { + // skip + return null; + } + + public String visitMethodref(CONSTANT_Methodref_info info, Void p) { + return addMethodDescriptor(info, p); + } + + public String visitString(CONSTANT_String_info info, Void p) { + // skip + return null; + } + + public String visitUtf8(CONSTANT_Utf8_info info, Void p) { + return null; + } + }; + } + static boolean traceOn = System.getProperty("classanalyzer.debug") != null; + + private static void trace(String format, Object... args) { + if (traceOn) { + System.out.format(format, args); + } + } + + private static void usage() { + System.out.println("Usage: BootAnalyzer "); + System.out.println("Options: "); + System.out.println("\t-jdkhome where all jars will be parsed"); + System.out.println("\t-config "); + System.out.println("\t-output "); + System.out.println("\t-classlist print class list and summary"); + System.exit(-1); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/CheckDeps.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/CheckDeps.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,181 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.classanalyzer; + +import java.io.*; +import java.util.*; + +/** + * A simple tool to check module dependencies against a known list of + * dependencies. The tool fails (by throwing a RuntimeException) is an + * unexpected dependency is detected. + */ + +public class CheckDeps { + + /** + * Represents a dependency from one module to another module. The dependency + * may be optional. + */ + static class Dependency { + private final String module; + private final String other; + private final boolean optional; + + private Dependency(String module, String other, boolean optional) { + this.module = module; + this.other = other; + this.optional = optional; + } + + String module() { return module; } + String other() { return other; } + boolean isOptional() { return optional; } + + /** + * Parses a dependency in one of the following forms: + * a -> b + * [optional] a -> b + */ + static Dependency fromString(String s) { + String[] components = s.split(" "); + int count = components.length; + if (count != 3 && count != 4) + throw new IllegalArgumentException(s); + boolean optional = (count == 4); + if (optional && !components[0].equals("[optional]")) + throw new IllegalArgumentException(s); + String arrow = optional ? components[2] : components[1]; + if (!arrow.equals("->")) + throw new IllegalArgumentException(s); + String module = optional ? components[1] : components[0]; + String other = optional ? components[3] : components[2]; + return new Dependency(module, other, optional); + } + + @Override public String toString() { + StringBuilder sb = new StringBuilder(); + if (optional) + sb.append("[optional] "); + sb.append(module); + sb.append(" -> "); + sb.append(other); + return sb.toString(); + } + } + + /** + * Represents the "tail" + */ + static class DependencyTail { + private final String module; + private final boolean optional; + + DependencyTail(String module, boolean optional) { + this.module = module; + this.optional = optional; + } + String module() { return module; } + boolean isOptional() { return optional; } + } + + static void usage() { + System.out.println("java CheckDeps file1 file2"); + System.out.println(" where file1 is the expected dependencies and file2 is"); + System.out.println(" the actual dependencies. Both files are assumed to be"); + System.out.println(" in modules.summary format (see ClassAnalyzer tool)."); + System.out.println(); + System.out.println("Example usages:"); + System.out.println(" java CheckDeps make/modules/modules.summary " + + "$(OUTPUTDIR)/modules.summary"); + System.exit(-1); + } + + public static void main(String[] args) throws IOException { + if (args.length != 2) + usage(); + + // maps a module to the list of modules that it depends on + Map> expected = + new HashMap>(); + + // parse the expected dependencies file + Scanner s; + s = new Scanner(new FileInputStream(args[0])); + try { + while (s.hasNextLine()) { + Dependency ref = Dependency.fromString(s.nextLine()); + if (ref != null) { + String module = ref.module(); + List list = expected.get(module); + if (list == null) { + list = new ArrayList(); + expected.put(module, list); + } + list.add(new DependencyTail(ref.other(), ref.isOptional())); + } + } + } finally { + s.close(); + } + + // parse the actual dependencies file, checking each dependency + // against the expected list. + boolean fail = false; + s = new Scanner(new FileInputStream(args[1])); + try { + while (s.hasNextLine()) { + Dependency dep = Dependency.fromString(s.nextLine()); + + // check if this dependency is expected + List list = expected.get(dep.module()); + DependencyTail tail = null; + if (list != null) { + for (DependencyTail t: list) { + if (t.module().equals(dep.other())) { + tail = t; + break; + } + } + } + if (tail == null) { + System.err.println("Unexpected dependency: " + dep); + fail = true; + } else { + // hard dependency when optional dependency is expected + if (tail.isOptional() != dep.isOptional()) { + if (tail.isOptional()) { + System.err.println("Unexpected dependency: " + dep); + fail = true; + } + } + } + } + } finally { + s.close(); + } + + if (fail) + throw new RuntimeException("Unexpected dependencies found"); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ClassAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassAnalyzer.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,354 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.classanalyzer; + +import com.sun.classanalyzer.AnnotatedDependency.*; +import com.sun.classanalyzer.Module.Dependency; +import com.sun.classanalyzer.Module.PackageInfo; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.io.File; +import java.io.PrintWriter; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * + * @author Mandy Chung + */ +public class ClassAnalyzer { + + public static void main(String[] args) throws Exception { + String jdkhome = null; + String cpath = null; + List configs = new ArrayList(); + List depconfigs = new ArrayList(); + String output = "."; + boolean mergeModules = true; + boolean showDynamic = false; + + // process arguments + int i = 0; + while (i < args.length) { + String arg = args[i++]; + if (arg.equals("-jdkhome")) { + if (i < args.length) { + jdkhome = args[i++]; + } else { + usage(); + } + } else if (arg.equals("-cpath")) { + if (i < args.length) { + cpath = args[i++]; + } else { + usage(); + } + } else if (arg.equals("-config")) { + if (i < args.length) { + configs.add(args[i++]); + } else { + usage(); + } + } else if (arg.equals("-depconfig")) { + if (i < args.length) { + depconfigs.add(args[i++]); + } else { + usage(); + } + } else if (arg.equals("-output")) { + if (i < args.length) { + output = args[i++]; + } else { + usage(); + } + } else if (arg.equals("-base")) { + ModuleConfig.setBaseModule(args[i++]); + } else if (arg.equals("-nomerge")) { + // analyze the fine-grained module dependencies + mergeModules = false; + } else if (arg.equals("-showdynamic")) { + showDynamic = true; + } else { + System.err.println("Invalid option: " + arg); + usage(); + } + } + + if ((jdkhome == null && cpath == null) || (jdkhome != null && cpath != null)) { + usage(); + } + if (configs.isEmpty()) { + usage(); + } + + if (jdkhome != null) { + ClassPath.setJDKHome(jdkhome); + } else if (cpath != null) { + ClassPath.setClassPath(cpath); + } + + // create output directory if it doesn't exist + File dir = new File(output); + if (!dir.isDirectory()) { + if (!dir.exists()) { + boolean created = dir.mkdir(); + if (!created) { + throw new RuntimeException("Unable to create `" + dir + "'"); + } + } + } + + buildModules(configs, depconfigs, mergeModules); + + // generate output files + for (Module m : modules) { + // only generate reports for top-level modules + if (m.group() == m) { + m.printClassListTo(resolve(dir, m.name(), "classlist")); + m.printResourceListTo(resolve(dir, m.name(), "resources")); + m.printSummaryTo(resolve(dir, m.name(), "summary")); + m.printDependenciesTo(resolve(dir, m.name(), "dependencies"), showDynamic); + } + } + + // Generate other summary reports + printModulesSummary(dir, showDynamic); + printModulesDot(dir, showDynamic); + printModulesList(dir); + printPackagesSummary(dir); + } + private static List modules = new ArrayList(); + + static void buildModules(List configs, + List depconfigs, + boolean mergeModules) throws IOException { + // create modules based on the input config files + for (String file : configs) { + for (ModuleConfig mconfig : ModuleConfig.readConfigurationFile(file)) { + modules.add(Module.addModule(mconfig)); + } + } + + // parse class files + ClassPath.parseAllClassFiles(); + + // Add additional dependencies if specified + if (depconfigs != null && depconfigs.size() > 0) { + DependencyConfig.parse(depconfigs); + } + + // process the roots and dependencies to get the classes for each module + for (Module m : modules) { + m.processRootsAndReferences(); + } + + // update the dependencies for classes that were subsequently allocated + // to modules + for (Module m : modules) { + m.fixupDependencies(); + } + + if (mergeModules) { + Module.buildModuleMembers(); + } + } + + private static void printModulesSummary(File dir, boolean showDynamic) throws IOException { + // print summary of dependencies + PrintWriter writer = new PrintWriter(new File(dir, "modules.summary")); + try { + for (Module m : modules) { + // only show top-level module dependencies + if (m.group() == m) { + for (Dependency dep : m.dependents()) { + if (!showDynamic && dep.dynamic && dep.optional) { + continue; + } + if (dep.module == null || !dep.module.isBase()) { + + String prefix = ""; + if (dep.optional) { + if (dep.dynamic) { + prefix = "[dynamic] "; + } else { + prefix = "[optional] "; + } + } + + Module other = dep != null ? dep.module : null; + writer.format("%s%s -> %s%n", prefix, m, other); + } + } + } + } + } finally { + writer.close(); + } + } + + private static void printModulesDot(File dir, boolean showDynamic) throws IOException { + PrintWriter writer = new PrintWriter(new File(dir, "modules.dot")); + try { + writer.println("digraph jdk {"); + for (Module m : modules) { + if (m.group() == m) { + for (Dependency dep : m.dependents()) { + if (!showDynamic && dep.dynamic && dep.optional) { + continue; + } + if (dep.module == null || !dep.module.isBase()) { + String style = ""; + String color = ""; + String property = ""; + if (dep.optional) { + style = "style=dotted"; + } + if (dep.dynamic) { + color = "color=red"; + } + if (style.length() > 0 || color.length() > 0) { + String comma = ""; + if (style.length() > 0 && color.length() > 0) { + comma = ", "; + } + property = String.format(" [%s%s%s]", style, comma, color); + } + Module other = dep != null ? dep.module : null; + writer.format(" \"%s\" -> \"%s\"%s;%n", m, other, property); + } + } + } + } + writer.println("}"); + } finally { + writer.close(); + } + } + + private static void printMembers(Module m, PrintWriter writer) { + for (Module member : m.members()) { + if (!member.isEmpty()) { + writer.format("%s ", member); + printMembers(member, writer); + } + } + } + + private static void printModulesList(File dir) throws IOException { + // print module group / members relationship + PrintWriter writer = new PrintWriter(new File(dir, "modules.list")); + try { + for (Module m : modules) { + if (m.group() == m && !m.isEmpty()) { + writer.format("%s ", m); + printMembers(m, writer); + writer.println(); + } + } + } finally { + writer.close(); + } + } + + private static void printPackagesSummary(File dir) throws IOException { + // print package / module relationship + PrintWriter writer = new PrintWriter(new File(dir, "modules.pkginfo")); + try { + Map> packages = new TreeMap>(); + Set splitPackages = new TreeSet(); + + for (Module m : modules) { + if (m.group() == m) { + for (PackageInfo info : m.getPackageInfos()) { + Set value = packages.get(info.pkgName); + if (value == null) { + value = new TreeSet(); + packages.put(info.pkgName, value); + } else { + // package in more than one module + splitPackages.add(info.pkgName); + } + value.add(m); + } + } + } + + // packages that are splitted among multiple modules + writer.println("Packages splitted across modules:-\n"); + writer.format("%-60s %s\n", "Package", "Module"); + + for (String pkgname : splitPackages) { + writer.format("%-60s", pkgname); + for (Module m : packages.get(pkgname)) { + writer.format(" %s", m); + } + writer.println(); + } + + writer.println("\nPackage-private dependencies:-"); + for (String pkgname : splitPackages) { + for (Klass k : Klass.getAllClasses()) { + if (k.getPackageName().equals(pkgname)) { + Module m = k.getModule(); + // check if this klass references a package-private + // class that is in a different module + for (Klass other : k.getReferencedClasses()) { + if (other.getModule() != m && + !other.isPublic() && + other.getPackageName().equals(pkgname)) { + String from = k.getClassName() + " (" + m + ")"; + writer.format("%-60s -> %s (%s)\n", from, other, other.getModule()); + } + } + } + } + } + } finally { + writer.close(); + } + + } + + private static String resolve(File dir, String mname, String suffix) { + File f = new File(dir, mname + "." + suffix); + return f.toString(); + + } + + private static void usage() { + System.out.println("Usage: ClassAnalyzer "); + System.out.println("Options: "); + System.out.println("\t-jdkhome where all jars will be parsed"); + System.out.println("\t-cpath where classes and jars will be parsed"); + System.out.println("\t Either -jdkhome or -cpath option can be used."); + System.out.println("\t-config "); + System.out.println("\t This option can be repeated for multiple module config files"); + System.out.println("\t-output "); + System.out.println("\t-nomerge specify not to merge modules"); + System.out.println("\t-showdynamic show dynamic dependencies in the reports"); + System.exit(-1); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ClassFileParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassFileParser.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,629 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ +package com.sun.classanalyzer; + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.Type.*; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import static com.sun.tools.classfile.AccessFlags.*; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** + * + * @author Mandy Chung + */ +public class ClassFileParser { + + final Klass this_klass; + final ClassFile classfile; + final ConstantPoolParser constantPoolParser; + final AnnotationParser annotationParser; + final CodeAttributeParser codeAttributeParser; + private final boolean buildDeps; + + protected ClassFileParser(InputStream in, long size, boolean buildDeps) throws IOException { + try { + this.classfile = ClassFile.read(in); + this.this_klass = getKlass(this.classfile); + this.buildDeps = buildDeps; + this.constantPoolParser = new ConstantPoolParser(this); + this.annotationParser = new AnnotationParser(this); + this.codeAttributeParser = new CodeAttributeParser(this); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + } + + private Klass getKlass(ClassFile cf) throws ConstantPoolException { + Klass k = Klass.getKlass(cf.getName()); + k.setAccessFlags(cf.access_flags.flags); + k.setFileSize(cf.byteLength()); + return k; + } + + public static ClassFileParser newParser(InputStream in, long size, boolean buildDeps) throws IOException { + return new ClassFileParser(in, size, buildDeps); + } + + public static ClassFileParser newParser(String classPathname, boolean buildDeps) throws IOException { + return newParser(new File(classPathname), buildDeps); + } + + public static ClassFileParser newParser(File f, boolean buildDeps) throws IOException { + BufferedInputStream in = new BufferedInputStream(new FileInputStream(f)); + try { + return newParser(in, f.length(), buildDeps); + } finally { + in.close(); + } + } + + public void parseDependency(boolean publicAPIs) throws IOException { + if (publicAPIs && !classfile.access_flags.is(ACC_PUBLIC)) { + // process public APIs only + return; + } + + parseClassInfo(); + if (!publicAPIs) { + // parse all references in the classfile + constantPoolParser.parseDependency(); + } + parseMethods(publicAPIs); + parseFields(publicAPIs); + } + + void parseClassInfo() throws IOException { + ConstantPool cpool = classfile.constant_pool; + try { + Signature_attribute sigAttr = (Signature_attribute) classfile.attributes.get(Attribute.Signature); + if (sigAttr == null) { + // use info from class file header + if (classfile.isClass() && classfile.super_class != 0) { + String sn = classfile.getSuperclassName(); + addExtends(sn); + } + for (int i = 0; i < classfile.interfaces.length; i++) { + String interf = classfile.getInterfaceName(i); + if (classfile.isClass()) { + addImplements(interf); + } else { + addExtends(interf); + } + } + } else { + Type t = sigAttr.getParsedSignature().getType(cpool); + // The signature parser cannot disambiguate between a + // FieldType and a ClassSignatureType that only contains a superclass type. + if (t instanceof Type.ClassSigType) { + Type.ClassSigType cst = Type.ClassSigType.class.cast(t); + if (cst.superclassType != null) { + for (Klass k : getKlass(cst.superclassType)) { + addExtends(k); + } + } + if (cst.superinterfaceTypes != null) { + for (Type t1 : cst.superinterfaceTypes) { + for (Klass k : getKlass(t1)) { + addImplements(k); + } + } + } + } else { + for (Klass k : getKlass(t)) { + addExtends(k); + } + } + } + // parse attributes + annotationParser.parseAttributes(classfile.attributes); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + } + + private void parseFields(boolean publicAPIs) throws IOException { + ConstantPool cpool = classfile.constant_pool; + for (Field f : classfile.fields) { + try { + AccessFlags flags = f.access_flags; + if (publicAPIs && !flags.is(ACC_PUBLIC) && !flags.is(ACC_PROTECTED)) { + continue; + } + String fieldname = f.getName(cpool); + Signature_attribute sigAttr = (Signature_attribute) f.attributes.get(Attribute.Signature); + + if (sigAttr == null) { + Set types = parseDescriptor(f.descriptor); + String info = getFlag(flags) + " " + f.descriptor.getFieldType(cpool) + " " + fieldname; + addFieldTypes(types, info, flags); + } else { + Type t = sigAttr.getParsedSignature().getType(cpool); + String info = getFlag(flags) + " " + t + " " + fieldname; + addFieldTypes(getKlass(t), info, flags); + } + // parse attributes + annotationParser.parseAttributes(f.attributes); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } catch (InvalidDescriptor ex) { + throw new RuntimeException(ex); + } + } + } + + private void parseMethods(boolean publicAPIs) { + for (Method m : classfile.methods) { + if (publicAPIs && !m.access_flags.is(ACC_PUBLIC) && !m.access_flags.is(ACC_PROTECTED)) { + // only interest in the API level + return; + } + + parseMethod(m); + } + } + + String checkClassName(String classname) { + int i = 0; + while (i < classname.length()) { + switch (classname.charAt(i)) { + case 'Z': + case 'B': + case 'C': + case 'S': + case 'I': + case 'J': + case 'F': + case 'D': + return ""; + case 'L': + if (!classname.endsWith(";")) { + throw new RuntimeException("Invalid classname " + classname); + } + return classname.substring(i + 1, classname.length() - 1); + case '[': + i++; + break; + default: + if (classname.endsWith(";")) { + throw new RuntimeException("Invalid classname " + classname); + } + return classname; + + } + } + throw new RuntimeException("Invalid classname " + classname); + } + + private void addExtends(String classname) throws IOException { + if (!buildDeps) { + return; + } + + addExtends(Klass.getKlass(classname)); + } + + private void addExtends(Klass k) { + if (!buildDeps) { + return; + } + + ResolutionInfo resInfo = ResolutionInfo.resolvedExtends(this_klass, k); + resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC)); + this_klass.addDep(k, resInfo); + k.addReferrer(this_klass, resInfo); + } + + private void addImplements(String classname) throws IOException { + if (!buildDeps) { + return; + } + + addImplements(Klass.getKlass(classname)); + } + + private void addImplements(Klass k) { + if (!buildDeps) { + return; + } + + ResolutionInfo resInfo = ResolutionInfo.resolvedImplements(this_klass, k); + resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC)); + + this_klass.addDep(k, resInfo); + + k.addReferrer(this_klass, resInfo); + } + + private Set getKlass(Type type) throws IOException { + Set refTypes = new TreeSet(); + if (!buildDeps) { + return refTypes; + } + + type.accept(typevisitor, refTypes); + return refTypes; + } + private Type.Visitor> typevisitor = new Type.Visitor>() { + + public Void visitSimpleType(SimpleType type, Set klasses) { + // nop + return null; + } + + public Void visitArrayType(ArrayType type, Set klasses) { + try { + klasses.addAll(getKlass(type.elemType)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + return null; + + } + + public Void visitMethodType(MethodType type, Set klasses) { + throw new InternalError("Unexpected type " + type); + } + + public Void visitClassSigType(ClassSigType type, Set klasses) { + try { + if (type.superclassType != null) { + klasses.addAll(getKlass(type.superclassType)); + } + if (type.superinterfaceTypes != null) { + for (Type t : type.superinterfaceTypes) { + klasses.addAll(getKlass(t)); + } + } + if (type.typeParamTypes != null) { + for (Type t : type.typeParamTypes) { + klasses.addAll(getKlass(t)); + } + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + return null; + } + + public Void visitClassType(ClassType type, Set klasses) { + klasses.add(Klass.getKlass(type.getBinaryName())); + if (type.typeArgs != null) { + for (Type t : type.typeArgs) { + try { + klasses.addAll(getKlass(t)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + } + return null; + + } + + public Void visitTypeParamType(TypeParamType type, Set klasses) { + try { + if (type.classBound != null) { + klasses.addAll(getKlass(type.classBound)); + } + if (type.interfaceBounds != null) { + for (Type t : type.interfaceBounds) { + klasses.addAll(getKlass(t)); + } + } + + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + return null; + + } + + public Void visitWildcardType(WildcardType type, Set klasses) { + if (type.boundType != null) { + try { + klasses.addAll(getKlass(type.boundType)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + return null; + + } + }; + + private void printMethod(Method m) { + try { + System.out.println("parsing " + m.getName(classfile.constant_pool) + "(" + + m.descriptor.getParameterTypes(classfile.constant_pool) + ") return type " + + m.descriptor.getReturnType(classfile.constant_pool)); + + } catch (ConstantPoolException ex) { + } catch (InvalidDescriptor ex) { + } + } + + private static StringBuilder appendWord(StringBuilder sb, String word) { + if (sb.length() > 0) { + sb.append(" "); + } + sb.append(word); + return sb; + } + + private static String getFlag(AccessFlags flags) { + StringBuilder modifier = new StringBuilder(); + if (flags.is(ACC_PUBLIC)) { + modifier.append("public"); + } + if (flags.is(ACC_PRIVATE)) { + modifier.append("private"); + } + if (flags.is(ACC_PROTECTED)) { + modifier.append("protected"); + } + if (flags.is(ACC_STATIC)) { + appendWord(modifier, "static"); + } + if (flags.is(ACC_FINAL)) { + appendWord(modifier, "final"); + } + if (flags.is(ACC_SYNCHRONIZED)) { + // return "synchronized"; + } + if (flags.is(0x80)) { + // return (t == Type.Field ? "transient" : null); + // return "transient"; + } + if (flags.is(ACC_VOLATILE)) { + // return "volatile"; + } + if (flags.is(ACC_NATIVE)) { + // return "native"; + } + if (flags.is(ACC_ABSTRACT)) { + appendWord(modifier, "abstract"); + } + if (flags.is(ACC_STRICT)) { + // return "strictfp"; + } + if (flags.is(ACC_MODULE)) { + appendWord(modifier, "module"); + } + return modifier.toString(); + } + + private Klass.Method toKlassMethod(Method m, Descriptor d) { + try { + ConstantPool cpool = classfile.constant_pool; + String methodname = m.getName(cpool); + StringBuilder sb = new StringBuilder(); + sb.append(getFlag(m.access_flags)); + if (methodname.equals("")) { + String s = this_klass.getBasename() + d.getParameterTypes(cpool); + appendWord(sb, s); + } else if (methodname.equals("")) { + // + appendWord(sb, methodname); + } else { + String s = d.getReturnType(cpool) + " " + methodname + d.getParameterTypes(cpool); + appendWord(sb, s); + } + String signature = sb.toString().replace('/', '.'); + return this_klass.getMethod(methodname, signature); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } catch (InvalidDescriptor ex) { + throw new RuntimeException(ex); + } + } + + Klass.Method parseMethod(Method m) { + AccessFlags flags = m.access_flags; + Descriptor d; + List methodExceptions = null; + try { + ConstantPool cpool = classfile.constant_pool; + Klass.Method kmethod; + Signature_attribute sigAttr = (Signature_attribute) m.attributes.get(Attribute.Signature); + if (sigAttr == null) { + d = m.descriptor; + Set types = parseDescriptor(d); + + kmethod = toKlassMethod(m, d); + addMethodTypes(types, kmethod, flags); + } else { + Type.MethodType methodType; + Signature methodSig = sigAttr.getParsedSignature(); + d = methodSig; + try { + kmethod = toKlassMethod(m, d); + methodType = (Type.MethodType) methodSig.getType(cpool); + addMethodTypes(getKlass(methodType.returnType), kmethod, flags); + if (methodType.paramTypes != null) { + for (Type t : methodType.paramTypes) { + addMethodTypes(getKlass(t), kmethod, flags); + } + } + if (methodType.typeParamTypes != null) { + for (Type t : methodType.typeParamTypes) { + addMethodTypes(getKlass(t), kmethod, flags); + } + } + + methodExceptions = methodType.throwsTypes; + if (methodExceptions != null) { + if (methodExceptions.size() == 0) { + methodExceptions = null; + } else { + for (Type t : methodExceptions) { + addCheckedExceptionTypes(getKlass(t), kmethod, flags); + } + } + } + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + Attribute e_attr = m.attributes.get(Attribute.Exceptions); + if (e_attr != null && methodExceptions == null) { + // if there are generic exceptions, there must be erased exceptions + if (e_attr instanceof Exceptions_attribute) { + Exceptions_attribute exceptions = (Exceptions_attribute) e_attr; + for (int i = 0; i < exceptions.number_of_exceptions; i++) { + String classname = checkClassName(exceptions.getException(i, classfile.constant_pool)); + if (classname.length() > 0 && buildDeps) { + Klass to = Klass.getKlass(classname); + ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, kmethod); + resInfo.setPublicAccess(flags.is(ACC_PUBLIC)); + + this_klass.addDep(to, resInfo); + to.addReferrer(this_klass, resInfo); + } + } + } else { + throw new RuntimeException("Invalid attribute: " + e_attr); + } + } + + Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code); + if (c_attr != null) { + codeAttributeParser.parse(c_attr, kmethod); + } + kmethod.isAbstract = classfile.access_flags.is(ACC_ABSTRACT); + kmethod.setCodeLength(m.byteLength()); + + // parse annotation attributes + annotationParser.parseAttributes(m.attributes, kmethod); + return kmethod; + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private void addFieldTypes(Set types, String info, AccessFlags flags) { + if (types.isEmpty() || !buildDeps) { + return; + } + + for (Klass to : types) { + ResolutionInfo resInfo = ResolutionInfo.resolvedField(this_klass, to, info); + resInfo.setPublicAccess(flags.is(ACC_PUBLIC)); + + this_klass.addDep(to, resInfo); + to.addReferrer(this_klass, resInfo); + } + } + + private void addReferencedTypes(Method m, Descriptor d, AccessFlags flags) { + Set types = parseDescriptor(d); + + Klass.Method method = toKlassMethod(m, d); + addMethodTypes(types, method, flags); + } + + private void addMethodTypes(Set types, Klass.Method method, AccessFlags flags) { + if (types.isEmpty() || !buildDeps) { + return; + } + for (Klass to : types) { + ResolutionInfo resInfo = ResolutionInfo.resolvedMethodSignature(this_klass, to, method); + resInfo.setPublicAccess(flags.is(ACC_PUBLIC)); + + this_klass.addDep(to, resInfo); + to.addReferrer(this_klass, resInfo); + } + } + + private void addCheckedExceptionTypes(Set types, Klass.Method method, AccessFlags flags) { + if (types.isEmpty() || !buildDeps) { + return; + } + for (Klass to : types) { + ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, method); + resInfo.setPublicAccess(flags.is(ACC_PUBLIC)); + + this_klass.addDep(to, resInfo); + to.addReferrer(this_klass, resInfo); + } + } + + private Set parseDescriptor(Descriptor d) { + Set types = new TreeSet(); + try { + String desc = d.getValue(classfile.constant_pool); + int p = 0; + while (p < desc.length()) { + String type; + char ch; + switch (ch = desc.charAt(p++)) { + case '(': + case ')': + case '[': + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + case 'V': + continue; + case 'L': + int sep = desc.indexOf(';', p); + if (sep == -1) { + throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc); + } + type = checkClassName(desc.substring(p, sep)); + p = sep + 1; + break; + default: + throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc); + } + + if (!type.isEmpty() && buildDeps) { + Klass to = Klass.getKlass(type); + types.add(to); + + } + } + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + return types; + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ClassPath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ClassPath.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,275 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ +package com.sun.classanalyzer; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * + * @author mchung + */ +public class ClassPath { + + public class FileInfo { + + File file; + JarFile jarfile; + int classCount; + long filesize; + + FileInfo(File f) throws IOException { + this.file = f; + this.classCount = 0; + if (file.getName().endsWith(".jar")) { + this.filesize = file.length(); + jarfile = new JarFile(f); + } + } + + File getFile() { + return file; + } + + JarFile getJarFile() { + return jarfile; + } + + String getName() throws IOException { + return file.getCanonicalPath(); + } + } + private List fileList = new ArrayList(); + private static ClassPath instance = new ClassPath(); + + static List getFileInfos() { + return instance.fileList; + } + + static ClassPath setJDKHome(String jdkhome) throws IOException { + List files = new ArrayList(); + File jre = new File(jdkhome, "jre"); + File lib = new File(jdkhome, "lib"); + if (jre.exists() && jre.isDirectory()) { + listFiles(new File(jre, "lib"), ".jar", files); + } else if (lib.exists() && lib.isDirectory()) { + // either a JRE or a jdk build image + listFiles(lib, ".jar", files); + + File classes = new File(jdkhome, "classes"); + if (classes.exists() && classes.isDirectory()) { + // jdk build outputdir + instance.add(classes); + } + } else { + throw new RuntimeException("\"" + jdkhome + "\" not a JDK home"); + } + + for (File f : files) { + instance.add(f); + } + return instance; + } + + static ClassPath setClassPath(String path) throws IOException { + if (path.endsWith(".class")) { + // one class file + File f = new File(path); + if (!f.exists()) { + throw new RuntimeException("Classfile \"" + f + "\" doesn't exist"); + } + + instance.add(f); + } else { + List jarFiles = new ArrayList(); + String[] locs = path.split(File.pathSeparator); + for (String p : locs) { + File f = new File(p); + if (!f.exists()) { + throw new RuntimeException("\"" + f + "\" doesn't exist"); + } + + if (f.isDirectory()) { + instance.add(f); // add the directory to look up .class files + listFiles(f, ".jar", jarFiles); + } else if (p.endsWith(".jar")) { + // jar files + jarFiles.add(f); + } else { + throw new RuntimeException("Invalid file \"" + f); + } + } + // add jarFiles if any + for (File f : jarFiles) { + instance.add(f); + } + } + + return instance; + } + + private void add(File f) throws IOException { + fileList.add(new FileInfo(f)); + } + + public static InputStream open(String pathname) throws IOException { + for (FileInfo fi : instance.fileList) { + if (fi.getName().endsWith(".jar")) { + String path = pathname.replace(File.separatorChar, '/'); + JarEntry e = fi.jarfile.getJarEntry(path); + if (e != null) { + return fi.jarfile.getInputStream(e); + } + } else if (fi.getFile().isDirectory()) { + File f = new File(fi.getFile(), pathname); + if (f.exists()) { + return new FileInputStream(f); + } + } else if (fi.file.isFile()) { + if (fi.getName().endsWith(File.separator + pathname)) { + return new FileInputStream(fi.file); + } + } + } + return null; + } + + static ClassFileParser parserForClass(String classname) throws IOException { + String pathname = classname.replace('.', File.separatorChar) + ".class"; + + ClassFileParser cfparser = null; + for (FileInfo fi : instance.fileList) { + if (fi.getName().endsWith(".class")) { + if (fi.getName().endsWith(File.separator + pathname)) { + cfparser = ClassFileParser.newParser(fi.getFile(), true); + break; + } + } else if (fi.getName().endsWith(".jar")) { + JarEntry e = fi.jarfile.getJarEntry(classname.replace('.', '/') + ".class"); + if (e != null) { + cfparser = ClassFileParser.newParser(fi.jarfile.getInputStream(e), e.getSize(), true); + break; + } + } else if (fi.getFile().isDirectory()) { + File f = new File(fi.getFile(), pathname); + if (f.exists()) { + cfparser = ClassFileParser.newParser(f, true); + break; + } + } + } + return cfparser; + } + + public static void parseAllClassFiles() throws IOException { + instance.parseFiles(); + } + + private void parseFiles() throws IOException { + Set classes = new HashSet(); + + int count = 0; + for (FileInfo fi : fileList) { + // filter out public generated classes (i.e. not public API) + // javax.management.remote.rmi._RMIConnectionImpl_Tie + // javax.management.remote.rmi._RMIServerImpl_Tie + if (fi.getName().endsWith(".class")) { + parseClass(fi); + } else if (fi.getName().endsWith(".jar")) { + Enumeration entries = fi.jarfile.entries(); + while (entries.hasMoreElements()) { + JarEntry e = entries.nextElement(); + if (e.getName().endsWith(".class")) { + ClassFileParser cfparser = ClassFileParser.newParser(fi.jarfile.getInputStream(e), e.getSize(), true); + cfparser.parseDependency(false); + fi.classCount++; + } else if (!e.isDirectory() && ResourceFile.isResource(e.getName())) { + ResourceFile.addResource(e.getName(), fi.jarfile.getInputStream(e)); + } + } + } else if (fi.getFile().isDirectory()) { + List files = new ArrayList(); + listFiles(fi.getFile(), "", files); + for (File f : files) { + if (f.getName().endsWith(".class")) { + parseClass(fi, f); + } else if (!f.isDirectory() && ResourceFile.isResource(f.getCanonicalPath())) { + String pathname = f.getCanonicalPath(); + String dir = fi.getName(); + if (!pathname.startsWith(dir)) { + throw new RuntimeException("Incorrect pathname " + pathname); + } + String name = pathname.substring(dir.length() + 1, pathname.length()); + BufferedInputStream in = new BufferedInputStream(new FileInputStream(f)); + try { + ResourceFile.addResource(name, in); + } finally { + in.close(); + } + } + } + } else { + // should not reach here + throw new RuntimeException("Unexpected class path: " + fi.getFile()); + } + } + } + + private void parseClass(FileInfo fi) throws IOException { + parseClass(fi, fi.getFile()); + } + + private void parseClass(FileInfo fi, File f) throws IOException { + ClassFileParser cfparser = ClassFileParser.newParser(f, true); + cfparser.parseDependency(false); + fi.classCount++; + // need to update the filesize for this directory + fi.filesize += fi.getFile().length(); + + } + + public static void listFiles(File path, String suffix, List result) { + if (path.isDirectory()) { + File[] children = path.listFiles(); + for (File c : children) { + listFiles(c, suffix, result); + } + + } else { + if (suffix.isEmpty() || path.getName().endsWith(suffix)) { + result.add(path); + } + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/CodeAttributeParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/CodeAttributeParser.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,157 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package com.sun.classanalyzer; + +import com.sun.classanalyzer.Klass.Method; + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.Instruction.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +/** + * + * @author Mandy Chung + */ +public class CodeAttributeParser { + private final ClassFileParser cfparser; + private final ConstantPool cpool; + private final ConstantPoolParser constantPoolParser; + + + static final Map> runtimeReferences = + new HashMap>(); + + + CodeAttributeParser(ClassFileParser parser) { + this.cfparser = parser; + this.cpool = cfparser.classfile.constant_pool; + this.constantPoolParser = cfparser.constantPoolParser; + } + + static boolean parseCodeAttribute = false; // by default don't parse code attribute + static void setParseCodeAttribute(boolean newValue) { + parseCodeAttribute = newValue; + } + + void parse(Code_attribute attr, Klass.Method method) { + if (!parseCodeAttribute) { + return; + } + + for (Instruction instr : attr.getInstructions()) { + try { + instr.accept(instructionVisitor, method); + } catch (ArrayIndexOutOfBoundsException e) { + throw new RuntimeException("error at or after byte " + instr.getPC()); + } + + } + + if (attr.exception_table_langth > 0) { + for (int i = 0; i < + attr.exception_table.length; i++) { + Code_attribute.Exception_data handler = attr.exception_table[i]; + int catch_type = handler.catch_type; + if (catch_type > 0) { + addMethodReference(catch_type, method); + } + + } + } + + } + + + private void addMethodReference(int index, Klass.Method m) { + String method = constantPoolParser.getMethodName(index); + + if (method != null && + (method.equals("java.lang.Class.forName") || + method.equals("java.lang.Class.loadClass") || + method.startsWith("java.util.ServiceLoader.load") || + method.equals("sun.misc.Service.providers"))) { + Set refs = runtimeReferences.get(method); + if (refs == null) { + refs = new TreeSet(); + runtimeReferences.put(method, refs); + } + refs.add(m); + } + } + + Instruction.KindVisitor instructionVisitor = + new Instruction.KindVisitor() { + + public Void visitNoOperands(Instruction instr, Klass.Method m) { + return null; + } + + public Void visitArrayType(Instruction instr, TypeKind kind, Klass.Method m) { + return null; + } + + public Void visitBranch(Instruction instr, int offset, Klass.Method m) { + return null; + } + + public Void visitConstantPoolRef(Instruction instr, int index, Klass.Method m) { + addMethodReference(index, m); + return null; + } + + public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Klass.Method m) { + addMethodReference(index, m); + return null; + } + + public Void visitLocal(Instruction instr, int index, Klass.Method m) { + return null; + } + + public Void visitLocalAndValue(Instruction instr, int index, int value, Klass.Method m) { + return null; + } + + public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Klass.Method m) { + return null; + } + + public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Klass.Method m) { + return null; + } + + public Void visitValue(Instruction instr, int value, Klass.Method m) { + return null; + } + + public Void visitUnknown(Instruction instr, Klass.Method m) { + return null; + } + }; +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolAnalyzer.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.classanalyzer; + +/** + * + * @author Mandy Chung + */ +public class ConstantPoolAnalyzer { + public static void main(String[] args) throws Exception { + String jdkhome = null; + + // process arguments + int i = 0; + while (i < args.length) { + String arg = args[i++]; + if (arg.equals("-jdkhome")) { + if (i < args.length) { + jdkhome = args[i++]; + } else { + usage(); + } + } + } + if (jdkhome == null) { + usage(); + } + ClassPath.setJDKHome(jdkhome); + ClassPath.parseAllClassFiles(); + } + + private static void usage() { + System.out.println("Usage: ConstantPoolAnalyzer "); + System.out.println("Options: "); + System.out.println("\t-jdkhome where all jars will be parsed"); + System.out.println("\t-cpath where classes and jars will be parsed"); + System.exit(-1); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ConstantPoolParser.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,377 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.classanalyzer; + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; +import static com.sun.tools.classfile.ConstantPool.*; + +/** + * + * @author Mandy Chung + */ +public class ConstantPoolParser { + + private final ClassFileParser cfparser; + private final StringValueVisitor visitor; + private final ConstantPool cpool; + + ConstantPoolParser(ClassFileParser parser) { + this.cfparser = parser; + this.cpool = cfparser.classfile.constant_pool; + this.visitor = new StringValueVisitor(); + } + + public String stringValue(CPInfo cpInfo) { + return visitor.visit(cpInfo); + } + + public String stringValue(int constant_pool_index) { + try { + return stringValue(cpool.get(constant_pool_index)); + } catch (ConstantPool.InvalidIndex e) { + throw new RuntimeException(e); + } + } + + public void parseDependency() { + ConstantPool.Visitor v = new ConstantPool.Visitor() { + + public Integer visitClass(CONSTANT_Class_info info, Void p) { + try { + String classname = cfparser.checkClassName(info.getName()); + if (classname.isEmpty()) { + return 1; + } + + Klass from = cfparser.this_klass; + Klass to = Klass.getKlass(classname); + ResolutionInfo resInfo = ResolutionInfo.resolvedConstantPool(from, to, info.name_index); + + from.addDep(to, resInfo); + to.addReferrer(from, resInfo); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + return 1; + } + + public Integer visitDouble(CONSTANT_Double_info info, Void p) { + // skip + return 2; + } + + public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) { + // skip + return 1; + } + + public Integer visitFloat(CONSTANT_Float_info info, Void p) { + // skip + return 1; + } + + public Integer visitInteger(CONSTANT_Integer_info info, Void p) { + // skip + return 1; + } + + public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { + // skip + return 1; + } + + public Integer visitLong(CONSTANT_Long_info info, Void p) { + // skip + return 2; + } + + public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) { + // skip + return 1; + } + + public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) { + // skip + return 1; + } + + public Integer visitString(CONSTANT_String_info info, Void p) { + // skip + return 1; + } + + public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) { + // skip + return 1; + } + }; + int cpx = 1; + while (cpx < cpool.size()) { + try { + CPInfo cpInfo = cpool.get(cpx); + cpx += cpInfo.accept(v, null); + } catch (ConstantPool.InvalidIndex ex) { + throw new RuntimeException(ex); + } + } + } + + int getTag(int index) { + try { + return cpool.get(index).getTag(); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + } + + String getDescriptor(int index) { + CPInfo cpInfo; + try { + cpInfo = cpool.get(index); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + + int tag = cpInfo.getTag(); + switch (tag) { + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: + case CONSTANT_Fieldref: + // simplify references within this class + CPRefInfo ref = (CPRefInfo) cpInfo; + try { + return ref.getNameAndTypeInfo().getType(); + } catch (ConstantPoolException ex) { + } + } + return stringValue(cpInfo); + } + + String getMethodName(int index) { + try { + CPInfo cpInfo = cpool.get(index); + if (cpInfo.getTag() == CONSTANT_Methodref || + cpInfo.getTag() == CONSTANT_InterfaceMethodref) { + + // simplify references within this class + CPRefInfo ref = (CPRefInfo) cpInfo; + String classname; + if (ref.class_index == cfparser.classfile.this_class) { + classname = cfparser.this_klass.getClassName(); + } else { + classname = cfparser.checkClassName(ref.getClassName()).replace('/', '.'); + } + String methodname = ref.getNameAndTypeInfo().getName(); + return classname + "." + methodname; + } else { + return null; + } + } catch (InvalidIndex ex) { + throw new RuntimeException(ex); + } catch (ConstantPoolException ex) { + throw new RuntimeException(ex); + } + + } + + class StringValueVisitor implements ConstantPool.Visitor { + + public StringValueVisitor() { + } + + public String visit(CPInfo info) { + return info.accept(this, null); + } + + public String visitClass(CONSTANT_Class_info info, Void p) { + return getCheckedName(info); + } + + String getCheckedName(CONSTANT_Class_info info) { + try { + return checkName(info.getName()); + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + public String visitDouble(CONSTANT_Double_info info, Void p) { + return info.value + "d"; + } + + public String visitFieldref(CONSTANT_Fieldref_info info, Void p) { + return visitRef(info, p); + } + + public String visitFloat(CONSTANT_Float_info info, Void p) { + return info.value + "f"; + } + + public String visitInteger(CONSTANT_Integer_info info, Void p) { + return String.valueOf(info.value); + } + + public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) { + return visitRef(info, p); + } + + public String visitLong(CONSTANT_Long_info info, Void p) { + return info.value + "l"; + } + + public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) { + return getCheckedName(info) + ":" + getType(info); + } + + String getCheckedName(CONSTANT_NameAndType_info info) { + try { + return checkName(info.getName()); + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + String getType(CONSTANT_NameAndType_info info) { + try { + return info.getType(); + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + public String visitMethodref(CONSTANT_Methodref_info info, Void p) { + return visitRef(info, p); + } + + public String visitString(CONSTANT_String_info info, Void p) { + try { + int string_index = info.string_index; + return cpool.getUTF8Info(string_index).accept(this, p); + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + + public String visitUtf8(CONSTANT_Utf8_info info, Void p) { + String s = info.value; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '\t': + sb.append('\\').append('t'); + break; + case '\n': + sb.append('\\').append('n'); + break; + case '\r': + sb.append('\\').append('r'); + break; + case '\"': + sb.append('\\').append('\"'); + break; + default: + sb.append(c); + } + } + return sb.toString(); + } + + String visitRef(CPRefInfo info, Void p) { + String cn = getCheckedClassName(info); + String nat; + try { + nat = info.getNameAndTypeInfo().accept(this, p); + } catch (ConstantPoolException e) { + nat = e.getMessage(); + } + return cn + "." + nat; + } + + String getCheckedClassName(CPRefInfo info) { + try { + return checkName(info.getClassName()); + } catch (ConstantPoolException e) { + throw new RuntimeException(e); + } + } + } + /* If name is a valid binary name, return it; otherwise quote it. */ + + private static String checkName(String name) { + if (name == null) { + return "null"; + } + + int len = name.length(); + if (len == 0) { + return "\"\""; + } + + int cc = '/'; + int cp; + for (int k = 0; k < len; k += Character.charCount(cp)) { + cp = name.codePointAt(k); + if ((cc == '/' && !Character.isJavaIdentifierStart(cp)) || (cp != '/' && !Character.isJavaIdentifierPart(cp))) { + return "\"" + name + "\""; + } + cc = cp; + } + return name; + } + + String tagName(int index) { + try { + int tag = cpool.get(index).getTag(); + switch (tag) { + case CONSTANT_Utf8: + return "Utf8"; + case CONSTANT_Integer: + return "int"; + case CONSTANT_Float: + return "float"; + case CONSTANT_Long: + return "long"; + case CONSTANT_Double: + return "double"; + case CONSTANT_Class: + return "class"; + case CONSTANT_String: + return "String"; + case CONSTANT_Fieldref: + return "Field"; + case CONSTANT_Methodref: + return "Method"; + case CONSTANT_InterfaceMethodref: + return "InterfaceMethod"; + case CONSTANT_NameAndType: + return "NameAndType"; + default: + return "(unknown tag)"; + } + } catch (InvalidIndex e) { + throw new RuntimeException(e); + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/DependencyConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/DependencyConfig.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,99 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.classanalyzer; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; + +/** + * Config file specifying additional dependency + * Each line consists of: + * -> + * where can be: + * @ClassForName and is its dependency + * @Provider and is the service name + * @Providers and is the list of the service names + * + * @author Mandy Chung + */ +public class DependencyConfig { + private DependencyConfig() { + } + + static void parse(List configs) throws IOException { + for (String s : configs) { + parse(s); + } + } + + private static void parse(String config) throws IOException { + // parse configuration file + FileInputStream in = new FileInputStream(config); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String line; + int lineNumber = 0; + String type = null; + while ((line = reader.readLine()) != null) { + lineNumber++; + line = line.trim(); + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + if (line.charAt(0) == '@') { + if (AnnotatedDependency.isValidType(line)) { + type = line; + continue; + } else { + throw new RuntimeException(config + ", line " + + lineNumber + ", invalid annotation type."); + } + } + String[] s = line.split("\\s+"); + if (s.length < 3 || !s[1].equals("->")) { + throw new RuntimeException(config + ", line " + + lineNumber + ", is malformed"); + } + String classname = s[0].trim(); + String value = s[2].trim(); + + Klass k = Klass.findKlass(classname); + if (k == null) { + // System.out.println("Warning: " + classname + " cannot be found"); + continue; + } + AnnotatedDependency dep = AnnotatedDependency.newAnnotatedDependency(type, value, k); + if (dep == null) { + throw new RuntimeException(config + ", line " + + lineNumber + ", is malformed. Fail to construct the dependency."); + } + } + + } finally { + in.close(); + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/Klass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/Klass.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,357 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package com.sun.classanalyzer; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; + +import com.sun.tools.classfile.AccessFlags; + +/** + * + * @author Mandy Chung + */ +public class Klass implements Comparable { + private final String classname; + private final String packagename; + private Module module; + private boolean isJavaLangObject; + private String[] paths; + private Map> methods; + private AccessFlags accessFlags; + private long filesize; + + private SortedMap> deps; + private SortedMap> referrers; + private List annotatedDeps; + private Set classForNameRefs; + + private Klass(String classname) { + this.classname = classname; + this.paths = classname.replace('.', '/').split("/"); + this.isJavaLangObject = classname.equals("java.lang.Object"); + this.deps = new TreeMap>(); + this.referrers = new TreeMap>(); + this.methods = new HashMap>(); + this.annotatedDeps = new ArrayList(); + this.classForNameRefs = new TreeSet(); + + int pos = classname.lastIndexOf('.'); + this.packagename = (pos > 0) ? classname.substring(0, pos) : ""; + } + + String getBasename() { + return paths[paths.length - 1]; + } + + String getClassName() { + return classname; + } + + String getPackageName() { + return packagename; + } + + String getClassFilePathname() { + StringBuilder sb = new StringBuilder(paths[0]); + for (int i = 1; i < paths.length; i++) { + String p = paths[i]; + sb.append(File.separator).append(p); + } + return sb.append(".class").toString(); + } + + boolean isPublic() { + return accessFlags == null || accessFlags.is(AccessFlags.ACC_PUBLIC); + } + + Module getModule() { + return module; + } + + void setModule(Module m) { + if (module != null) { + throw new RuntimeException("Module for " + this + " already set"); + } + this.module = m; + } + + Set getReferencedClasses() { + return deps.keySet(); + } + + Set getReferencingClasses() { + return referrers.keySet(); + } + + void setAccessFlags(int flags) { + this.accessFlags = new AccessFlags(flags); + } + + void setFileSize(long size) { + this.filesize = size; + } + + long getFileSize() { + return this.filesize; + } + + boolean exists() { + return filesize > 0; + } + + boolean skip(Klass k) { + // skip if either class is a root or same class + return k.isJavaLangObject || this == k || k.classname.equals(classname); + } + + void addDep(Method callee, ResolutionInfo resInfo) { + addDep(callee.getKlass(), resInfo); + } + + void addDep(Klass ref, ResolutionInfo ri) { + if (skip(ref)) { + return; + } + Set resInfos; + if (!deps.containsKey(ref)) { + resInfos = new TreeSet(); + deps.put(ref, resInfos); + } else { + resInfos = deps.get(ref); + } + resInfos.add(ri); + } + + void addReferrer(Method caller, ResolutionInfo resInfo) { + addReferrer(caller.getKlass(), resInfo); + } + + void addReferrer(Klass k, ResolutionInfo ri) { + if (skip(k)) { + return; + } + Set resInfos; + if (!referrers.containsKey(k)) { + resInfos = new TreeSet(); + referrers.put(k, resInfos); + } else { + resInfos = referrers.get(k); + } + resInfos.add(ri); + } + + Method getMethod(String name) { + return getMethod(name, ""); + } + + Method getMethod(String name, String signature) { + Set set; + if (methods.containsKey(name)) { + set = methods.get(name); + } else { + set = new TreeSet(); + methods.put(name, set); + } + + for (Method m : set) { + if (m.getName().equals(name) && m.getSignature().equals(signature)) { + return m; + } + } + Method m = new Method(this, name, signature); + set.add(m); + return m; + } + + @Override + public String toString() { + return classname; + } + + @Override + public int compareTo(Klass o) { + return classname.compareTo(o.classname); + } + + void addAnnotatedDep(AnnotatedDependency dep) { + annotatedDeps.add(dep); + } + + void addClassForNameReference(String method) { + classForNameRefs.add(method); + } + + List getAnnotatedDeps() { + return annotatedDeps; + } + + private static Map classes = new TreeMap(); + static Set getAllClasses() { + return new TreeSet(classes.values()); + } + + static Klass findKlassFromPathname(String filename) { + String name = filename; + if (filename.endsWith(".class")) { + name = filename.substring(0, filename.length() - 6); + } + + // trim ".class" + name = name.replace('/', '.'); + for (Klass k : classes.values()) { + if (name.endsWith(k.getClassName())) { + return k; + } + } + return null; + } + + static Klass findKlass(String classname) { + return classes.get(classname); + } + + static Klass getKlass(String name) { + Klass k; + String classname = name.replace('/', '.'); + if (classname.charAt(classname.length() - 1) == ';') { + classname = classname.substring(0, classname.length() - 1); + } + if (classes.containsKey(classname)) { + k = classes.get(classname); + } else { + k = new Klass(classname); + classes.put(classname, k); + } + return k; + } + + public class Method implements Comparable { + + private final Klass k; + private final String method; + private final String signature; + private long codeLength; + // non-primitive types only + private final List argTypes; + private final Klass returnType; + boolean isAbstract = false; + boolean marked = false; + + public Method(Klass k, String method, String signature) { + this(k, method, signature, null, null); + } + + public Method(Klass k, String method, String signature, Klass returnType, List argTypes) { + this.k = k; + this.method = method; + this.signature = signature; + this.argTypes = argTypes; + this.returnType = returnType; + this.codeLength = 0; + } + + public Klass getKlass() { + return k; + } + + public String getName() { + return method; + } + + public String getSignature() { + return signature; + } + + public Klass getReturnType() { + return returnType; + } + + public List argTypes() { + return argTypes; + } + + public void setCodeLength(long len) { + this.codeLength = len; + } + + public long getCodeLength() { + return codeLength; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Method) { + return compareTo((Method) o) == 0; + } else { + return false; + } + } + + @Override + public int hashCode() { + int hash = 3; + hash = 71 * hash + (this.k != null ? this.k.hashCode() : 0); + hash = 71 * hash + (this.method != null ? this.method.hashCode() : 0); + return hash; + } + + @Override + public String toString() { + if (signature.isEmpty()) { + return k.classname + "." + method; + } else { + return signature; + } + } + + public String toHtmlString() { + return toString().replace("<", "<").replace(">", ">"); + } + + boolean isClinit() { + return method.equals(""); + } + + public int compareTo(Method m) { + if (k == m.getKlass()) { + if (method.equals(m.method)) { + return signature.compareTo(m.signature); + } else { + return method.compareTo(m.method); + } + } else { + return k.compareTo(m.getKlass()); + } + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/Module.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/Module.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,693 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ +package com.sun.classanalyzer; + +import com.sun.classanalyzer.AnnotatedDependency.OptionalDependency; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +/** + * + * @author Mandy Chung + */ +public class Module implements Comparable { + + private static Map modules = new LinkedHashMap(); + + public static Module addModule(ModuleConfig config) { + String name = config.module; + if (modules.containsKey(name)) { + throw new RuntimeException("module \"" + name + "\" already exists"); + } + + Module m = new Module(config); + modules.put(name, m); + return m; + } + + public static Module findModule(String name) { + return modules.get(name); + } + + static Collection getAllModules() { + return Collections.unmodifiableCollection(modules.values()); + } + private final String name; + private final ModuleConfig config; + private final Set classes; + private final Set resources; + private final Set unresolved; + private final Set dependents; + private final Map packages; + private final Set members; + private Module group; + private boolean isBaseModule; + + private Module(ModuleConfig config) { + this.name = config.module; + this.isBaseModule = config.isBase; + this.classes = new TreeSet(); + this.resources = new TreeSet(); + this.config = config; + this.unresolved = new HashSet(); + this.dependents = new TreeSet(); + this.packages = new TreeMap(); + this.members = new TreeSet(); + this.group = this; // initialize to itself + } + + String name() { + return name; + } + + Module group() { + return group; + } + + boolean isBase() { + return isBaseModule; + } + + Set members() { + return members; + } + + boolean contains(Klass k) { + return k != null && classes.contains(k); + } + + boolean isEmpty() { + return classes.isEmpty() && resources.isEmpty(); + } + + /** + * Returns an Iterable of Dependency, only one for each dependent + * module of the strongest dependency (i.e. + * hard static > hard dynamic > optional static > optional dynamic + */ + Iterable dependents() { + Map deps = new LinkedHashMap(); + for (Dependency dep : dependents) { + Dependency d = deps.get(dep.module); + if (d == null || dep.compareTo(d) > 0) { + deps.put(dep.module, dep); + } + } + return deps.values(); + } + + @Override + public int compareTo(Module o) { + if (o == null) { + return -1; + } + return name.compareTo(o.name); + } + + @Override + public String toString() { + return name; + } + + void addKlass(Klass k) { + classes.add(k); + k.setModule(this); + + // update package statistics + String pkg = k.getPackageName(); + PackageInfo pkginfo = packages.get(pkg); + if (pkginfo == null) { + pkginfo = new PackageInfo(pkg); + packages.put(pkg, pkginfo); + } + if (k.exists()) { + // only count the class that is parsed + pkginfo.add(k.getFileSize()); + } + } + + void addResource(ResourceFile res) { + resources.add(res); + res.setModule(this); + } + + void processRootsAndReferences() { + // start with the root set + Deque pending = new ArrayDeque(); + for (Klass k : Klass.getAllClasses()) { + if (k.getModule() != null) { + continue; + } + String classname = k.getClassName(); + if (config.matchesRoot(classname) && !config.isExcluded(classname)) { + addKlass(k); + pending.add(k); + } + } + + // follow all references + Klass k; + while ((k = pending.poll()) != null) { + if (!classes.contains(k)) { + addKlass(k); + } + for (Klass other : k.getReferencedClasses()) { + Module otherModule = other.getModule(); + if (otherModule != null && otherModule != this) { + // this module is dependent on otherModule + addDependency(k, other); + continue; + } + + if (!classes.contains(other)) { + if (config.isExcluded(other.getClassName())) { + // reference to an excluded class + unresolved.add(new Reference(k, other)); + } else { + pending.add(other); + } + } + } + } + + // add other matching classes that don't require dependency analysis + for (Klass c : Klass.getAllClasses()) { + if (c.getModule() == null) { + String classname = c.getClassName(); + if (config.matchesIncludes(classname) && !config.isExcluded(classname)) { + addKlass(c); + // dependencies + for (Klass other : c.getReferencedClasses()) { + Module otherModule = other.getModule(); + if (otherModule == null) { + unresolved.add(new Reference(c, other)); + } else { + if (otherModule != this) { + // this module is dependent on otherModule + addDependency(c, other); + } + } + } + } + } + } + + + // add other matching classes that don't require dependency analysis + for (ResourceFile res : ResourceFile.getAllResources()) { + if (res.getModule() == null) { + String name = res.getName(); + if (config.matchesIncludes(name) && !config.isExcluded(name)) { + addResource(res); + } + } + } + } + + void addDependency(Klass from, Klass to) { + Dependency dep = new Dependency(from, to); + dependents.add(dep); + } + + void fixupDependencies() { + // update dependencies for classes that were allocated to modules after + // this module was processed. + for (Reference ref : unresolved) { + Module m = ref.referree().getModule(); + if (m == null || m != this) { + addDependency(ref.referrer, ref.referree); + } + } + + fixupAnnotatedDependencies(); + } + + private void fixupAnnotatedDependencies() { + // add dependencies that this klass may depend on due to the AnnotatedDependency + dependents.addAll(AnnotatedDependency.getDependencies(this)); + } + + boolean isModuleDependence(Klass k) { + Module m = k.getModule(); + return m == null || (!classes.contains(k) && !m.isBase()); + } + + Module getModuleDependence(Klass k) { + if (isModuleDependence(k)) { + Module m = k.getModule(); + if (group == this && m != null) { + // top-level module + return m.group; + } else { + return m; + } + } + return null; + } + +

void visit(Set visited, Visitor

visitor, P p) { + if (!visited.contains(this)) { + visited.add(this); + visitor.preVisit(this, p); + for (Module m : members) { + m.visit(visited, visitor, p); + visitor.postVisit(this, m, p); + } + } else { + throw new RuntimeException("Cycle detected: module " + this.name); + } + } + + void addMember(Module m) { + // merge class list + for (Klass k : m.classes) { + classes.add(k); + } + + // merge resource list + for (ResourceFile res : m.resources) { + resources.add(res); + } + + // merge the package statistics + for (PackageInfo pinfo : m.getPackageInfos()) { + String packageName = pinfo.pkgName; + PackageInfo pkginfo = packages.get(packageName); + if (pkginfo == null) { + pkginfo = new PackageInfo(packageName); + packages.put(packageName, pkginfo); + } + pkginfo.add(pinfo); + } + } + + static void buildModuleMembers() { + // set up module member relationship + for (Module m : modules.values()) { + m.group = m; // initialize to itself + for (String name : m.config.members()) { + Module member = modules.get(name); + if (member == null) { + throw new RuntimeException("module \"" + name + "\" doesn't exist"); + } + m.members.add(member); + } + } + + // set up the top-level module + Visitor groupSetter = new Visitor() { + + public void preVisit(Module m, Module p) { + m.group = p; + if (p.isBaseModule) { + // all members are also base + m.isBaseModule = true; + } + } + + public void postVisit(Module m, Module child, Module p) { + // nop - breadth-first search + } + }; + + // propagate the top-level module to all its members + for (Module p : modules.values()) { + for (Module m : p.members) { + if (m.group == m) { + m.visit(new TreeSet(), groupSetter, p); + } + } + } + + Visitor mergeClassList = new Visitor() { + + public void preVisit(Module m, Module p) { + // nop - depth-first search + } + + public void postVisit(Module m, Module child, Module p) { + m.addMember(child); + } + }; + + Set visited = new TreeSet(); + for (Module m : modules.values()) { + if (m.group() == m) { + if (m.members().size() > 0) { + // merge class list from all its members + m.visit(visited, mergeClassList, m); + } + + // clear the dependencies before fixup + m.dependents.clear(); + + // fixup dependencies + for (Klass k : m.classes) { + for (Klass other : k.getReferencedClasses()) { + if (m.isModuleDependence(other)) { + // this module is dependent on otherModule + m.addDependency(k, other); + } + } + } + + // add dependencies that this klass may depend on due to the AnnotatedDependency + m.fixupAnnotatedDependencies(); + } + } + } + + class PackageInfo implements Comparable { + + final String pkgName; + int count; + long filesize; + + PackageInfo(String name) { + this.pkgName = name; + this.count = 0; + this.filesize = 0; + } + + void add(PackageInfo pkg) { + this.count += pkg.count; + this.filesize += pkg.filesize; + } + + void add(long size) { + count++; + filesize += size; + + } + + @Override + public int compareTo(Object o) { + return pkgName.compareTo(((PackageInfo) o).pkgName); + } + } + + Set getPackageInfos() { + return new TreeSet(packages.values()); + } + + void printSummaryTo(String output) throws IOException { + PrintWriter writer = new PrintWriter(output); + try { + long total = 0L; + int count = 0; + writer.format("%10s\t%10s\t%s\n", "Bytes", "Classes", "Package name"); + for (String pkg : packages.keySet()) { + PackageInfo info = packages.get(pkg); + if (info.count > 0) { + writer.format("%10d\t%10d\t%s\n", info.filesize, info.count, pkg); + total += info.filesize; + count += info.count; + } + } + + writer.format("\nTotal: %d bytes (uncompressed) %d classes\n", total, count); + } finally { + writer.close(); + } + + } + + void printClassListTo(String output) throws IOException { + // no file created if the module doesn't have any class + if (classes.isEmpty()) { + return; + } + + PrintWriter writer = new PrintWriter(output); + try { + for (Klass c : classes) { + if (c.exists()) { + writer.format("%s\n", c.getClassFilePathname()); + } else { + trace("%s in module %s missing\n", c, this); + } + } + + } finally { + writer.close(); + } + } + + void printResourceListTo(String output) throws IOException { + // no file created if the module doesn't have any resource file + if (resources.isEmpty()) { + return; + } + + PrintWriter writer = new PrintWriter(output); + try { + for (ResourceFile res : resources) { + writer.format("%s\n", res.getPathname()); + } + } finally { + writer.close(); + } + } + + void printDependenciesTo(String output, boolean showDynamic) throws IOException { + // no file created if the module doesn't have any class + if (classes.isEmpty()) { + return; + } + + PrintWriter writer = new PrintWriter(output); + try { + // classes that this klass may depend on due to the AnnotatedDependency + Map> annotatedDeps = AnnotatedDependency.getReferences(this); + + for (Klass klass : classes) { + Set references = klass.getReferencedClasses(); + for (Klass other : references) { + String classname = klass.getClassName(); + boolean optional = OptionalDependency.isOptional(klass, other); + if (optional) { + classname = "[optional] " + classname; + } + + Module m = getModuleDependence(other); + if (m != null || other.getModule() == null) { + writer.format("%-40s -> %s (%s)", classname, other, m); + Reference ref = new Reference(klass, other); + if (annotatedDeps.containsKey(ref)) { + for (AnnotatedDependency ad : annotatedDeps.get(ref)) { + writer.format(" %s", ad.getTag()); + } + // printed; so remove the dependency from the annotated deps list + annotatedDeps.remove(ref); + } + writer.format("\n"); + } + } + } + + + // print remaining dependencies specified in AnnotatedDependency list + if (annotatedDeps.size() > 0) { + for (Map.Entry> entry : annotatedDeps.entrySet()) { + Reference ref = entry.getKey(); + Module m = getModuleDependence(ref.referree); + if (m != null || ref.referree.getModule() == null) { + String classname = ref.referrer.getClassName(); + boolean optional = true; + boolean dynamic = true; + String tag = ""; + for (AnnotatedDependency ad : entry.getValue()) { + if (optional && !ad.isOptional()) { + optional = false; + tag = ad.getTag(); + } + if (!ad.isDynamic()) { + dynamic = false; + } + } + if (!showDynamic && optional && dynamic) { + continue; + } + if (optional) { + if (dynamic) { + classname = "[dynamic] " + classname; + } else { + classname = "[optional] " + classname; + } + } + writer.format("%-40s -> %s (%s) %s%n", classname, ref.referree, m, tag); + } + } + } + + } finally { + writer.close(); + } + } + + static class Dependency implements Comparable { + + final Module module; + final boolean optional; + final boolean dynamic; + + Dependency(Klass from, Klass to) { + // static dependency + this.module = to.getModule() != null ? to.getModule().group() : null; + this.optional = OptionalDependency.isOptional(from, to); + this.dynamic = false; + } + + Dependency(Module m, boolean optional, boolean dynamic) { + this.module = m != null ? m.group() : null; + this.optional = optional; + this.dynamic = dynamic; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Dependency)) { + return false; + } + if (this == obj) { + return true; + } + + Dependency d = (Dependency) obj; + if (this.module != d.module) { + return false; + } else { + return this.optional == d.optional && this.dynamic == d.dynamic; + } + } + + @Override + public int hashCode() { + int hash = 3; + hash = 19 * hash + (this.module != null ? this.module.hashCode() : 0); + hash = 19 * hash + (this.optional ? 1 : 0); + hash = 19 * hash + (this.dynamic ? 1 : 0); + return hash; + } + + @Override + public int compareTo(Dependency d) { + if (this.equals(d)) { + return 0; + } + + // Hard static > hard dynamic > optional static > optional dynamic + if (this.module == d.module) { + if (this.optional == d.optional) { + return this.dynamic ? -1 : 1; + } else { + return this.optional ? -1 : 1; + } + } else if (this.module != null && d.module != null) { + return (this.module.compareTo(d.module)); + } else { + return (this.module == null) ? -1 : 1; + } + } + + @Override + public String toString() { + String s = module.name(); + if (dynamic && optional) { + s += " (dynamic)"; + } else if (optional) { + s += " (optional)"; + } + return s; + } + } + + static class Reference implements Comparable { + + private final Klass referrer, referree; + + Reference(Klass referrer, Klass referree) { + this.referrer = referrer; + this.referree = referree; + } + + Klass referrer() { + return referrer; + } + + Klass referree() { + return referree; + } + + @Override + public int hashCode() { + return referrer.hashCode() ^ referree.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Reference)) { + return false; + } + if (this == obj) { + return true; + } + + Reference r = (Reference) obj; + return (this.referrer.equals(r.referrer) && + this.referree.equals(r.referree)); + } + + @Override + public int compareTo(Reference r) { + int ret = referrer.compareTo(r.referrer); + if (ret == 0) { + ret = referree.compareTo(r.referree); + } + return ret; + } + } + + interface Visitor

{ + + public void preVisit(Module m, P param); + + public void postVisit(Module m, Module child, P param); + } + private static boolean traceOn = System.getProperty("classanalyzer.debug") != null; + + private static void trace(String format, Object... params) { + System.err.format(format, params); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ModuleConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ModuleConfig.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,562 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.classanalyzer; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.regex.Pattern; + +/** + * + * @author Mandy Chung + */ +public class ModuleConfig { + + private static String baseModuleName = "base"; + private final Set roots; + private final Set includes; + private final Filter filter; + private List members; + final String module; + final boolean isBase; + + private ModuleConfig(String name) throws IOException { + this.roots = new TreeSet(); + this.includes = new TreeSet(); + this.module = name; + this.isBase = name.equals(baseModuleName); + this.filter = new Filter(this); + } + + List members() { + if (members == null) { + members = new LinkedList(); + + for (String s : includes) { + if (!s.contains("*") && Module.findModule(s) != null) { + // module member + members.add(s); + } + } + } + return members; + } + + boolean matchesRoot(String name) { + for (String pattern : roots) { + if (matches(name, pattern)) { + return true; + } + } + return false; + } + + boolean matchesIncludes(String name) { + for (String pattern : includes) { + if (matches(name, pattern)) { + return true; + } + } + return false; + } + + boolean isExcluded(String name) { + return filter.isExcluded(name); + } + + boolean matchesPackage(String packageName, String pattern) { + int pos = pattern.lastIndexOf('.'); + String pkg = pos > 0 ? pattern.substring(0, pos) : ""; + return packageName.equals(pkg); + } + + + boolean matches(String name, String pattern) { + if (pattern.contains("**") && !pattern.endsWith("**")) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + String javaName = name; + + boolean isResourceFile = name.indexOf('/') >= 0; + if (isResourceFile) { + // it's a resource file; convert the name as a java + javaName = name.replace('/', '.'); + } + if (pattern.indexOf('/') < 0) { + // if the pattern doesn't contain '/ + return matchesJavaName(javaName, pattern); + } else { + if (isResourceFile) { + // the pattern is for matching resource file + return matchesNameWithSlash(name, pattern); + } else { + return false; + } + } + } + + boolean matchesJavaName(String name, String pattern) { + int pos = name.lastIndexOf('.'); + String packageName = pos > 0 ? name.substring(0, pos) : ""; + if (pattern.endsWith("**")) { + String p = pattern.substring(0, pattern.length() - 2); + return name.startsWith(p); + } else if (pattern.endsWith("*") && pattern.indexOf('*') == pattern.lastIndexOf('*')) { + if (matchesPackage(packageName, pattern)) { + // package name has to be exact match + String p = pattern.substring(0, pattern.length() - 1); + return name.startsWith(p); + } else { + return false; + } + } else if (pattern.contains("*")) { + String basename = pos > 0 ? name.substring(pos + 1, name.length()) : name; + pos = pattern.indexOf('*'); + String prefix = pattern.substring(0, pos); + String suffix = pattern.substring(pos + 1, pattern.length()); + if (name.startsWith(prefix) && matchesPackage(packageName, prefix)) { + // package name has to be exact match + if (suffix.contains("*")) { + return name.matches(convertToRegex(pattern)); + } else { + return basename.endsWith(suffix); + } + } else { + // we don't support wildcard be used in the package name + return false; + } + } else { + // exact match or inner class + return name.equals(pattern) || name.startsWith(pattern + "$"); + } + } + + boolean matchesNameWithSlash(String name, String pattern) { + if (pattern.endsWith("**")) { + String p = pattern.substring(0, pattern.length() - 2); + return name.startsWith(p); + } else if (pattern.contains("*")) { + int pos = pattern.indexOf('*'); + String prefix = pattern.substring(0, pos); + String suffix = pattern.substring(pos + 1, pattern.length()); + String tail = name.substring(pos, name.length()); + + if (!name.startsWith(prefix)) { + // prefix has to exact match + return false; + } + + if (pattern.indexOf('*') == pattern.lastIndexOf('*')) { + // exact match prefix with no '/' in the tail string + String wildcard = tail.substring(0, tail.length() - suffix.length()); + return tail.indexOf('/') < 0 && tail.endsWith(suffix); + } + + if (suffix.contains("*")) { + return matchesNameWithSlash(tail, suffix); + } else { + // tail ends with the suffix while no '/' in the wildcard matched string + String any = tail.substring(0, tail.length() - suffix.length()); + return tail.endsWith(suffix) && any.indexOf('/') < 0; + } + } else { + // exact match + return name.equals(pattern); + } + } + + private String convertToRegex(String pattern) { + StringBuilder sb = new StringBuilder(); + int i = 0; + int index = 0; + int plen = pattern.length(); + while (i < plen) { + char p = pattern.charAt(i); + if (p == '*') { + sb.append("(").append(pattern.substring(index, i)).append(")"); + if (i + 1 < plen && pattern.charAt(i + 1) == '*') { + sb.append(".*"); + index = i + 2; + } else { + sb.append("[^\\.]*"); + index = i + 1; + } + } + i++; + } + if (index < plen) { + sb.append("(").append(pattern.substring(index, plen)).append(")"); + } + return sb.toString(); + } + + static class Filter { + + final ModuleConfig config; + final Set exclude = new TreeSet(); + final Set allow = new TreeSet(); + + Filter(ModuleConfig config) { + this.config = config; + } + + Filter exclude(String pattern) { + exclude.add(pattern); + return this; + } + + Filter allow(String pattern) { + allow.add(pattern); + return this; + } + + String allowedBy(String name) { + String allowedBy = null; + for (String pattern : allow) { + if (config.matches(name, pattern)) { + if (name.equals(pattern)) { + return pattern; // exact match + } + if (allowedBy == null) { + allowedBy = pattern; + } else { + if (pattern.length() > allowedBy.length()) { + allowedBy = pattern; + } + } + } + } + return allowedBy; + } + + String excludedBy(String name) { + String allowedBy = allowedBy(name); + String excludedBy = null; + + if (allowedBy != null && name.equals(allowedBy)) { + return null; // exact match + } + for (String pattern : exclude) { + if (config.matches(name, pattern)) { + // not matched by allowed rule or exact match + if (allowedBy == null || name.equals(pattern)) { + return pattern; + } + if (excludedBy == null) { + excludedBy = pattern; + } else { + if (pattern.length() > excludedBy.length()) { + excludedBy = pattern; + } + } + } + } + return excludedBy; + } + + boolean isExcluded(String name) { + String allowedBy = allowedBy(name); + String excludedBy = excludedBy(name); + + if (excludedBy == null) { + return false; + } + // not matched by allowed rule or exact match + if (allowedBy == null || name.equals(excludedBy)) { + return true; + } + + if (allowedBy == null) { + return true; + } + if (allowedBy != null && + excludedBy.length() > allowedBy.length()) { + return true; + } + return false; + } + } + + private static String trimComment(String line) { + StringBuilder sb = new StringBuilder(); + + int pos = 0; + while (pos >= 0 && pos < line.length()) { + int c1 = line.indexOf("//", pos); + if (c1 > 0 && !Character.isWhitespace(line.charAt(c1-1))) { + // not a comment + c1 = -1; + } + + int c2 = line.indexOf("/*", pos); + if (c2 > 0 && !Character.isWhitespace(line.charAt(c2-1))) { + // not a comment + c2 = -1; + } + + int c = line.length(); + int n = line.length(); + if (c1 >= 0 || c2 >= 0) { + if (c1 >= 0) { + c = c1; + } + if (c2 >= 0 && c2 < c) { + c = c2; + } + int c3 = line.indexOf("*/", c2 + 2); + if (c == c2 && c3 > c2) { + n = c3 + 2; + } + } + if (c > 0) { + if (sb.length() > 0) { + // add a whitespace if multiple comments on one line + sb.append(" "); + } + sb.append(line.substring(pos, c)); + } + pos = n; + } + return sb.toString(); + } + + private static boolean beginBlockComment(String line) { + int pos = 0; + while (pos >= 0 && pos < line.length()) { + int c = line.indexOf("/*", pos); + if (c < 0) { + return false; + } + + if (c > 0 && !Character.isWhitespace(line.charAt(c-1))) { + return false; + } + + int c1 = line.indexOf("//", pos); + if (c1 >= 0 && c1 < c) { + return false; + } + + int c2 = line.indexOf("*/", c + 2); + if (c2 < 0) { + return true; + } + pos = c + 2; + } + return false; + } + + static void setBaseModule(String name) { + baseModuleName = name; + } + // TODO: we shall remove "-" from the regex once we define + // the naming convention for the module names without dashes + static final Pattern classNamePattern = Pattern.compile("[\\w\\.\\*_$-/]+"); + + static List readConfigurationFile(String file) throws IOException { + List result = new ArrayList(); + // parse configuration file + FileInputStream in = new FileInputStream(file); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String line; + + int lineNumber = 0; + boolean inRoots = false; + boolean inIncludes = false; + boolean inAllows = false; + boolean inExcludes = false; + boolean inBlockComment = false; + ModuleConfig config = null; + + while ((line = reader.readLine()) != null) { + lineNumber++; + + if (inBlockComment) { + int c = line.indexOf("*/"); + if (c >= 0) { + line = line.substring(c + 2, line.length()); + inBlockComment = false; + } else { + // skip lines until end of comment block + continue; + } + } + + inBlockComment = beginBlockComment(line); + + line = trimComment(line).trim(); + // ignore empty lines + if (line.length() == 0) { + continue; + } + + String values; + if (inRoots || inIncludes || inExcludes || inAllows) { + values = line; + } else { + String[] s = line.split("\\s+"); + String keyword = s[0].trim(); + if (keyword.equals("module")) { + if (s.length != 3 || !s[2].trim().equals("{")) { + throw new RuntimeException(file + ", line " + + lineNumber + ", is malformed"); + } + config = new ModuleConfig(s[1].trim()); + result.add(config); + // switch to a new module; so reset the flags + inRoots = false; + inIncludes = false; + inExcludes = false; + inAllows = false; + continue; + } else if (keyword.equals("roots")) { + inRoots = true; + } else if (keyword.equals("include")) { + inIncludes = true; + } else if (keyword.equals("exclude")) { + inExcludes = true; + } else if (keyword.equals("allow")) { + inAllows = true; + } else if (keyword.equals("}")) { + if (config == null || s.length != 1) { + throw new RuntimeException(file + ", line " + + lineNumber + ", is malformed"); + } else { + // end of a module + config = null; + continue; + } + } else { + throw new RuntimeException(file + ", \"" + keyword + "\" on line " + + lineNumber + ", is not recognized"); + } + values = line.substring(keyword.length(), line.length()).trim(); + } + + if (config == null) { + throw new RuntimeException(file + ", module not specified"); + } + + int len = values.length(); + if (len == 0) { + continue; + } + char lastchar = values.charAt(len - 1); + if (lastchar != ',' && lastchar != ';') { + throw new RuntimeException(file + ", line " + + lineNumber + ", is malformed:" + + " ',' or ';' is missing."); + } + + values = values.substring(0, len - 1); + // parse the values specified for a keyword specified + for (String s : values.split(",")) { + s = s.trim(); + if (s.length() > 0) { + if (!classNamePattern.matcher(s).matches()) { + throw new RuntimeException(file + ", line " + + lineNumber + ", is malformed: \"" + s + "\""); + } + if (inRoots) { + config.roots.add(s); + } else if (inIncludes) { + config.includes.add(s); + } else if (inExcludes) { + config.filter.exclude(s); + } else if (inAllows) { + config.filter.allow(s); + } + + } + } + if (lastchar == ';') { + inRoots = false; + inIncludes = false; + inExcludes = false; + inAllows = false; + } + } + + if (inBlockComment) { + throw new RuntimeException(file + ", line " + + lineNumber + ", missing \"*/\" to end a block comment"); + } + if (config != null) { + throw new RuntimeException(file + ", line " + + lineNumber + ", missing \"}\" to end module definition" + + " for \"" + config.module + "\""); + } + + } finally { + in.close(); + } + + return result; + } + + private String format(String keyword, Collection values) { + if (values.size() == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + String format = "%4s%-9s"; + String spaces = String.format(format, "", ""); + sb.append(String.format(format, "", keyword)); + int count = 0; + for (String s : values) { + if (count > 0) { + sb.append(",\n").append(spaces); + } else if (count++ > 0) { + sb.append(", "); + } + sb.append(s); + } + if (count > 0) { + sb.append(";\n"); + } + return sb.toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("module " + module).append(" {\n"); + sb.append(format("include", includes)); + sb.append(format("root", roots)); + sb.append(format("allow", filter.allow)); + sb.append(format("exclude", filter.exclude)); + sb.append("}\n"); + return sb.toString(); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ResolutionInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ResolutionInfo.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,201 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package com.sun.classanalyzer; + +import com.sun.classanalyzer.Klass.Method; + +/** + * + * @author mchung + */ +public class ResolutionInfo implements Comparable { + + enum Type { + + REFLECTION("reflection", true), + NATIVE("native", true), + INTERFACE("interface", false), + SUPER("super", false), + EXPLICIT("explicit", false), + VERIFICATION("verification", false), + METHODTRACE("method trace", true), + CONSTANT_POOL("constant pool", true), + CHECKED_EXCEPTION("throws", true), + METHOD("method", true), + FIELD("field", true), + EXTENDS("extends", true), + IMPLEMENTS("implements", true), + NOINFO("No info", false); + + private final String name; + private final boolean hasInfo; + + private Type(String name, boolean hasInfo) { + this.name = name; + this.hasInfo = hasInfo; + } + + public String getName() { + return name; + } + + public boolean hasInfo() { + return hasInfo; + } + + public static Type getType(String s) { + if (s.isEmpty()) { + return NOINFO; + } + for (Type t : values()) { + if (s.equals(t.name)) { + return t; + } + } + // Need to fix the VM output to add "native" + // throw new IllegalArgumentException("Invalid ResolutionInfo.type \"" + s + "\""); + System.out.println("WARNING: Invalid ResolutionInfo.type \"" + s + "\""); + return null; + } + } + final Klass fromClass; + final Method method; + final Klass toClass; + final int linenumber; + final Type type; + final String info; + private boolean isPublic = false; + + private ResolutionInfo(Klass from, Klass to, int linenumber, Type type, String info) { + this.fromClass = from; + this.method = null; + this.toClass = to; + this.linenumber = linenumber; + this.type = type; + this.info = info; + } + + private ResolutionInfo(Klass from, Method m, Klass to, int linenumber, Type type) { + this.fromClass = from; + this.method = m; + this.toClass = to; + this.linenumber = linenumber; + this.type = type; + this.info = m.toString(); + } + + public boolean isPublic() { + return isPublic; + } + + public void setPublicAccess(boolean value) { + isPublic = value; + } + static ResolutionInfo resolved(Klass from, Klass to) { + return new ResolutionInfo(from, to, 0, Type.NOINFO, ""); + } + + static ResolutionInfo resolved(Klass from, Klass to, int linenumber) { + return new ResolutionInfo(from, to, linenumber, Type.NOINFO, ""); + } + + static ResolutionInfo resolved(Klass from, Klass to, int linenumber, String reason) { + String[] ss = reason.split("\\s+"); + Type type; + String info; + if (linenumber == -1) { + type = Type.NATIVE; + info = ss[0]; // native method name + } else { + info = ss.length == 2 ? ss[1] : ""; + type = Type.getType(ss[0]); + if (type == null) { + if (reason.isEmpty()) { + throw new IllegalArgumentException("Invalid type: " + reason + " (" + ss[0] + ")" + ss.length); + } + // assume it's native + type = Type.NATIVE; + info = reason.isEmpty() ? ss[0] : reason; + } + } + + return new ResolutionInfo(from, to, linenumber, type, info); + } + + static ResolutionInfo resolved(Klass from, Klass to, Method callee) { + return new ResolutionInfo(from, callee, to, 0, Type.METHODTRACE); + } + + static ResolutionInfo resolvedConstantPool(Klass from, Klass to, int index) { + return new ResolutionInfo(from, to, 0, Type.CONSTANT_POOL, "#" + index); + } + + static ResolutionInfo resolvedField(Klass from, Klass to, String fieldname) { + return new ResolutionInfo(from, to, 0, Type.FIELD, fieldname); + } + + static ResolutionInfo resolvedMethodSignature(Klass from, Klass to, Method m) { + return new ResolutionInfo(from, m, to, 0, Type.METHOD); + } + + static ResolutionInfo resolvedCheckedException(Klass from, Klass to, Method m) { + return new ResolutionInfo(from, m, to, 0, Type.CHECKED_EXCEPTION); + } + + static ResolutionInfo resolvedExtends(Klass from, Klass to) { + String info = from.getClassName() + " implements " + to.getClassName(); + return new ResolutionInfo(from, to, 0, Type.EXTENDS, info); + } + + static ResolutionInfo resolvedImplements(Klass from, Klass to) { + String info = from.getClassName() + " implements " + to.getClassName(); + return new ResolutionInfo(from, to, 0, Type.IMPLEMENTS, info); + } + + @Override + public int compareTo(ResolutionInfo ri) { + if (this.fromClass == ri.fromClass && + this.toClass == ri.toClass && + this.linenumber == ri.linenumber && + this.type == ri.type && + this.info.equals(ri.info)) { + return 0; + } else if (this.fromClass == ri.fromClass) { + if (this.linenumber > ri.linenumber) { + return 1; + } else if (this.linenumber < ri.linenumber) { + return -1; + } else if (this.type != ri.type) { + return this.type.getName().compareTo(ri.type.getName()); + } else if (this.toClass != ri.toClass) { + return this.toClass.compareTo(ri.toClass); + } else { + return this.info.compareTo(ri.info); + } + } else { + return this.fromClass.compareTo(ri.fromClass); + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ResourceFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ResourceFile.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,186 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ +package com.sun.classanalyzer; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +/** + * + * @author Mandy Chung + */ +public class ResourceFile implements Comparable { + + private final String pathname; + private Module module; + + ResourceFile(String pathname) { + this.pathname = pathname.replace(File.separatorChar, '/'); + } + + Module getModule() { + return module; + } + + void setModule(Module m) { + if (module != null) { + throw new RuntimeException("Module for " + this + " already set"); + } + this.module = m; + } + + String getName() { + return pathname; + } + + String getPathname() { + return pathname; + } + + @Override + public String toString() { + return pathname; + } + + @Override + public int compareTo(ResourceFile o) { + return pathname.compareTo(o.pathname); + } + static Set resources = new TreeSet(); + + static boolean isResource(String pathname) { + String name = pathname.replace(File.separatorChar, '/'); + + if (name.endsWith("META-INF/MANIFEST.MF")) { + return false; + } + if (name.contains("META-INF/JCE_RSA.")) { + return false; + } + + return true; + } + + static void addResource(String name, InputStream in) { + ResourceFile res; + name = name.replace(File.separatorChar, '/'); + if (name.startsWith("META-INF/services")) { + res = new ServiceProviderConfigFile(name, in); + } else { + res = new ResourceFile(name); + } + resources.add(res); + } + + static Set getAllResources() { + return Collections.unmodifiableSet(resources); + } + + static class ServiceProviderConfigFile extends ResourceFile { + + private final List providers = new ArrayList(); + private final String service; + ServiceProviderConfigFile(String pathname, InputStream in) { + super(pathname); + readServiceConfiguration(in, providers); + this.service = pathname.substring("META-INF/services".length() + 1, pathname.length()); + } + + @Override + String getName() { + if (providers.isEmpty()) { + return service; + } else { + // just use the first one for matching + return providers.get(0); + } + } + + @SuppressWarnings("empty-statement") + void readServiceConfiguration(InputStream in, List names) { + BufferedReader br = null; + try { + if (in != null) { + // Properties doesn't perserve the order of the input file + br = new BufferedReader(new InputStreamReader(in, "utf-8")); + int lc = 1; + while ((lc = parseLine(br, lc, names)) >= 0); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + } + } + + // Parse a single line from the given configuration file, adding the name + // on the line to the names list. + // + private int parseLine(BufferedReader r, int lc, List names) throws IOException { + String ln = r.readLine(); + if (ln == null) { + return -1; + } + int ci = ln.indexOf('#'); + if (ci >= 0) { + ln = ln.substring(0, ci); + } + ln = ln.trim(); + int n = ln.length(); + if (n != 0) { + if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) { + throw new RuntimeException("Illegal configuration-file syntax"); + } + int cp = ln.codePointAt(0); + if (!Character.isJavaIdentifierStart(cp)) { + throw new RuntimeException("Illegal provider-class name: " + ln); + } + for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) { + cp = ln.codePointAt(i); + if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) { + throw new RuntimeException("Illegal provider-class name: " + ln); + } + } + if (!names.contains(ln)) { + names.add(ln); + } + } + return lc + 1; + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/make/modules/tools/src/com/sun/classanalyzer/ShowDeps.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/modules/tools/src/com/sun/classanalyzer/ShowDeps.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,100 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.classanalyzer; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +/** + * A simple tool to print out the static dependencies for a given set of JAR, + * class files, or combinations of. The tools supports an -ignore option to + * ignore references to classes listed in the file (including .classlists + * created by the ClassAnalyzer tool). + */ + +public class ShowDeps { + + static void usage() { + System.out.println("java ShowDeps [-ignore ] file..."); + System.out.println(" where is a class or JAR file, or a directory"); + System.out.println(); + System.out.println("Example usages:"); + System.out.println(" java ShowDeps Foo.jar"); + System.out.println(" java ShowDeps -ignore base.classlist Foo.jar"); + System.out.println(" java ShowDeps -ignore base.classlist -ignore " + + "jaxp-parsers.classlist

"); + System.exit(-1); + } + + public static void main(String[] args) throws IOException { + // process -ignore options + int argi = 0; + Set ignore = new HashSet(); + while (argi < args.length && args[argi].equals("-ignore")) { + argi++; + Scanner s = new Scanner(new File(args[argi++])); + try { + while (s.hasNextLine()) { + String line = s.nextLine(); + if (!line.endsWith(".class")) + continue; + int len = line.length(); + // convert to class names + String clazz = line.replace('\\', '.').replace('/', '.') + .substring(0, len-6); + ignore.add(clazz); + } + } finally { + s.close(); + } + } + + if (argi >= args.length) + usage(); + + // parse all classes + while (argi < args.length) + ClassPath.setClassPath(args[argi++]); + ClassPath.parseAllClassFiles(); + + // find the classes that don't exist + Set unresolved = new TreeSet(); + for (Klass k : Klass.getAllClasses()) { + if (k.getFileSize() == 0) + unresolved.add(k); + } + + // print references to classes that don't exist + for (Klass k: Klass.getAllClasses()) { + for (Klass other : k.getReferencedClasses()) { + if (unresolved.contains(other)) { + String name = other.toString(); + if (!ignore.contains(name)) { + System.out.format("%s -> %s\n", k, other); + } + } + } + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/bin/java.c --- a/jdk/src/share/bin/java.c Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/bin/java.c Wed Jul 05 17:05:01 2017 +0200 @@ -93,6 +93,7 @@ * Prototypes for functions internal to launcher. */ static void SetClassPath(const char *s); +static void SetModulesBootClassPath(const char *s); static void SelectVersion(int argc, char **argv, char **main_class); static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, char **pclassname, int *pret, const char *jvmpath); @@ -277,6 +278,9 @@ return(ret); } + /* Set bootclasspath for modules */ + SetModulesBootClassPath(jrepath); + /* Override class path if -jar flag was specified */ if (jarfile != 0) { SetClassPath(jarfile); @@ -694,6 +698,44 @@ } /* + * Set the bootclasspath for modules. + * A temporary workaround until jigsaw is integrated into JDK 7. + */ +static void +SetModulesBootClassPath(const char *jrepath) +{ + char *def, *s; + char pathname[MAXPATHLEN]; + const char separator[] = { FILE_SEPARATOR, '\0' }; + const char *orig = jrepath; + static const char format[] = "-Xbootclasspath/p:%s"; + struct stat statbuf; + + /* return if jre/lib/rt.jar exists */ + sprintf(pathname, "%s%slib%srt.jar", jrepath, separator, separator); + if (stat(pathname, &statbuf) == 0) { + return; + } + + /* return if jre/classes exists */ + sprintf(pathname, "%s%sclasses", jrepath, separator); + if (stat(pathname, &statbuf) == 0) { + return; + } + + /* modularized jre */ + sprintf(pathname, "%s%slib%s*", jrepath, separator, separator); + s = (char *) JLI_WildcardExpandClasspath(pathname); + def = JLI_MemAlloc(sizeof(format) + - 2 /* strlen("%s") */ + + JLI_StrLen(s)); + sprintf(def, format, s); + AddOption(def, NULL); + if (s != orig) + JLI_MemFree((char *) s); +} + +/* * The SelectVersion() routine ensures that an appropriate version of * the JRE is running. The specification for the appropriate version * is obtained from either the manifest of a jar file (preferred) or diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java --- a/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java Wed Jul 05 17:05:01 2017 +0200 @@ -33,10 +33,10 @@ import java.util.Hashtable; import java.util.Properties; import java.util.Enumeration; -import java.applet.Applet; import org.omg.CORBA.ORB; +import javax.naming.Context; import javax.naming.ConfigurationException; /** @@ -191,16 +191,48 @@ } // Get Applet from environment - Applet applet = null; if (env != null) { - applet = (Applet) env.get("java.naming.applet"); + Object applet = env.get(Context.APPLET); + if (applet != null) { + // Create ORBs for an applet + return initAppletORB(applet, orbProp); + } } - // Create ORBs using applet and orbProp - if (applet != null) { - return ORB.init(applet, orbProp); - } else { - return ORB.init(new String[0], orbProp); + // Create ORBs using orbProp for a standalone application + return ORB.init(new String[0], orbProp); + } + + /** + * This method returns a new ORB instance for the given applet + * without creating a static dependency on java.applet. + */ + private static ORB initAppletORB(Object applet, Properties orbProp) { + try { + Class appletClass = Class.forName("java.applet.Applet", true, null); + if (!appletClass.isInstance(applet)) { + throw new ClassCastException(applet.getClass().getName()); + } + + // invoke the static method ORB.init(applet, orbProp); + Method method = ORB.class.getMethod("init", appletClass, Properties.class); + return (ORB) method.invoke(null, applet, orbProp); + } catch (ClassNotFoundException e) { + // java.applet.Applet doesn't exist and the applet parameter is + // non-null; so throw CCE + throw new ClassCastException(applet.getClass().getName()); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } + throw new AssertionError(e); + } catch (IllegalAccessException iae) { + throw new AssertionError(iae); } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/CallSite.java --- a/jdk/src/share/classes/java/dyn/CallSite.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/CallSite.java Wed Jul 05 17:05:01 2017 +0200 @@ -26,6 +26,9 @@ package java.dyn; import sun.dyn.util.BytecodeName; +import sun.dyn.Access; +import sun.dyn.CallSiteImpl; +import sun.dyn.MethodHandleImpl; /** * An {@code invokedynamic} call site, as reified by the @@ -52,15 +55,25 @@ * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle) * @author John Rose, JSR 292 EG */ -public class CallSite { +public class CallSite + // Note: This is an implementation inheritance hack, and will be removed + // with a JVM change which moves the required hidden state onto this class. + extends CallSiteImpl +{ + private static final Access IMPL_TOKEN = Access.getToken(); + + /* + // Fields used only by the JVM. Do not use or change. private Object vmmethod; int callerMID, callerBCI; // supplied by the JVM - MethodHandle target; + private MethodHandle target; + final Object caller; // usually a class final String name; final MethodType type; + */ /** * Make a call site given the parameters from a call to the bootstrap method. @@ -72,16 +85,21 @@ * @param type the method handle type derived from descriptor of the {@code invokedynamic} instruction */ public CallSite(Object caller, String name, MethodType type) { - this.caller = caller; - this.name = name; - this.type = type; + super(IMPL_TOKEN, caller, name, type); } private static void privateInitializeCallSite(CallSite site, int callerMID, int callerBCI) { site.callerMID = callerMID; site.callerBCI = callerBCI; - if (site.target == null) - site.setTarget(site.initialTarget()); + site.ensureTarget(); + } + private void ensureTarget() { + // Note use of super, which accesses the field directly, + // without deferring to possible subclass overrides. + if (super.getTarget() == null) { + super.setTarget(this.initialTarget()); + super.getTarget().type(); // provoke NPE if still null + } } /** @@ -102,10 +120,11 @@ /** * Report the current linkage state of the call site. (This is mutable.) - * The value maybe null only if the call site is currently unlinked. - * When a linked call site is invoked, the target method is used directly. - * When an unlinked call site is invoked, its bootstrap method receives - * the call, as if via {@link Linkage#bootstrapInvokeDynamic}. + * The value may not be null after the {@code CallSite} object is returned + * from the bootstrap method of the {@code invokedynamic} instruction. + * When an {@code invokedynamic} instruction is executed, the target method + * of its associated {@code call site} object is invoked directly, + * as if via {@link MethodHandle}{@code .invoke}. *

* The interactions of {@code getTarget} with memory are the same * as of a read from an ordinary variable, such as an array element or a @@ -118,7 +137,7 @@ * @see #setTarget */ public MethodHandle getTarget() { - return target; + return super.getTarget(); } /** @@ -140,13 +159,13 @@ */ public void setTarget(MethodHandle target) { checkTarget(target); - this.target = target; + super.setTarget(target); } protected void checkTarget(MethodHandle target) { target.type(); // provoke NPE if (!canSetTarget(target)) - throw new WrongMethodTypeException(String.valueOf(target)); + throw new WrongMethodTypeException(String.valueOf(target)+target.type()+" should be of type "+type()); } protected boolean canSetTarget(MethodHandle target) { @@ -219,6 +238,10 @@ @Override public String toString() { - return "CallSite#"+hashCode()+"["+name+type+" => "+target+"]"; + return "CallSite#"+hashCode()+"["+name+type+" => "+getTarget()+"]"; } + + // Package-local constant: + static final MethodHandle GET_TARGET = MethodHandleImpl.getLookup(IMPL_TOKEN). + findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/InvokeDynamic.java --- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/InvokeDynamic.java Wed Jul 05 17:05:01 2017 +0200 @@ -45,6 +45,24 @@ * class or interface supertype, or an object type; it can never be instantiated. * Logically, it denotes a source of all dynamically typed methods. * It may be viewed as a pure syntactic marker (an importable one) of static calls. + *

+ * Here are some examples of usage: + *

+ * Object x; String s; int i;
+ * x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
+ * s = InvokeDynamic.<String>hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
+ * InvokeDynamic.<void>cogito(); // cogito()V
+ * i = InvokeDynamic.<int>#"op:+"(2, 3); // "op:+"(II)I
+ * 
+ * Each of the above calls generates a single invokedynamic instruction + * with the name-and-type descriptors indicated in the comments. + * The argument types are taken directly from the actual arguments, + * while the return type is taken from the type parameter. + * (This type parameter may be a primtive, and it defaults to {@code Object}.) + * The final example uses a special syntax for uttering non-Java names. + * Any name legal to the JVM may be given between the double quotes. + * None of these calls is complete without a bootstrap method, + * which must be registered by the static initializer of the enclosing class. * @author John Rose, JSR 292 EG */ public final class InvokeDynamic { diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java --- a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java Wed Jul 05 17:05:01 2017 +0200 @@ -52,4 +52,16 @@ public InvokeDynamicBootstrapError(String s) { super(s); } + + /** + * Constructs a {@code InvokeDynamicBootstrapError} with the specified + * detail message and cause. + * + * @param s the detail message. + * @param cause the cause. + */ + public InvokeDynamicBootstrapError(String s, Throwable cause) { + super(s); + this.initCause(cause); + } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/JavaMethodHandle.java --- a/jdk/src/share/classes/java/dyn/JavaMethodHandle.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/JavaMethodHandle.java Wed Jul 05 17:05:01 2017 +0200 @@ -25,6 +25,8 @@ package java.dyn; +import sun.dyn.Access; + /** * A Java method handle extends the basic method handle type with additional * programmer defined methods and fields. @@ -39,31 +41,105 @@ * of the entry point method handle, with the leading parameter type * omitted. *

- * Here is an example of usage: + * Here is an example of usage, creating a hybrid object/functional datum: *

- *     class Greeter extends JavaMethodHandle {
+ * class Greeter extends JavaMethodHandle {
+ *     private String greeting = "hello";
+ *     public void setGreeting(String s) { greeting = s; }
+ *     public void run() { System.out.println(greeting+", "+greetee); }
+ *     private final String greetee;
+ *     Greeter(String greetee) {
+ *         super(RUN); // alternatively, super("run")
+ *         this.greetee = greetee;
+ *     }
+ *     // the entry point function is computed once:
+ *     private static final MethodHandle RUN
+ *         = MethodHandles.lookup().findVirtual(Greeter.class, "run",
+ *               MethodType.make(void.class));
+ * }
+ * // class Main { public static void main(String... av) { ...
+ * Greeter greeter = new Greeter("world");
+ * greeter.run();  // prints "hello, world"
+ * // Statically typed method handle invocation (most direct):
+ * MethodHandle mh = greeter;
+ * mh.<void>invoke();  // also prints "hello, world"
+ * // Dynamically typed method handle invocation:
+ * MethodHandles.invoke(greeter);  // also prints "hello, world"
+ * greeter.setGreeting("howdy");
+ * mh.invoke();  // prints "howdy, world" (object-like mutable behavior)
+ * 
+ *

+ * In the example of {@code Greeter}, the method {@code run} provides the entry point. + * The entry point need not be a constant value; it may be independently + * computed in each call to the constructor. The entry point does not + * even need to be a method on the {@code Greeter} class, though + * that is the typical case. + *

+ * The entry point may also be provided symbolically, in which case the the + * {@code JavaMethodHandle} constructor performs the lookup of the entry point. + * This makes it possible to use {@code JavaMethodHandle} to create an anonymous + * inner class: + *

+ * // We can also do this with symbolic names and/or inner classes:
+ * MethodHandles.invoke(new JavaMethodHandle("yow") {
+ *     void yow() { System.out.println("yow, world"); }
+ * });
+ * 
+ *

+ * Here is similar lower-level code which works in terms of a bound method handle. + *

+ *     class Greeter {
  *         public void run() { System.out.println("hello, "+greetee); }
  *         private final String greetee;
- *         Greeter(String greetee) {
- *             super(RUN);
- *             this.greetee = greetee;
- *         }
+ *         Greeter(String greetee) { this.greetee = greetee; }
  *         // the entry point function is computed once:
  *         private static final MethodHandle RUN
- *             = MethodHandles.findVirtual(MyMethodHandle.class, "run",
+ *             = MethodHandles.findVirtual(Greeter.class, "run",
  *                   MethodType.make(void.class));
  *     }
+ *     // class Main { public static void main(String... av) { ...
  *     Greeter greeter = new Greeter("world");
  *     greeter.run();  // prints "hello, world"
- *     MethodHandle mh = greeter;
+ *     MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
  *     mh.invoke();  // also prints "hello, world"
  * 
+ * Note that the method handle must be separately created as a view on the base object. + * This increases footprint, complexity, and dynamic indirections. + *

+ * Here is a pure functional value expressed most concisely as an anonymous inner class: + *

+ *     // class Main { public static void main(String... av) { ...
+ *     final String greetee = "world";
+ *     MethodHandle greeter = new JavaMethodHandle("run") {
+ *         private void run() { System.out.println("hello, "+greetee); }
+ *     }
+ *     greeter.invoke();  // prints "hello, world"
+ * 
*

- * In this example, the method {@code run} provides the entry point. - * The entry point need not be a constant value; it may be independently - * computed in each call to the constructor. The entry point does not - * even need to be a method on the Java method handle class, though - * that is the typical case. + * Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle, + * and instantiated as an anonymous class. The data structure is a handle to 1-D array, + * with a specialized index type (long). It is created by inner class, and uses + * signature-polymorphic APIs throughout. + *

+ *     abstract class AssignableMethodHandle extends JavaMethodHandle {
+ *       private final MethodHandle setter;
+ *       public MethodHandle setter() { return setter; }
+ *       public AssignableMethodHandle(String get, String set) {
+ *         super(get);
+ *         MethodType getType = this.type();
+ *         MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
+ *         this.setter = MethodHandles.publicLookup().bind(this, set, setType);
+ *       }
+ *     }
+ *     // class Main { public static void main(String... av) { ...
+ *     final Number[] stuff = { 123, 456 };
+ *     AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
+ *         public Number get(long i)           { return stuff[(int)i]; }
+ *         public void   set(long i, Object x) {        stuff[(int)i] = x; }
+ *     }
+ *     int x = (Integer) stuffPtr.<Number>invoke(1L);  // 456
+ *     stuffPtr.setter().<void>invoke(0L, (Number) 789);  // replaces 123 with 789
+ * 
* @see MethodHandle * @author John Rose, JSR 292 EG */ @@ -72,12 +148,87 @@ // with a JVM change which moves the required hidden behavior onto this class. extends sun.dyn.BoundMethodHandle { + private static final Access IMPL_TOKEN = Access.getToken(); + /** - * When creating a, pass in {@code entryPoint}, any method handle which - * can take the current object - * @param entryPoint + * When creating a {@code JavaMethodHandle}, the actual method handle + * invocation behavior will be delegated to the specified {@code entryPoint}. + * This may be any method handle which can take the newly constructed object + * as a leading parameter. + *

+ * The method handle type of {@code this} (i.e, the fully constructed object) + * will be {@code entryPoint}, minus the leading argument. + * The leading argument will be bound to {@code this} on every method + * handle invocation. + * @param entryPoint the method handle to handle calls */ protected JavaMethodHandle(MethodHandle entryPoint) { - super(entryPoint, 0); + super(entryPoint); + } + + /** + * Create a method handle whose entry point is a non-static method + * visible in the exact (most specific) class of + * the newly constructed object. + *

+ * The method is specified by name and type, as if via this expression: + * {@code MethodHandles.lookup().findVirtual(this.getClass(), name, type)}. + * The class defining the method might be an anonymous inner class. + *

+ * The method handle type of {@code this} (i.e, the fully constructed object) + * will be the given method handle type. + * A call to {@code this} will invoke the selected method. + * The receiver argument will be bound to {@code this} on every method + * handle invocation. + *

+ * Rationale: + * Although this constructor may seem to be a mere luxury, + * it is not subsumed by the more general constructor which + * takes any {@code MethodHandle} as the entry point argument. + * In order to convert an entry point name to a method handle, + * the self-class of the object is required (in order to do + * the lookup). The self-class, in turn, is generally not + * available at the time of the constructor invocation, + * due to the rules of Java and the JVM verifier. + * One cannot call {@code this.getClass()}, because + * the value of {@code this} is inaccessible at the point + * of the constructor call. (Changing this would require + * change to the Java language, verifiers, and compilers.) + * In particular, this constructor allows {@code JavaMethodHandle}s + * to be created in combination with the anonymous inner class syntax. + * @param entryPointName the name of the entry point method + * @param type (optional) the desired type of the method handle + */ + protected JavaMethodHandle(String entryPointName, MethodType type) { + super(entryPointName, type, true); + + } + + /** + * Create a method handle whose entry point is a non-static method + * visible in the exact (most specific) class of + * the newly constructed object. + *

+ * The method is specified only by name. + * There must be exactly one method of that name visible in the object class, + * either inherited or locally declared. + * (That is, the method must not be overloaded.) + *

+ * The method handle type of {@code this} (i.e, the fully constructed object) + * will be the same as the type of the selected non-static method. + * The receiver argument will be bound to {@code this} on every method + * handle invocation. + *

ISSUE: This signature wildcarding feature does not correspond to + * any MethodHandles.Lookup API element. Can we eliminate it? + * Alternatively, it is useful for naming non-overloaded methods. + * Shall we make type arguments optional in the Lookup methods, + * throwing an error in cases of ambiguity? + *

+ * For this method's rationale, see the documentation + * for {@link #JavaMethodHandle(String,MethodType)}. + * @param entryPointName the name of the entry point method + */ + protected JavaMethodHandle(String entryPointName) { + super(entryPointName, (MethodType) null, false); } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/Linkage.java --- a/jdk/src/share/classes/java/dyn/Linkage.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/Linkage.java Wed Jul 05 17:05:01 2017 +0200 @@ -25,7 +25,9 @@ package java.dyn; +import java.dyn.MethodHandles.Lookup; import java.util.WeakHashMap; +import sun.dyn.Access; import sun.reflect.Reflection; import static sun.dyn.util.VerifyAccess.checkBootstrapPrivilege; @@ -34,6 +36,8 @@ * @author John Rose, JSR 292 EG */ public class Linkage { + private static final Access IMPL_TOKEN = Access.getToken(); + private Linkage() {} // do not instantiate /** @@ -53,19 +57,23 @@ * call to this method. *

  • The given class is already fully initialized. *
  • The given class is in the process of initialization, in another thread. + *
  • The same {@code CallSite} object has already been returned from + * a bootstrap method call to another {@code invokedynamic} call site. * * Because of these rules, a class may install its own bootstrap method in * a static initializer. + * @param callerClass a class that may have {@code invokedynamic} sites + * @param bootstrapMethod the method to use to bootstrap all such sites */ public static - void registerBootstrapMethod(Class callerClass, MethodHandle mh) { + void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) { Class callc = Reflection.getCallerClass(2); checkBootstrapPrivilege(callc, callerClass, "registerBootstrapMethod"); - checkBSM(mh); + checkBSM(bootstrapMethod); synchronized (bootstrapMethods) { if (bootstrapMethods.containsKey(callerClass)) throw new IllegalStateException("bootstrap method already declared in "+callerClass); - bootstrapMethods.put(callerClass, mh); + bootstrapMethods.put(callerClass, bootstrapMethod); } } @@ -88,8 +96,9 @@ public static void registerBootstrapMethod(Class runtime, String name) { Class callc = Reflection.getCallerClass(2); + Lookup lookup = new Lookup(IMPL_TOKEN, callc); MethodHandle bootstrapMethod = - MethodHandles.findStaticFrom(callc, runtime, name, BOOTSTRAP_METHOD_TYPE); + lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE); // FIXME: exception processing wrong here checkBSM(bootstrapMethod); Linkage.registerBootstrapMethod(callc, bootstrapMethod); @@ -106,8 +115,9 @@ public static void registerBootstrapMethod(String name) { Class callc = Reflection.getCallerClass(2); + Lookup lookup = new Lookup(IMPL_TOKEN, callc); MethodHandle bootstrapMethod = - MethodHandles.findStaticFrom(callc, callc, name, BOOTSTRAP_METHOD_TYPE); + lookup.findStatic(callc, name, BOOTSTRAP_METHOD_TYPE); // FIXME: exception processing wrong here checkBSM(bootstrapMethod); Linkage.registerBootstrapMethod(callc, bootstrapMethod); @@ -116,8 +126,7 @@ /** * PROVISIONAL API, WORK IN PROGRESS: * Report the bootstrap method registered for a given class. - * Returns null if the class has never yet registered a bootstrap method, - * or if the class has explicitly registered a null bootstrap method. + * Returns null if the class has never yet registered a bootstrap method. * Only callers privileged to set the bootstrap method may inquire * about it, because a bootstrap method is potentially a back-door entry * point into its class. @@ -137,12 +146,12 @@ * {@code (Class, String, MethodType)} returning a {@code CallSite}. */ public static final MethodType BOOTSTRAP_METHOD_TYPE - = MethodType.make(CallSite.class, - Class.class, String.class, MethodType.class); + = MethodType.methodType(CallSite.class, + Class.class, String.class, MethodType.class); private static final MethodType OLD_BOOTSTRAP_METHOD_TYPE - = MethodType.make(Object.class, - CallSite.class, Object[].class); + = MethodType.methodType(Object.class, + CallSite.class, Object[].class); private static final WeakHashMap bootstrapMethods = new WeakHashMap(); @@ -173,8 +182,8 @@ /** * PROVISIONAL API, WORK IN PROGRESS: - * Invalidate all invokedynamic call sites associated - * with the given class. + * Invalidate all invokedynamic call sites in the bytecodes + * of any methods of the given class. * (These are exactly those sites which report the given class * via the {@link CallSite#callerClass()} method.) *

    diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/LinkagePermission.java --- a/jdk/src/share/classes/java/dyn/LinkagePermission.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/LinkagePermission.java Wed Jul 05 17:05:01 2017 +0200 @@ -88,7 +88,7 @@ /** * Create a new LinkagePermission with the given name. * The name is the symbolic name of the LinkagePermission, such as - * "registerBootstrapMethod", "invalidateClass.*", etc. An asterisk + * "registerBootstrapMethod", "invalidateCallerClass.*", etc. An asterisk * may appear at the end of the name, following a ".", or by itself, to * signify a wildcard match. * diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/MethodHandle.java --- a/jdk/src/share/classes/java/dyn/MethodHandle.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/MethodHandle.java Wed Jul 05 17:05:01 2017 +0200 @@ -30,6 +30,9 @@ import sun.dyn.Access; import sun.dyn.MethodHandleImpl; +import static java.dyn.MethodHandles.invokers; // package-private API +import static sun.dyn.MemberName.newIllegalArgumentException; // utility + /** * A method handle is a typed reference to the entry point of a method. *

    @@ -45,8 +48,9 @@ * Every method handle appears as an object containing a method named * invoke, whose signature exactly matches * the method handle's type. - * A normal Java method call (using the invokevirtual instruction) - * can invoke this method from Java source code (if language support is present). + * A Java method call expression, which compiles to an + * invokevirtual instruction, + * can invoke this method from Java source code. *

    * Every call to a method handle specifies an intended method type, * which must exactly match the type of the method handle. @@ -57,6 +61,10 @@ * The call fails with a {@link WrongMethodTypeException} * if the method does not exist, even if there is an invoke * method of a closely similar signature. + * As with other kinds + * of methods in the JVM, signature matching during method linkage + * is exact, and does not allow for language-level implicit conversions + * such as {@code String} to {@code Object} or {@code short} to {@code int}. *

    * A method handle is an unrestricted capability to call a method. * A method handle can be formed on a non-public method by a class @@ -74,6 +82,15 @@ * (after resolving symbolic type names) must exactly match the method type * of the target method. *

    + * Every invoke method always throws {@link Exception}, + * which is to say that there is no static restriction on what a method handle + * can throw. Since the JVM does not distinguish between checked + * and unchecked exceptions (other than by their class, of course), + * there is no particular effect on bytecode shape from ascribing + * checked exceptions to method handle invocations. But in Java source + * code, methods which perform method handle calls must either explicitly + * throw {@code Exception}, or else must catch all checked exceptions locally. + *

    * Bytecode in an extended JVM can directly obtain a method handle * for any accessible method from a ldc instruction * which refers to a CONSTANT_Methodref or @@ -97,6 +114,59 @@ * can also be created. These do not perform virtual lookup based on * receiver type. Such a method handle simulates the effect of * an invokespecial instruction to the same method. + *

    + * Here are some examples of usage: + *

    + * Object x, y; String s; int i;
    + * MethodType mt; MethodHandle mh;
    + * MethodHandles.Lookup lookup = MethodHandles.lookup();
    + * // mt is {(char,char) => String}
    + * mt = MethodType.make(String.class, char.class, char.class);
    + * mh = lookup.findVirtual(String.class, "replace", mt);
    + * // (Ljava/lang/String;CC)Ljava/lang/String;
    + * s = mh.<String>invoke("daddy",'d','n');
    + * assert(s.equals("nanny"));
    + * // weakly typed invocation (using MHs.invoke)
    + * s = (String) MethodHandles.invoke(mh, "sappy", 'p', 'v');
    + * assert(s.equals("savvy"));
    + * // mt is {Object[] => List}
    + * mt = MethodType.make(java.util.List.class, Object[].class);
    + * mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
    + * // mt is {(Object,Object,Object) => Object}
    + * mt = MethodType.makeGeneric(3);
    + * mh = MethodHandles.collectArguments(mh, mt);
    + * // mt is {(Object,Object,Object) => Object}
    + * // (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
    + * x = mh.invoke((Object)1, (Object)2, (Object)3);
    + * assert(x.equals(java.util.Arrays.asList(1,2,3)));
    + * // mt is { => int}
    + * mt = MethodType.make(int.class);
    + * mh = lookup.findVirtual(java.util.List.class, "size", mt);
    + * // (Ljava/util/List;)I
    + * i = mh.<int>invoke(java.util.Arrays.asList(1,2,3));
    + * assert(i == 3);
    + * 
    + * Each of the above calls generates a single invokevirtual instruction + * with the name {@code invoke} and the type descriptors indicated in the comments. + * The argument types are taken directly from the actual arguments, + * while the return type is taken from the type parameter. + * (This type parameter may be a primitive, and it defaults to {@code Object}.) + *

    + * A note on generic typing: Method handles do not represent + * their function types in terms of Java parameterized (generic) types, + * because there are three mismatches between function types and parameterized + * Java types. + *

      + *
    1. Method types range over all possible arities, + * from no arguments to an arbitrary number of arguments. + * Generics are not variadic, and so cannot represent this.
    2. + *
    3. Method types can specify arguments of primitive types, + * which Java generic types cannot range over.
    4. + *
    5. Higher order functions over method handles (combinators) are + * often generic across a wide range of function types, including + * those of multiple arities. It is impossible to represent such + * genericity with a Java type parameter.
    6. + *
    * * @see MethodType * @see MethodHandles @@ -107,17 +177,19 @@ // with a JVM change which moves the required hidden state onto this class. extends MethodHandleImpl { - // interface MethodHandle> - // { T type(); public R invoke(A...); } + private static Access IMPL_TOKEN = Access.getToken(); - final private MethodType type; + // interface MethodHandle + // { MethodType type(); public R invoke(A...) throws X; } + + private MethodType type; /** * Report the type of this method handle. * Every invocation of this method handle must exactly match this type. * @return the method handle type */ - public MethodType type() { + public final MethodType type() { return type; } @@ -130,6 +202,369 @@ */ protected MethodHandle(Access token, MethodType type) { super(token); + Access.check(token); + this.type = type; + } + + private void initType(MethodType type) { + type.getClass(); // elicit NPE + if (this.type != null) throw new InternalError(); this.type = type; } + + static { + // This hack allows the implementation package special access to + // the internals of MethodHandle. In particular, the MTImpl has all sorts + // of cached information useful to the implementation code. + MethodHandleImpl.setMethodHandleFriend(IMPL_TOKEN, new MethodHandleImpl.MethodHandleFriend() { + public void initType(MethodHandle mh, MethodType type) { mh.initType(type); } + }); + } + + /** The string of a direct method handle is the simple name of its target method. + * The string of an adapter or bound method handle is the string of its + * target method handle. + * The string of a Java method handle is the string of its entry point method, + * unless the Java method handle overrides the toString method. + */ + @Override + public String toString() { + return MethodHandleImpl.getNameString(IMPL_TOKEN, this); + } + + //// First draft of the "Method Handle Kernel API" discussed at the JVM Language Summit, 9/2009. + //// Implementations here currently delegate to statics in MethodHandles. Some of those statics + //// will be deprecated. Others will be kept as "algorithms" to supply degrees of freedom + //// not present in the Kernel API. + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Perform an exact invocation. The signature at the call site of {@code invokeExact} must + * exactly match this method handle's {@code type}. + * No conversions are allowed on arguments or return values. + * This is not yet implemented, pending required compiler and JVM support. + */ + public final T invokeExact(Object... arguments) throws Throwable { + // This is an approximate implementation, which discards the caller's signature and refuses the call. + throw new InternalError("not yet implemented"); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Perform a generic invocation. The signature at the call site of {@code invokeExact} must + * have the same arity as this method handle's {@code type}. + * The same conversions are allowed on arguments or return values as are supported by + * by {@link MethodHandles#convertArguments}. + * If the call site signature exactly matches this method handle's {@code type}, + * the call proceeds as if by {@link #invokeExact}. + * This is not fully implemented, pending required compiler and JVM support. + */ + // This is an approximate implementation, which discards the caller's signature. + // When it is made signature polymorphic, the overloadings will disappear. + public final T invokeGeneric() throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this); + } + public final T invokeGeneric(Object a0) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0); + } + public final T invokeGeneric(Object a0, Object a1) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1); + } + public final T invokeGeneric(Object a0, Object a1, Object a2) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2); + } + public final T invokeGeneric(Object a0, Object a1, Object a2, Object a3) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2, a3); + } + public final T invokeGeneric(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2, a3, a4); + } + public final T invokeGeneric(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2, a3, a4, a5); + } + public final T invokeGeneric(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2, a3, a4, a5, a6); + } + public final T invokeGeneric(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2, a3, a4, a5, a6, a7); + } + public final T invokeGeneric(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + public final T invokeGeneric(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { + MethodHandle invoker = invokers(this.type()).genericInvoker(); + return invoker.invoke(this, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Perform a varargs invocation, passing the arguments in the given array + * to the method handle, as if via {@link #invokeGeneric} from a call site + * which mentions only the type {@code Object}, and whose arity is the length + * of the argument array. + *

    + * The length of the arguments array must equal the parameter count + * of the target's type. + * The arguments array is spread into separate arguments. + *

    + * In order to match the type of the target, the following argument + * conversions are applied as necessary: + *

      + *
    • reference casting + *
    • unboxing + *
    + * The following conversions are not applied: + *
      + *
    • primitive conversions (e.g., {@code byte} to {@code int} + *
    • varargs conversions other than the initial spread + *
    • any application-specific conversions (e.g., string to number) + *
    + * The result returned by the call is boxed if it is a primitive, + * or forced to null if the return type is void. + *

    + * This call is equivalent to the following code: + *

    +     *   MethodHandle invoker = MethodHandles.genericInvoker(this.type(), 0, true);
    +     *   Object result = invoker.invoke(this, arguments);
    +     * 
    + * @param arguments the arguments to pass to the target + * @return the result returned by the target + * @see MethodHandles#genericInvoker + */ + public final Object invokeVarargs(Object[] arguments) throws Throwable { + int argc = arguments == null ? 0 : arguments.length; + MethodType type = type(); + if (argc <= 10) { + MethodHandle invoker = MethodHandles.invokers(type).genericInvoker(); + switch (argc) { + case 0: return invoker.invoke(this); + case 1: return invoker.invoke(this, + arguments[0]); + case 2: return invoker.invoke(this, + arguments[0], arguments[1]); + case 3: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2]); + case 4: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2], + arguments[3]); + case 5: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4]); + case 6: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4], arguments[5]); + case 7: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4], arguments[5], + arguments[6]); + case 8: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4], arguments[5], + arguments[6], arguments[7]); + case 9: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4], arguments[5], + arguments[6], arguments[7], arguments[8]); + case 10: return invoker.invoke(this, + arguments[0], arguments[1], arguments[2], + arguments[3], arguments[4], arguments[5], + arguments[6], arguments[7], arguments[8], + arguments[9]); + } + } + + // more than ten arguments get boxed in a varargs list: + MethodHandle invoker = MethodHandles.invokers(type).varargsInvoker(0); + return invoker.invoke(this, arguments); + } + /** Equivalent to {@code invokeVarargs(arguments.toArray())}. */ + public final Object invokeVarargs(java.util.List arguments) throws Throwable { + return invokeVarargs(arguments.toArray()); + } + + /* --- this is intentionally NOT a javadoc yet --- + * PROVISIONAL API, WORK IN PROGRESS: + * Produce an adapter method handle which adapts the type of the + * current method handle to a new type by pairwise argument conversion. + * The original type and new type must have the same number of arguments. + * The resulting method handle is guaranteed to confess a type + * which is equal to the desired new type. + *

    + * If the original type and new type are equal, returns {@code this}. + *

    + * The following conversions are applied as needed both to + * arguments and return types. Let T0 and T1 be the differing + * new and old parameter types (or old and new return types) + * for corresponding values passed by the new and old method types. + * Given those types T0, T1, one of the following conversions is applied + * if possible: + *

      + *
    • If T0 and T1 are references, and T1 is not an interface type, + * then a cast to T1 is applied. + * (The types do not need to be related in any particular way.) + *
    • If T0 and T1 are references, and T1 is an interface type, + * then the value of type T0 is passed as a T1 without a cast. + * (This treatment of interfaces follows the usage of the bytecode verifier.) + *
    • If T0 and T1 are primitives, then a Java casting + * conversion (JLS 5.5) is applied, if one exists. + *
    • If T0 and T1 are primitives and one is boolean, + * the boolean is treated as a one-bit unsigned integer. + * (This treatment follows the usage of the bytecode verifier.) + * A conversion from another primitive type behaves as if + * it first converts to byte, and then masks all but the low bit. + *
    • If T0 is a primitive and T1 a reference, a boxing + * conversion is applied if one exists, possibly followed by + * an reference conversion to a superclass. + * T1 must be a wrapper class or a supertype of one. + * If T1 is a wrapper class, T0 is converted if necessary + * to T1's primitive type by one of the preceding conversions. + * Otherwise, T0 is boxed, and its wrapper converted to T1. + *
    • If T0 is a reference and T1 a primitive, an unboxing + * conversion is applied if one exists, possibly preceded by + * a reference conversion to a wrapper class. + * T0 must be a wrapper class or a supertype of one. + * If T0 is a wrapper class, its primitive value is converted + * if necessary to T1 by one of the preceding conversions. + * Otherwise, T0 is converted directly to the wrapper type for T1, + * which is then unboxed. + *
    • If the return type T1 is void, any returned value is discarded + *
    • If the return type T0 is void and T1 a reference, a null value is introduced. + *
    • If the return type T0 is void and T1 a primitive, a zero value is introduced. + *
    + *

    + */ + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce an adapter method handle which adapts the type of the + * current method handle to a new type by pairwise argument conversion. + * The original type and new type must have the same number of arguments. + * The resulting method handle is guaranteed to confess a type + * which is equal to the desired new type. + *

    + * If the original type and new type are equal, returns {@code this}. + *

    + * This method is equivalent to {@link MethodHandles#convertArguments}. + * @param newType the expected type of the new method handle + * @return a method handle which delegates to {@code this} after performing + * any necessary argument conversions, and arranges for any + * necessary return value conversions + * @throws IllegalArgumentException if the conversion cannot be made + * @see MethodHandles#convertArguments + */ + public final MethodHandle asType(MethodType newType) { + return MethodHandles.convertArguments(this, newType); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle which adapts, as its target, + * the current method handle. The type of the adapter will be + * the same as the type of the target, except that all but the first + * {@code keepPosArgs} parameters of the target's type are replaced + * by a single array parameter of type {@code Object[]}. + * Thus, if {@code keepPosArgs} is zero, the adapter will take all + * arguments in a single object array. + *

    + * When called, the adapter replaces a trailing array argument + * by the array's elements, each as its own argument to the target. + * (The order of the arguments is preserved.) + * They are converted pairwise by casting and/or unboxing + * (as if by {@link MethodHandles#convertArguments}) + * to the types of the trailing parameters of the target. + * Finally the target is called. + * What the target eventually returns is returned unchanged by the adapter. + *

    + * Before calling the target, the adapter verifies that the array + * contains exactly enough elements to provide a correct argument count + * to the target method handle. + * (The array may also be null when zero elements are required.) + * @param keepPosArgs the number of leading positional arguments to preserve + * @return a new method handle which spreads its final argument, + * before calling the original method handle + * @throws IllegalArgumentException if target does not have at least + * {@code keepPosArgs} parameter types + */ + public final MethodHandle asSpreader(int keepPosArgs) { + MethodType oldType = type(); + int nargs = oldType.parameterCount(); + MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs); + newType = newType.insertParameterTypes(keepPosArgs, Object[].class); + return MethodHandles.spreadArguments(this, newType); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle which adapts, as its target, + * the current method handle. The type of the adapter will be + * the same as the type of the target, except that a single trailing + * array parameter of type {@code Object[]} is replaced by + * {@code spreadArrayArgs} parameters of type {@code Object}. + *

    + * When called, the adapter replaces its trailing {@code spreadArrayArgs} + * arguments by a single new {@code Object} array, whose elements + * comprise (in order) the replaced arguments. + * Finally the target is called. + * What the target eventually returns is returned unchanged by the adapter. + *

    + * (The array may also be a shared constant when {@code spreadArrayArgs} is zero.) + * @param spreadArrayArgs the number of arguments to spread from the trailing array + * @return a new method handle which collects some trailing argument + * into an array, before calling the original method handle + * @throws IllegalArgumentException if the last argument of the target + * is not {@code Object[]} + * @throws IllegalArgumentException if {@code spreadArrayArgs} is not + * a legal array size + * @deprecated Provisional and unstable; use {@link MethodHandles#collectArguments}. + */ + public final MethodHandle asCollector(int spreadArrayArgs) { + MethodType oldType = type(); + int nargs = oldType.parameterCount(); + MethodType newType = oldType.dropParameterTypes(nargs-1, nargs); + newType = newType.insertParameterTypes(nargs-1, MethodType.genericMethodType(spreadArrayArgs).parameterArray()); + return MethodHandles.collectArguments(this, newType); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle which binds the given argument + * to the current method handle as target. + * The type of the bound handle will be + * the same as the type of the target, except that a single leading + * reference parameter will be omitted. + *

    + * When called, the bound handle inserts the given value {@code x} + * as a new leading argument to the target. The other arguments are + * also passed unchanged. + * What the target eventually returns is returned unchanged by the bound handle. + *

    + * The reference {@code x} must be convertible to the first parameter + * type of the target. + * @param x the value to bind to the first argument of the target + * @return a new method handle which collects some trailing argument + * into an array, before calling the original method handle + * @throws IllegalArgumentException if the target does not have a + * leading parameter type that is a reference type + * @throws ClassCastException if {@code x} cannot be converted + * to the leading parameter type of the target + * @deprecated Provisional and unstable; use {@link MethodHandles#insertArguments}. + */ + public final MethodHandle bindTo(Object x) { + return MethodHandles.insertArguments(this, 0, x); + } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/MethodHandles.java --- a/jdk/src/share/classes/java/dyn/MethodHandles.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/MethodHandles.java Wed Jul 05 17:05:01 2017 +0200 @@ -34,6 +34,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.List; import java.util.ArrayList; import java.util.Arrays; import sun.dyn.Invokers; @@ -44,17 +45,14 @@ /** * Fundamental operations and utilities for MethodHandle. + * They fall into several categories: + *

      + *
    • Reifying methods and fields. This is subject to access checks. + *
    • Invoking method handles on dynamically typed arguments and/or varargs arrays. + *
    • Combining or transforming pre-existing method handles into new ones. + *
    • Miscellaneous emulation of common JVM operations or control flow patterns. + *
    *

    - * API Note: The matching of method types in this API cannot - * be completely checked by Java's generic type system for three reasons: - *

      - *
    1. Method types range over all possible arities, - * from no arguments to an arbitrary number of arguments. - * Generics are not variadic, and so cannot represent this.
    2. - *
    3. Method types can specify arguments of primitive types, - * which Java generic types cannot range over.
    4. - *
    5. Method types can optionally specify varargs (ellipsis).
    6. - *
    * @author John Rose, JSR 292 EG */ public class MethodHandles { @@ -68,12 +66,22 @@ //// Method handle creation from ordinary methods. + /** Create a {@link Lookup} lookup object on the caller. + * + */ public static Lookup lookup() { return new Lookup(); } + /** Version of lookup which is trusted minimally. + * It can only be used to create method handles to + * publicly accessible members. + */ + public static Lookup publicLookup() { + return Lookup.PUBLIC_LOOKUP; + } + /** - * PROVISIONAL API, WORK IN PROGRESS: * A factory object for creating method handles, when the creation * requires access checking. Method handles do not perform * access checks when they are called; this is a major difference @@ -121,7 +129,8 @@ /** Which class is performing the lookup? It is this class against * which checks are performed for visibility and access permissions. *

    - * This value is null if and only if this lookup is {@link #PUBLIC_LOOKUP}. + * This value is null if and only if this lookup was produced + * by {@link MethodHandles#publicLookup}. */ public Class lookupClass() { return lookupClass; @@ -135,23 +144,46 @@ * an access$N method. */ Lookup() { - Class caller = getCallerClassAtEntryPoint(); - // make sure we haven't accidentally picked up this class: - checkUnprivilegedlookupClass(caller); - this.lookupClass = caller; + this(IMPL_TOKEN, getCallerClassAtEntryPoint()); + } + + Lookup(Access token, Class lookupClass) { + // make sure we haven't accidentally picked up a privileged class: + checkUnprivilegedlookupClass(lookupClass); + this.lookupClass = lookupClass; + } + + /** + * Create a lookup on the specified class. + * The result is guaranteed to have no more access privileges + * than the original. + */ + public Lookup in(Class newLookupClass) { + if (this == PUBLIC_LOOKUP) return PUBLIC_LOOKUP; + if (newLookupClass == null) return PUBLIC_LOOKUP; + if (newLookupClass == lookupClass) return this; + if (this != IMPL_LOOKUP) { + if (!VerifyAccess.isSamePackage(lookupClass, newLookupClass)) + throw newNoAccessException(new MemberName(newLookupClass), this); + checkUnprivilegedlookupClass(newLookupClass); + } + return new Lookup(newLookupClass); } private Lookup(Class lookupClass) { this.lookupClass = lookupClass; } + // Make sure outer class is initialized first. + static { IMPL_TOKEN.getClass(); } + private static final Class PUBLIC_ONLY = sun.dyn.empty.Empty.class; /** Version of lookup which is trusted minimally. * It can only be used to create method handles to * publicly accessible members. */ - public static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY); + static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY); /** Package-private version of lookup which is trusted. */ static final Lookup IMPL_LOOKUP = new Lookup(null); @@ -178,12 +210,16 @@ // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint, // 2: Lookup., 3: MethodHandles.*, 4: caller // Note: This should be the only use of getCallerClass in this file. + assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class); return Reflection.getCallerClass(CALLER_DEPTH); } /** * Produce a method handle for a static method. * The type of the method handle will be that of the method. + * (Since static methods do not take receivers, there is no + * additional receiver argument inserted into the method handle type, + * as there would be with {@linkplain #findVirtual} or {@linkplain #findSpecial}.) * The method and all its argument types must be accessible to the lookup class. * If the method's class has not yet been initialized, that is done * immediately, before the method handle is returned. @@ -196,10 +232,11 @@ */ public MethodHandle findStatic(Class defc, String name, MethodType type) throws NoAccessException { - MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass); - checkStatic(true, method, lookupClass); + MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass()); + VerifyAccess.checkName(method, this); + checkStatic(true, method, this); //throw NoSuchMethodException - return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass); + return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass()); } /** @@ -228,9 +265,10 @@ * @exception NoAccessException if the method does not exist or access checking fails */ public MethodHandle findVirtual(Class defc, String name, MethodType type) throws NoAccessException { - MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass); - checkStatic(false, method, lookupClass); - return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass); + MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), true, lookupClass()); + VerifyAccess.checkName(method, this); + checkStatic(false, method, this); + return MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass()); } /** @@ -259,15 +297,17 @@ */ public MethodHandle findSpecial(Class defc, String name, MethodType type, Class specialCaller) throws NoAccessException { - checkSpecialCaller(specialCaller, lookupClass); - MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller); - checkStatic(false, method, lookupClass); + checkSpecialCaller(specialCaller, this); + Lookup slookup = this.in(specialCaller); + MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, slookup.lookupClass()); + VerifyAccess.checkName(method, this); + checkStatic(false, method, this); if (name.equals("")) { throw newNoAccessException("cannot directly invoke a constructor", method, null); } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) { - throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass); + throw newNoAccessException("method must be in a superclass of lookup class", method, slookup.lookupClass()); } - return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, specialCaller); + return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, slookup.lookupClass()); } /** @@ -275,13 +315,19 @@ * The receiver must have a supertype {@code defc} in which a method * of the given name and type is accessible to the lookup class. * The method and all its argument types must be accessible to the lookup class. - * The type of the method handle will be that of the method. - * The given receiver will be bound into the method handle. + * The type of the method handle will be that of the method, + * without any insertion of an additional receiver parameter. + * The given receiver will be bound into the method handle, + * so that every call to the method handle will invoke the + * requested method on the given receiver. *

    - * Equivalent to the following expression: + * This is equivalent to the following expression: * - * {@link #insertArgument}({@link #findVirtual}(defc, name, type), receiver) + * {@link #insertArguments}({@link #findVirtual}(defc, name, type), receiver) * + * where {@code defc} is either {@code receiver.getClass()} or a super + * type of that class, in which the requested method is accessible + * to the lookup class. * @param receiver the object from which the method is accessed * @param name the name of the method * @param type the type of the method, with the receiver argument omitted @@ -292,16 +338,18 @@ public MethodHandle bind(Object receiver, String name, MethodType type) throws NoAccessException { Class rcvc = receiver.getClass(); // may get NPE MemberName reference = new MemberName(rcvc, name, type); - MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass); - checkStatic(false, method, lookupClass); - MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass); + MemberName method = IMPL_NAMES.resolveOrFail(reference, true, lookupClass()); + VerifyAccess.checkName(method, this); + checkStatic(false, method, this); + MethodHandle dmh = MethodHandleImpl.findMethod(IMPL_TOKEN, method, true, lookupClass()); MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, dmh, receiver); if (bmh == null) - throw newNoAccessException(method, lookupClass); + throw newNoAccessException(method, this); return bmh; } /** + * PROVISIONAL API, WORK IN PROGRESS: * Make a direct method handle to m, if the lookup class has permission. * If m is non-static, the receiver argument is treated as an initial argument. * If m is virtual, overriding is respected on every call. @@ -316,10 +364,11 @@ * @exception NoAccessException if access checking fails */ public MethodHandle unreflect(Method m) throws NoAccessException { - return unreflectImpl(new MemberName(m), m.isAccessible(), true, lookupClass); + return unreflectImpl(new MemberName(m), m.isAccessible(), true, false, this); } /** + * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle for a reflected method. * It will bypass checks for overriding methods on the receiver, * as if by the {@code invokespecial} instruction. @@ -333,37 +382,41 @@ * @exception NoAccessException if access checking fails */ public MethodHandle unreflectSpecial(Method m, Class specialCaller) throws NoAccessException { - checkSpecialCaller(specialCaller, lookupClass); + checkSpecialCaller(specialCaller, this); + Lookup slookup = this.in(specialCaller); MemberName mname = new MemberName(m); - checkStatic(false, mname, lookupClass); - return unreflectImpl(mname, m.isAccessible(), false, specialCaller); + checkStatic(false, mname, this); + return unreflectImpl(mname, m.isAccessible(), false, false, slookup); } /** + * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle for a reflected constructor. - * The type of the method handle will be that of the constructor. + * The type of the method handle will be that of the constructor, + * with the return type changed to the declaring class. * The method handle will perform a {@code newInstance} operation, * creating a new instance of the constructor's class on the * arguments passed to the method handle. *

    * If the constructor's {@code accessible} flag is not set, - * access checking is performed immediately on behalf of the lookup class, - * as if {@code invokespecial} instruction were being linked. + * access checking is performed immediately on behalf of the lookup class. * @param ctor the reflected constructor * @return a method handle which can invoke the reflected constructor * @exception NoAccessException if access checking fails */ public MethodHandle unreflectConstructor(Constructor ctor) throws NoAccessException { MemberName m = new MemberName(ctor); - return unreflectImpl(m, ctor.isAccessible(), false, lookupClass); + return unreflectImpl(m, ctor.isAccessible(), false, false, this); } /** * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving read access to a reflected field. * The type of the method handle will have a return type of the field's - * value type. Its sole argument will be the field's containing class - * (but only if it is non-static). + * value type. + * If the field is static, the method handle will take no arguments. + * Otherwise, its single argument will be the instance containing + * the field. * If the method's {@code accessible} flag is not set, * access checking is performed immediately on behalf of the lookup class. * @param f the reflected field @@ -371,16 +424,18 @@ * @exception NoAccessException if access checking fails */ public MethodHandle unreflectGetter(Field f) throws NoAccessException { - return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), false, lookupClass); + MemberName m = new MemberName(f); + return unreflectImpl(m, f.isAccessible(), false, false, this); } /** * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle giving write access to a reflected field. * The type of the method handle will have a void return type. - * Its last argument will be the field's value type. - * Its other argument will be the field's containing class - * (but only if it is non-static). + * If the field is static, the method handle will take a single + * argument, of the field's value type, the value to be stored. + * Otherwise, the two arguments will be the instance containing + * the field, and the value to be stored. * If the method's {@code accessible} flag is not set, * access checking is performed immediately on behalf of the lookup class. * @param f the reflected field @@ -388,59 +443,75 @@ * @exception NoAccessException if access checking fails */ public MethodHandle unreflectSetter(Field f) throws NoAccessException { - return MethodHandleImpl.accessField(IMPL_TOKEN, new MemberName(f), true, lookupClass); + MemberName m = new MemberName(f); + return unreflectImpl(m, f.isAccessible(), false, true, this); } } static /*must not be public*/ - MethodHandle findStaticFrom(Class lookupClass, + MethodHandle findStaticFrom(Lookup lookup, Class defc, String name, MethodType type) throws NoAccessException { - MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookupClass); - checkStatic(true, method, lookupClass); - return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookupClass); + MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type, Modifier.STATIC), true, lookup.lookupClass()); + VerifyAccess.checkName(method, lookup); + checkStatic(true, method, lookup); + return MethodHandleImpl.findMethod(IMPL_TOKEN, method, false, lookup.lookupClass()); } - static void checkStatic(boolean wantStatic, MemberName m, Class lookupClass) { + static void checkStatic(boolean wantStatic, MemberName m, Lookup lookup) { if (wantStatic != m.isStatic()) { String message = wantStatic ? "expected a static method" : "expected a non-static method"; - throw newNoAccessException(message, m, lookupClass); + throw newNoAccessException(message, m, lookup.lookupClass()); } } - static void checkSpecialCaller(Class specialCaller, Class lookupClass) { - if (lookupClass == Lookup.IMPL_LOOKUP.lookupClass()) + static void checkSpecialCaller(Class specialCaller, Lookup lookup) { + if (lookup == Lookup.IMPL_LOOKUP) return; // privileged action - if (lookupClass == null || // public-only access - !VerifyAccess.isSamePackageMember(specialCaller, lookupClass)) - throw newNoAccessException("no private access", new MemberName(specialCaller), lookupClass); + assert(lookup.lookupClass() != null); + if (!VerifyAccess.isSamePackageMember(specialCaller, lookup.lookupClass())) + throw newNoAccessException("no private access", new MemberName(specialCaller), lookup.lookupClass()); } // Helper for creating handles on reflected methods and constructors. static MethodHandle unreflectImpl(MemberName m, boolean isAccessible, - boolean doDispatch, Class lookupClass) { - MethodType mtype = m.getInvocationType(); + boolean doDispatch, boolean isSetter, Lookup lookup) { + MethodType narrowMethodType = null; Class defc = m.getDeclaringClass(); + boolean isSpecialInvoke = m.isInvocable() && !doDispatch; int mods = m.getModifiers(); if (m.isStatic()) { if (!isAccessible && - VerifyAccess.isAccessible(defc, mods, false, lookupClass) == null) - throw newNoAccessException(m, lookupClass); + VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), false) == null) + throw newNoAccessException(m, lookup); } else { Class constraint; if (isAccessible) { // abbreviated access check for "unlocked" method - constraint = doDispatch ? defc : lookupClass; + constraint = doDispatch ? defc : lookup.lookupClass(); } else { - constraint = VerifyAccess.isAccessible(defc, mods, doDispatch, lookupClass); + constraint = VerifyAccess.isAccessible(defc, mods, lookup.lookupClass(), isSpecialInvoke); + } + if (constraint == null) { + throw newNoAccessException(m, lookup); } if (constraint != defc && !constraint.isAssignableFrom(defc)) { if (!defc.isAssignableFrom(constraint)) - throw newNoAccessException("receiver must be in caller class", m, lookupClass); - mtype = mtype.changeParameterType(0, constraint); + throw newNoAccessException("receiver must be in caller class", m, lookup.lookupClass()); + if (m.isInvocable()) + narrowMethodType = m.getInvocationType().changeParameterType(0, constraint); + else if (m.isField()) + narrowMethodType = (!isSetter + ? MethodType.methodType(m.getFieldType(), constraint) + : MethodType.methodType(void.class, constraint, m.getFieldType())); } } - return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookupClass); + if (m.isInvocable()) + return MethodHandleImpl.findMethod(IMPL_TOKEN, m, doDispatch, lookup.lookupClass()); + else if (m.isField()) + return MethodHandleImpl.accessField(IMPL_TOKEN, m, isSetter, lookup.lookupClass()); + else + throw new InternalError(); } /** @@ -472,138 +543,104 @@ return MethodHandleImpl.accessArrayElement(IMPL_TOKEN, arrayClass, true); } - /// method handle invocation (reflective style) /** - * PROVISIONAL API, WORK IN PROGRESS: - * Call the {@code invoke} method of a given method handle, - * with arguments that exactly match the parameter types of the method handle. - * The length of the arguments array must equal the parameter count - * of the target's type. - * The arguments array is spread into separate arguments, and - * basic reference and unboxing conversions are applied. - *

    - * In order to match the type of the target, the following argument - * conversions are applied as necessary: - *

      - *
    • reference casting - *
    • unboxing - *
    - * The following conversions are not applied: - *
      - *
    • primitive conversions (e.g., {@code byte} to {@code int} - *
    • varargs conversions other than the initial spread - *
    • any application-specific conversions (e.g., string to number) - *
    - * The result returned by the call is boxed if it is a primitive, - * or forced to null if the return type is void. - *

    - * This call is a convenience method for the following code: - *

    -     *   MethodHandle invoker = MethodHandles.genericInvoker(target.type(), 0, true);
    -     *   Object result = invoker.invoke(arguments);
    -     * 
    - * @param target the method handle to invoke - * @param arguments the arguments to pass to the target - * @return the result returned by the target + * @deprecated Alias for MethodHandle.invokeVarargs. */ + @Deprecated public static - Object invoke(MethodHandle target, Object... arguments) { - int argc = arguments == null ? 0 : arguments.length; - MethodType type = target.type(); - if (argc <= 4) { - MethodHandle invoker = invokers(type).genericInvoker(); - switch (argc) { - case 0: return invoker.invoke(target); - case 1: return invoker.invoke(target, - arguments[0]); - case 2: return invoker.invoke(target, - arguments[0], arguments[1]); - case 3: return invoker.invoke(target, - arguments[0], arguments[1], arguments[2]); - case 4: return invoker.invoke(target, - arguments[0], arguments[1], arguments[2], arguments[3]); - } - } - MethodHandle invoker = invokers(type).varargsInvoker(); - return invoker.invoke(target, arguments); + Object invokeVarargs(MethodHandle target, Object... arguments) throws Throwable { + return target.invokeVarargs(arguments); } - public static - Object invoke_0(MethodHandle target) { - MethodHandle invoker = invokers(target.type()).genericInvoker(); - return invoker.invoke(target); - } - public static - Object invoke_1(MethodHandle target, Object a0) { - MethodHandle invoker = invokers(target.type()).genericInvoker(); - return invoker.invoke(target, a0); - } + /** + * @deprecated Alias for MethodHandle.invokeVarargs. + */ + @Deprecated public static - Object invoke_2(MethodHandle target, Object a0, Object a1) { - MethodHandle invoker = invokers(target.type()).genericInvoker(); - return invoker.invoke(target, a0, a1); - } - public static - Object invoke_3(MethodHandle target, Object a0, Object a1, Object a2) { - MethodHandle invoker = invokers(target.type()).genericInvoker(); - return invoker.invoke(target, a0, a1, a2); - } - public static - Object invoke_4(MethodHandle target, Object a0, Object a1, Object a2, Object a3) { - MethodHandle invoker = invokers(target.type()).genericInvoker(); - return invoker.invoke(target, a0, a1, a2, a3); + Object invoke(MethodHandle target, Object... arguments) throws Throwable { + return target.invokeVarargs(arguments); } /** * PROVISIONAL API, WORK IN PROGRESS: - * Give a method handle which will invoke any method handle of the + * Produce a method handle which will invoke any method handle of the * given type on a standard set of {@code Object} type arguments. - * The the resulting invoker will be a method handle with the following + * The resulting invoker will be a method handle with the following * arguments: *
      *
    • a single {@code MethodHandle} target - *
    • zero or more {@code Object} values - *
    • an optional {@code Object[]} array containing more arguments + *
    • zero or more {@code Object} values (one for each argument in {@code type}) *
    - * The invoker will spread the varargs array (if present), apply + * The invoker will apply reference casts as necessary and unbox primitive arguments, + * as if by {@link #convertArguments}. + * The return value of the invoker will be an {@code Object} reference, + * boxing a primitive value if the original type returns a primitive, + * and always null if the original type returns void. + *

    + * This method is equivalent to the following code (though it may be more efficient): + *

    +     * MethodHandle invoker = exactInvoker(type);
    +     * MethodType genericType = type.generic();
    +     * genericType = genericType.insertParameterType(0, MethodHandle.class);
    +     * return convertArguments(invoker, genericType);
    +     * 
    + * @param type the type of target methods which the invoker will apply to + * @return a method handle suitable for invoking any method handle of the given type + */ + static public + MethodHandle genericInvoker(MethodType type) { + return invokers(type).genericInvoker(); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle which will invoke any method handle of the + * given type on a standard set of {@code Object} type arguments + * and a single trailing {@code Object[]} array. + * The resulting invoker will be a method handle with the following + * arguments: + *
      + *
    • a single {@code MethodHandle} target + *
    • zero or more {@code Object} values (counted by {@code objectArgCount}) + *
    • an {@code Object[]} array containing more arguments + *
    + * The invoker will spread the varargs array, apply * reference casts as necessary, and unbox primitive arguments. * The return value of the invoker will be an {@code Object} reference, * boxing a primitive value if the original type returns a primitive, * and always null if the original type returns void. *

    - * This is a convenience method equivalent to the following code: - *

    +     * This method is equivalent to the following code (though it may be more efficient):
    +     * 

          * MethodHandle invoker = exactInvoker(type);
    -     * MethodType genericType = MethodType.makeGeneric(objectArgCount, varargs);
    -     * genericType = genericType.insertParameterType(0, MethodHandle.class);
    -     * if (!varargs)
    -     *     return convertArguments(invoker, genericType);
    -     * else
    -     *     return spreadArguments(invoker, genericType);
    -     * 
    + * MethodType vaType = MethodType.makeGeneric(objectArgCount, true); + * vaType = vaType.insertParameterType(0, MethodHandle.class); + * return spreadArguments(invoker, vaType); + *
    * @param type the desired target type * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments - * @param varargs if true, the invoker will accept a final {@code Object[]} argument * @return a method handle suitable for invoking any method handle of the given type */ static public - MethodHandle genericInvoker(MethodType type, int objectArgCount, boolean varargs) { - return invokers(type).genericInvoker(); + MethodHandle varargsInvoker(MethodType type, int objectArgCount) { + if (objectArgCount < 0 || objectArgCount > type.parameterCount()) + throw new IllegalArgumentException("bad argument count "+objectArgCount); + return invokers(type).varargsInvoker(objectArgCount); } /** * PROVISIONAL API, WORK IN PROGRESS: - * Give a method handle which will take a invoke any method handle of the + * Produce a method handle which will take a invoke any method handle of the * given type. The resulting invoker will have a type which is * exactly equal to the desired type, except that it will accept * an additional leading argument of type {@code MethodHandle}. *

    - * This is a convenience method equivalent to the following code: - *

    -     *     MethodHandles.lookup().findVirtual(MethodHandle.class, "invoke", type);
    -     * 
    + * This method is equivalent to the following code (though it may be more efficient): + *

    +     * lookup().findVirtual(MethodHandle.class, "invoke", type);
    +     * 
    * @param type the desired target type * @return a method handle suitable for invoking any method handle of the given type */ @@ -612,7 +649,30 @@ return invokers(type).exactInvoker(); } - static private Invokers invokers(MethodType type) { + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Produce a method handle equivalent to an invokedynamic instruction + * which has been linked to the given call site. + * Along with {@link Lookup#findVirtual}, {@link Lookup#findStatic}, + * and {@link Lookup#findSpecial}, this completes the emulation + * of the JVM's {@code invoke} instructions. + *

    This method is equivalent to the following code: + *

    +     * MethodHandle getTarget, invoker, result;
    +     * getTarget = lookup().bind(site, "getTarget", methodType(MethodHandle.class));
    +     * invoker = exactInvoker(site.type());
    +     * result = foldArguments(invoker, getTarget)
    +     * 
    + * @return a method handle which always invokes the call site's target + */ + public static + MethodHandle dynamicInvoker(CallSite site) { + MethodHandle getTarget = MethodHandleImpl.bindReceiver(IMPL_TOKEN, CallSite.GET_TARGET, site); + MethodHandle invoker = exactInvoker(site.type()); + return foldArguments(invoker, getTarget); + } + + static Invokers invokers(MethodType type) { return MethodTypeImpl.invokers(IMPL_TOKEN, type); } @@ -688,14 +748,11 @@ /// method handle modification (creation from other method handles) /** - * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which adapts the type of the - * given method handle to a new type, by pairwise argument conversion, - * and/or varargs conversion. - * The original type and new type must have the same number of - * arguments, or else one or both them the must be varargs types. + * given method handle to a new type by pairwise argument conversion. + * The original type and new type must have the same number of arguments. * The resulting method handle is guaranteed to confess a type - * which is equal to the desired new type, with any varargs property erased. + * which is equal to the desired new type. *

    * If the original type and new type are equal, returns target. *

    @@ -703,26 +760,15 @@ * arguments and return types. Let T0 and T1 be the differing * new and old parameter types (or old and new return types) * for corresponding values passed by the new and old method types. - *

    - * If an ordinary (non-varargs) parameter of the new type is - * to be boxed in a varargs parameter of the old type of type T1[], - * then T1 is the element type of the varargs array. - * Otherwise, if a varargs parameter of the new type of type T0[] - * is to be spread into one or more outgoing old type parameters, - * then T0 is the element type of the - * If the new type is varargs and the old type is not, the varargs - * argument will be checked and must be a non-null array of exactly - * the right length. If there are no parameters in the old type - * corresponding to the new varargs parameter, the varargs argument - * is also allowed to be null. - *

    * Given those types T0, T1, one of the following conversions is applied * if possible: *

      - *
    • If T0 and T1 are references, then a cast to T2 is applied, - * where T2 is Object if T1 is an interface, else T1. - * (The types do not need to be related in any particular way. - * The treatment of interfaces follows the usage of the bytecode verifier.) + *
    • If T0 and T1 are references, and T1 is not an interface type, + * then a cast to T1 is applied. + * (The types do not need to be related in any particular way.) + *
    • If T0 and T1 are references, and T1 is an interface type, + * then the value of type T0 is passed as a T1 without a cast. + * (This treatment of interfaces follows the usage of the bytecode verifier.) *
    • If T0 and T1 are primitives, then a Java casting * conversion (JLS 5.5) is applied, if one exists. *
    • If T0 and T1 are primitives and one is boolean, @@ -745,16 +791,17 @@ * if necessary to T1 by one of the preceding conversions. * Otherwise, T0 is converted directly to the wrapper type for T1, * which is then unboxed. - *
    • If T1 is void, any returned value is discarded - *
    • If T0 is void and T1 a reference, a null value is introduced. - *
    • If T0 is void and T1 a primitive, a zero value is introduced. + *
    • If the return type T1 is void, any returned value is discarded + *
    • If the return type T0 is void and T1 a reference, a null value is introduced. + *
    • If the return type T0 is void and T1 a primitive, a zero value is introduced. *
    * @param target the method handle to invoke after arguments are retyped * @param newType the expected type of the new method handle * @return a method handle which delegates to {@code target} after performing * any necessary argument conversions, and arranges for any * necessary return value conversions - * @throws WrongMethodTypeException if the conversion cannot be made + * @throws IllegalArgumentException if the conversion cannot be made + * @see MethodHandle#asType */ public static MethodHandle convertArguments(MethodHandle target, MethodType newType) { @@ -872,23 +919,17 @@ * PROVISIONAL API, WORK IN PROGRESS: * Produce a method handle which adapts the type of the * given method handle to a new type, by collecting a series of - * trailing arguments into an array. - * The resulting method handle is guaranteed to confess a type - * which is equal to the desired new type. + * trailing arguments as elements to a single argument array. *

    - * This method is inverse to {@link #spreadArguments}. + * This method may be used as an inverse to {@link #spreadArguments}. * The final parameter type of the old type must be an array type T[], * which is the type of what is called the spread argument. * The trailing arguments of the new type which correspond to * the spread argument are all converted to type T and collected * into an array before the original method is called. - *

    - * ISSUE: Unify this with combineArguments. CollectArguments - * is combineArguments with (a) new Object[]{...} as a combiner, - * and (b) the combined arguments dropped, in favor of the combined result. * @param target the method handle to invoke after the argument is prepended * @param newType the expected type of the new method handle - * @return a new method handle which collects some trailings argument + * @return a new method handle which collects some trailing argument * into an array, before calling the original method handle */ public static @@ -900,50 +941,72 @@ int numCollect = (inargs - collectPos); if (collectPos < 0 || numCollect < 0) throw newIllegalArgumentException("wrong number of arguments"); - return MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos); + MethodHandle res = MethodHandleImpl.collectArguments(IMPL_TOKEN, target, newType, collectPos, null); + if (res == null) { + throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType); + } + return res; } /** * PROVISIONAL API, WORK IN PROGRESS: - * Produce a method handle which calls the original method handle, - * after inserting the given argument at the given position. - * The type of the new method handle will drop the corresponding argument - * type from the original handle's type. + * Produce a method handle which calls the original method handle {@code target}, + * after inserting the given argument(s) at the given position. + * The formal parameters to {@code target} which will be supplied by those + * arguments are called bound parameters, because the new method + * will contain bindings for those parameters take from {@code values}. + * The type of the new method handle will drop the types for the bound + * parameters from the original target type, since the new method handle + * will no longer require those arguments to be supplied by its callers. *

    - * The given argument object must match the dropped argument type. - * If the dropped argument type is a primitive, the argument object - * must be a wrapper, and is unboxed to produce the primitive. + * Each given argument object must match the corresponding bound parameter type. + * If a bound parameter type is a primitive, the argument object + * must be a wrapper, and will be unboxed to produce the primitive value. *

    * The pos may range between zero and N (inclusively), - * where N is the number of argument types in target, - * meaning to insert the new argument as the first or last (respectively), - * or somewhere in between. + * where N is the number of argument types in resulting method handle + * (after bound parameter types are dropped). * @param target the method handle to invoke after the argument is inserted * @param pos where to insert the argument (zero for the first) - * @param value the argument to insert + * @param values the series of arguments to insert * @return a new method handle which inserts an additional argument, * before calling the original method handle */ public static - MethodHandle insertArgument(MethodHandle target, int pos, Object value) { + MethodHandle insertArguments(MethodHandle target, int pos, Object... values) { + int insCount = values.length; MethodType oldType = target.type(); ArrayList> ptypes = new ArrayList>(oldType.parameterList()); int outargs = oldType.parameterCount(); - int inargs = outargs - 1; - if (pos < 0 || pos >= outargs) + int inargs = outargs - insCount; + if (inargs < 0) + throw newIllegalArgumentException("too many values to insert"); + if (pos < 0 || pos > inargs) throw newIllegalArgumentException("no argument type to append"); - Class valueType = ptypes.remove(pos); - value = checkValue(valueType, value); - if (pos == 0 && !valueType.isPrimitive()) { - // At least for now, make bound method handles a special case. - // This lets us get by with minimal JVM support, at the expense - // of generating signature-specific adapters as Java bytecodes. - MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, target, value); - if (bmh != null) return bmh; - // else fall through to general adapter machinery + MethodHandle result = target; + for (int i = 0; i < insCount; i++) { + Object value = values[i]; + Class valueType = oldType.parameterType(pos+i); + value = checkValue(valueType, value); + if (pos == 0 && !valueType.isPrimitive()) { + // At least for now, make bound method handles a special case. + MethodHandle bmh = MethodHandleImpl.bindReceiver(IMPL_TOKEN, result, value); + if (bmh != null) { + result = bmh; + continue; + } + // else fall through to general adapter machinery + } + result = MethodHandleImpl.bindArgument(IMPL_TOKEN, result, pos, value); } - return MethodHandleImpl.bindArgument(IMPL_TOKEN, target, pos, value); + return result; + } + + @Deprecated // "use MethodHandles.insertArguments instead" + public static + MethodHandle insertArgument(MethodHandle target, int pos, Object value) { + return insertArguments(target, pos, value); } /** @@ -953,10 +1016,25 @@ * The type of the new method handle will insert the given argument * type(s), at that position, into the original handle's type. *

    - * The pos may range between zero and N-1, + * The pos may range between zero and N, * where N is the number of argument types in target, * meaning to drop the first or last argument (respectively), * or an argument somewhere in between. + *

    + * Example: + *

    +     *   MethodHandle cat = MethodHandles.lookup().
    +     *     findVirtual(String.class, "concat", String.class, String.class);
    +     *   System.out.println(cat.<String>invoke("x", "y")); // xy
    +     *   MethodHandle d0 = dropArguments(cat, 0, String.class);
    +     *   System.out.println(d0.<String>invoke("x", "y", "z")); // xy
    +     *   MethodHandle d1 = dropArguments(cat, 1, String.class);
    +     *   System.out.println(d1.<String>invoke("x", "y", "z")); // xz
    +     *   MethodHandle d2 = dropArguments(cat, 2, String.class);
    +     *   System.out.println(d2.<String>invoke("x", "y", "z")); // yz
    +     *   MethodHandle d12 = dropArguments(cat, 1, String.class, String.class);
    +     *   System.out.println(d12.<String>invoke("w", "x", "y", "z")); // wz
    +     * 
    * @param target the method handle to invoke after the argument is dropped * @param valueTypes the type(s) of the argument to drop * @param pos which argument to drop (zero for the first) @@ -964,20 +1042,150 @@ * before calling the original method handle */ public static - MethodHandle dropArguments(MethodHandle target, int pos, Class... valueTypes) { - if (valueTypes.length == 0) return target; + MethodHandle dropArguments(MethodHandle target, int pos, List> valueTypes) { + if (valueTypes.size() == 0) return target; MethodType oldType = target.type(); int outargs = oldType.parameterCount(); - int inargs = outargs + valueTypes.length; + int inargs = outargs + valueTypes.size(); if (pos < 0 || pos >= inargs) throw newIllegalArgumentException("no argument type to remove"); ArrayList> ptypes = new ArrayList>(oldType.parameterList()); - ptypes.addAll(pos, Arrays.asList(valueTypes)); - MethodType newType = MethodType.make(oldType.returnType(), ptypes); + ptypes.addAll(pos, valueTypes); + MethodType newType = MethodType.methodType(oldType.returnType(), ptypes); return MethodHandleImpl.dropArguments(IMPL_TOKEN, target, newType, pos); } + public static + MethodHandle dropArguments(MethodHandle target, int pos, Class... valueTypes) { + return dropArguments(target, pos, Arrays.asList(valueTypes)); + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Adapt a target method handle {@code target} by pre-processing + * one or more of its arguments, each with its own unary filter function, + * and then calling the target with each pre-processed argument + * replaced by the result of its corresponding filter function. + *

    + * The pre-processing is performed by one or more method handles, + * specified in the non-null elements of the {@code filters} array. + * (If there are no such elements, the original target is returned.) + * Each filter (that is, each non-null element of {@code filters}) + * is applied to the corresponding argument of the adapter. + *

    + * If a filter {@code F} applies to the {@code N}th argument of + * the method handle, then {@code F} must be a method handle which + * takes exactly one argument. The type of {@code F}'s sole argument + * replaces the corresponding argument type of the target + * in the resulting adapted method handle. + * The return type of {@code F} must be identical to the corresponding + * parameter type of the target. + *

    + * It is an error if there are non-null elements of {@code filters} + * which do not correspond to argument positions in the target. + * The actual length of the target array may be any number, it need + * not be the same as the parameter count of the target type. + * (This provides an easy way to filter just the first argument or two + * of a target method handle.) + *

    Here is pseudocode for the resulting adapter: + *

    +     * // there are N arguments in the A sequence
    +     * T target(A[N]...);
    +     * [i<N] V[i] filter[i](B[i]) = filters[i] ?: identity;
    +     * T adapter(B[N]... b) {
    +     *   A[N] a...;
    +     *   [i<N] a[i] = filter[i](b[i]);
    +     *   return target(a...);
    +     * }
    +     * 
    + * @param target the method handle to invoke after arguments are filtered + * @param filters method handles to call initially on filtered arguments + * @return method handle which incorporates the specified argument filtering logic + * @throws IllegalArgumentException if a non-null element of {@code filters} + * does not match a corresponding argument type of {@code target} + */ + public static + MethodHandle filterArguments(MethodHandle target, MethodHandle... filters) { + MethodType targetType = target.type(); + MethodHandle adapter = target; + MethodType adapterType = targetType; + int pos = -1, maxPos = targetType.parameterCount(); + for (MethodHandle filter : filters) { + pos += 1; + if (filter == null) continue; + if (pos >= maxPos) + throw newIllegalArgumentException("too many filters"); + MethodType filterType = filter.type(); + if (filterType.parameterCount() != 1 + || filterType.returnType() != targetType.parameterType(pos)) + throw newIllegalArgumentException("target and filter types do not match"); + adapterType = adapterType.changeParameterType(pos, filterType.parameterType(0)); + adapter = MethodHandleImpl.filterArgument(IMPL_TOKEN, adapter, pos, filter); + } + MethodType midType = adapter.type(); + if (midType != adapterType) + adapter = MethodHandleImpl.convertArguments(IMPL_TOKEN, adapter, adapterType, midType, null); + return adapter; + } + + /** + * PROVISIONAL API, WORK IN PROGRESS: + * Adapt a target method handle {@code target} by pre-processing + * some of its arguments, and then calling the target with + * the result of the pre-processing, plus all original arguments. + *

    + * The pre-processing is performed by a second method handle, the {@code combiner}. + * The first {@code N} arguments passed to the adapter, + * are copied to the combiner, which then produces a result. + * (Here, {@code N} is defined as the parameter count of the adapter.) + * After this, control passes to the {@code target}, with both the result + * of the combiner, and all the original incoming arguments. + *

    + * The first argument type of the target must be identical with the + * return type of the combiner. + * The resulting adapter is the same type as the target, except that the + * initial argument type of the target is dropped. + *

    + * (Note that {@link #dropArguments} can be used to remove any arguments + * that either the {@code combiner} or {@code target} does not wish to receive. + * If some of the incoming arguments are destined only for the combiner, + * consider using {@link #collectArguments} instead, since those + * arguments will not need to be live on the stack on entry to the + * target.) + *

    + * The first argument of the target must be identical with the + * return value of the combiner. + *

    Here is pseudocode for the resulting adapter: + *

    +     * // there are N arguments in the A sequence
    +     * T target(V, A[N]..., B...);
    +     * V combiner(A...);
    +     * T adapter(A... a, B... b) {
    +     *   V v = combiner(a...);
    +     *   return target(v, a..., b...);
    +     * }
    +     * 
    + * @param target the method handle to invoke after arguments are combined + * @param combiner method handle to call initially on the incoming arguments + * @return method handle which incorporates the specified argument folding logic + * @throws IllegalArgumentException if the first argument type of + * {@code target} is not the same as {@code combiner}'s return type, + * or if the next {@code foldArgs} argument types of {@code target} + * are not identical with the argument types of {@code combiner} + */ + public static + MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) { + MethodType targetType = target.type(); + MethodType combinerType = combiner.type(); + int foldArgs = combinerType.parameterCount(); + boolean ok = (targetType.parameterCount() >= 1 + foldArgs); + if (!ok) + throw misMatchedTypes("target and combiner types", targetType, combinerType); + MethodType newType = targetType.dropParameterTypes(0, 1); + return MethodHandleImpl.foldArguments(IMPL_TOKEN, target, newType, combiner); + } + /** * PROVISIONAL API, WORK IN PROGRESS: * Make a method handle which adapts a target method handle, @@ -985,18 +1193,18 @@ * If the guard fails, a fallback handle is called instead. * All three method handles must have the same corresponding * argument and return types, except that the return type - * of the test must be boolean. + * of the test must be boolean, and the test is allowed + * to have fewer arguments than the other two method handles. *

    Here is pseudocode for the resulting adapter: *

    -     * signature T(A...);
          * boolean test(A...);
    -     * T target(A...);
    -     * T fallback(A...);
    -     * T adapter(A... a) {
    +     * T target(A...,B...);
    +     * T fallback(A...,B...);
    +     * T adapter(A... a,B... b) {
          *   if (test(a...))
    -     *     return target(a...);
    +     *     return target(a..., b...);
          *   else
    -     *     return fallback(a...);
    +     *     return fallback(a..., b...);
          * }
          * 
    * @param test method handle used for test, must return boolean @@ -1011,10 +1219,23 @@ MethodHandle guardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) { - if (target.type() != fallback.type()) - throw newIllegalArgumentException("target and fallback types do not match"); - if (target.type().changeReturnType(boolean.class) != test.type()) - throw newIllegalArgumentException("target and test types do not match"); + MethodType gtype = test.type(); + MethodType ttype = target.type(); + MethodType ftype = fallback.type(); + if (ttype != ftype) + throw misMatchedTypes("target and fallback types", ttype, ftype); + MethodType gtype2 = ttype.changeReturnType(boolean.class); + if (gtype2 != gtype) { + if (gtype.returnType() != boolean.class) + throw newIllegalArgumentException("guard type is not a predicate "+gtype); + int gpc = gtype.parameterCount(), tpc = ttype.parameterCount(); + if (gpc < tpc) { + test = dropArguments(test, gpc, ttype.parameterList().subList(gpc, tpc)); + gtype = test.type(); + } + if (gtype2 != gtype) + throw misMatchedTypes("target and test types", ttype, gtype); + } /* { MethodHandle invoke = findVirtual(MethodHandle.class, "invoke", target.type()); static MethodHandle choose(boolean z, MethodHandle t, MethodHandle f) { @@ -1027,7 +1248,7 @@ } // choose = \z.(z ? target : fallback) MethodHandle choose = findVirtual(MethodHandles.class, "choose", - MethodType.make(boolean.class, MethodHandle.class, MethodHandle.class)); + MethodType.methodType(boolean.class, MethodHandle.class, MethodHandle.class)); choose = appendArgument(choose, target); choose = appendArgument(choose, fallback); MethodHandle dispatch = compose(choose, test); @@ -1038,67 +1259,88 @@ return MethodHandleImpl.makeGuardWithTest(IMPL_TOKEN, test, target, fallback); } + static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) { + return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2); + } + /** * PROVISIONAL API, WORK IN PROGRESS: - * Adapt a target method handle {@code target} by first processing - * its arguments, and then calling the target. - * The initial processing is performed by a second method handle, the {@code combiner}. - * After this, control passes to the {@code target}, with the same arguments. + * Make a method handle which adapts a target method handle, + * by running it inside an exception handler. + * If the target returns normally, the adapter returns that value. + * If an exception matching the specified type is thrown, the fallback + * handle is called instead on the exception, plus the original arguments. *

    - * The return value of the {@code combiner} is inserted into the argument list - * for the {@code target} at the indicated position {@code pos}, if it is non-negative. - * Except for this inserted argument (if any), the argument types of - * the target {@code target} and the {@code combiner} must be identical. - *

    - * (Note that {@link #dropArguments} can be used to remove any arguments - * that either the {@code combiner} or {@code target} does not wish to receive.) - *

    - * The combiner handle must have the same argument types as the - * target handle, but must return {@link MethodHandle} instead of - * the ultimate return type. The returned method handle, in turn, - * is required to have exactly the given final method type. + * The handler must have leading parameter of {@code exType} or a supertype, + * followed by arguments which correspond (how? TBD) to + * all the parameters of the target. + * The target and handler must return the same type. *

    Here is pseudocode for the resulting adapter: *

    -     * signature V(A[pos]..., B...);
    -     * signature T(A[pos]..., V, B...);
    -     * T target(A... a, V v, B... b);
    -     * V combiner(A..., B...);
    -     * T adapter(A... a, B... b) {
    -     *   V v = combiner(a..., b...);
    -     *   return target(a..., v, b...);
    +     * T target(A...);
    +     * T handler(ExType, A...);
    +     * T adapter(A... a) {
    +     *   try {
    +     *     return target(a...);
    +     *   } catch (ExType ex) {
    +     *     return handler(ex, a...);
    +     *   }
          * }
          * 
    - * @param target the method handle to invoke after arguments are combined - * @param pos where the return value of {@code combiner} is to - * be inserted as an argument to {@code target} - * @param combiner method handle to call initially on the incoming arguments - * @return method handle which incorporates the specified dispatch logic - * @throws IllegalArgumentException if {@code combiner} does not itself - * return either void or the {@code pos}-th argument of {@code target}, - * or does not have the same argument types as {@code target} - * (minus the inserted argument) + * @param target method handle to call + * @param exType the type of exception which the handler will catch + * @param handler method handle to call if a matching exception is thrown + * @return method handle which incorporates the specified try/catch logic + * @throws IllegalArgumentException if {@code handler} does not accept + * the given exception type, or if the method handle types do + * not match in their return types and their + * corresponding parameters */ public static - MethodHandle combineArguments(MethodHandle target, int pos, MethodHandle combiner) { - MethodType mhType = target.type(); - Class combineType = combiner.type().returnType(); - MethodType incomingArgs; - if (pos < 0) { - // No inserted argument; target & combiner must have same argument types. - incomingArgs = mhType; - if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) - throw newIllegalArgumentException("target and combiner types do not match"); - } else { - // Inserted argument. - if (pos >= mhType.parameterCount() - || mhType.parameterType(pos) != combineType) - throw newIllegalArgumentException("inserted combiner argument does not match target"); - incomingArgs = mhType.dropParameterType(pos); - } - if (!incomingArgs.changeReturnType(combineType).equals(combiner.type())) { - throw newIllegalArgumentException("target and combiner types do not match"); - } - return MethodHandleImpl.combineArguments(IMPL_TOKEN, target, combiner, pos); + MethodHandle catchException(MethodHandle target, + Class exType, + MethodHandle handler) { + MethodType targetType = target.type(); + MethodType handlerType = handler.type(); + boolean ok = (targetType.parameterCount() == + handlerType.parameterCount() - 1); +// for (int i = 0; ok && i < numExArgs; i++) { +// if (targetType.parameterType(i) != handlerType.parameterType(1+i)) +// ok = false; +// } + if (!ok) + throw newIllegalArgumentException("target and handler types do not match"); + return MethodHandleImpl.makeGuardWithCatch(IMPL_TOKEN, target, exType, handler); } + /** + * Produce a method handle which will throw exceptions of the given {@code exType}. + * The method handle will accept a single argument of {@code exType}, + * and immediately throw it as an exception. + * The method type will nominally specify a return of {@code returnType}. + * The return type may be anything convenient: It doesn't matter to the + * method handle's behavior, since it will never return normally. + */ + public static + MethodHandle throwException(Class returnType, Class exType) { + return MethodHandleImpl.throwException(IMPL_TOKEN, MethodType.methodType(returnType, exType)); + } + + /** Alias for {@link MethodType#methodType}. */ + @Deprecated // "use MethodType.methodType instead" + public static MethodType methodType(Class rtype) { + return MethodType.methodType(rtype); + } + + /** Alias for {@link MethodType#methodType}. */ + @Deprecated // "use MethodType.methodType instead" + public static MethodType methodType(Class rtype, Class ptype) { + return MethodType.methodType(rtype, ptype); + } + + /** Alias for {@link MethodType#methodType}. */ + @Deprecated // "use MethodType.methodType instead" + public static MethodType methodType(Class rtype, Class ptype0, Class... ptypes) { + return MethodType.methodType(rtype, ptype0, ptypes); + } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/MethodType.java --- a/jdk/src/share/classes/java/dyn/MethodType.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/MethodType.java Wed Jul 05 17:05:01 2017 +0200 @@ -32,7 +32,7 @@ import sun.dyn.Access; import sun.dyn.Invokers; import sun.dyn.MethodTypeImpl; -import sun.dyn.util.BytecodeSignature; +import sun.dyn.util.BytecodeDescriptor; import static sun.dyn.MemberName.newIllegalArgumentException; /** @@ -63,7 +63,7 @@ static { // This hack allows the implementation package special access to - // the internals of MethodType. In particular, the Form has all sorts + // the internals of MethodType. In particular, the MTImpl has all sorts // of cached information useful to the implementation code. MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() { public Class[] ptypes(MethodType mt) { return mt.ptypes; } @@ -114,50 +114,75 @@ * @throws IllegalArgumentException if any of the ptypes is void */ public static + MethodType methodType(Class rtype, Class[] ptypes) { + return makeImpl(rtype, ptypes, false); + } + @Deprecated public static MethodType make(Class rtype, Class[] ptypes) { - return makeImpl(rtype, ptypes, false); + return methodType(rtype, ptypes); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. */ + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */ public static + MethodType methodType(Class rtype, List> ptypes) { + boolean notrust = false; // random List impl. could return evil ptypes array + return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust); + } + @Deprecated public static MethodType make(Class rtype, List> ptypes) { - return makeImpl(rtype, ptypes.toArray(NO_PTYPES), true); + return methodType(rtype, ptypes); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The leading parameter type is prepended to the remaining array. */ public static - MethodType make(Class rtype, Class ptype0, Class... ptypes) { + MethodType methodType(Class rtype, Class ptype0, Class... ptypes) { Class[] ptypes1 = new Class[1+ptypes.length]; ptypes1[0] = ptype0; System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length); return makeImpl(rtype, ptypes1, true); } + @Deprecated public static + MethodType make(Class rtype, Class ptype0, Class... ptypes) { + return methodType(rtype, ptype0, ptypes); + } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The resulting method has no parameter types. */ public static - MethodType make(Class rtype) { + MethodType methodType(Class rtype) { return makeImpl(rtype, NO_PTYPES, true); } + @Deprecated public static + MethodType make(Class rtype) { + return methodType(rtype); + } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The resulting method has the single given parameter type. */ public static - MethodType make(Class rtype, Class ptype0) { + MethodType methodType(Class rtype, Class ptype0) { return makeImpl(rtype, new Class[]{ ptype0 }, true); } + @Deprecated public static + MethodType make(Class rtype, Class ptype0) { + return methodType(rtype, ptype0); + } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * The resulting method has the same parameter types as {@code ptypes}, * and the specified return type. */ public static + MethodType methodType(Class rtype, MethodType ptypes) { + return makeImpl(rtype, ptypes.ptypes, true); + } + @Deprecated public static MethodType make(Class rtype, MethodType ptypes) { - return makeImpl(rtype, ptypes.ptypes, true); + return methodType(rtype, ptypes); } /** @@ -202,15 +227,16 @@ private static final MethodType[] objectOnlyTypes = new MethodType[20]; /** - * Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. - * All parameters and the return type will be Object, except the final varargs parameter if any. + * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. + * All parameters and the return type will be {@code Object}, + * except the final varargs parameter if any, which will be {@code Object[]}. * @param objectArgCount number of parameters (excluding the varargs parameter if any) - * @param varargs whether there will be a varargs parameter, of type Object[] + * @param varargs whether there will be a varargs parameter, of type {@code Object[]} * @return a totally generic method type, given only its count of parameters and varargs - * @see #makeGeneric(int) + * @see #genericMethodType(int) */ public static - MethodType makeGeneric(int objectArgCount, boolean varargs) { + MethodType genericMethodType(int objectArgCount, boolean varargs) { MethodType mt; int ivarargs = (!varargs ? 0 : 1); int ootIndex = objectArgCount*2 + ivarargs; @@ -227,19 +253,27 @@ } return mt; } + @Deprecated public static + MethodType makeGeneric(int objectArgCount, boolean varargs) { + return genericMethodType(objectArgCount, varargs); + } /** * All parameters and the return type will be Object. * @param objectArgCount number of parameters * @return a totally generic method type, given only its count of parameters - * @see #makeGeneric(int, boolean) + * @see #genericMethodType(int, boolean) */ public static + MethodType genericMethodType(int objectArgCount) { + return genericMethodType(objectArgCount, false); + } + @Deprecated public static MethodType makeGeneric(int objectArgCount) { - return makeGeneric(objectArgCount, false); + return genericMethodType(objectArgCount); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * @param num the index (zero-based) of the parameter type to change * @param nptype a new parameter type to replace the old one with * @return the same type, except with the selected parameter changed @@ -251,11 +285,10 @@ return makeImpl(rtype, nptypes, true); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. - * @param num the position (zero-based) of the inserted parameter type - * @param nptype a new parameter type to insert into the parameter list - * @return the same type, except with the selected parameter inserted + /** Convenience method for {@link #insertParameterTypes}. + * @deprecated Use {@link #insertParameterTypes} instead. */ + @Deprecated public MethodType insertParameterType(int num, Class nptype) { int len = ptypes.length; Class[] nptypes = Arrays.copyOfRange(ptypes, 0, len+1); @@ -264,23 +297,73 @@ return makeImpl(rtype, nptypes, true); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. - * @param num the index (zero-based) of the parameter type to remove - * @return the same type, except with the selected parameter removed + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. + * @param num the position (zero-based) of the inserted parameter type(s) + * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list + * @return the same type, except with the selected parameter(s) inserted */ - public MethodType dropParameterType(int num) { + public MethodType insertParameterTypes(int num, Class... ptypesToInsert) { int len = ptypes.length; + if (num < 0 || num > len) + throw newIllegalArgumentException("num="+num); //SPECME + int ilen = ptypesToInsert.length; + if (ilen == 0) return this; + Class[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen); + System.arraycopy(nptypes, num, nptypes, num+ilen, len-num); + System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen); + return makeImpl(rtype, nptypes, true); + } + + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. + * @param num the position (zero-based) of the inserted parameter type(s) + * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list + * @return the same type, except with the selected parameter(s) inserted + */ + public MethodType insertParameterTypes(int num, List> ptypesToInsert) { + return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES)); + } + + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. + * @param start the index (zero-based) of the first parameter type to remove + * @param end the index (greater than {@code start}) of the first parameter type after not to remove + * @return the same type, except with the selected parameter(s) removed + */ + public MethodType dropParameterTypes(int start, int end) { + int len = ptypes.length; + if (!(0 <= start && start <= end && end <= len)) + throw newIllegalArgumentException("start="+start+" end="+end); //SPECME + if (start == end) return this; Class[] nptypes; - if (num == 0) { - nptypes = Arrays.copyOfRange(ptypes, 1, len); + if (start == 0) { + if (end == len) { + // drop all parameters + nptypes = NO_PTYPES; + } else { + // drop initial parameter(s) + nptypes = Arrays.copyOfRange(ptypes, end, len); + } } else { - nptypes = Arrays.copyOfRange(ptypes, 0, len-1); - System.arraycopy(ptypes, num+1, nptypes, num, (len-1)-num); + if (end == len) { + // drop trailing parameter(s) + nptypes = Arrays.copyOfRange(ptypes, 0, start); + } else { + int tail = len - end; + nptypes = Arrays.copyOfRange(ptypes, 0, start + tail); + System.arraycopy(ptypes, end, nptypes, start, tail); + } } return makeImpl(rtype, nptypes, true); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[], boolean)}. + /** Convenience method for {@link #dropParameterTypes}. + * @deprecated Use {@link #dropParameterTypes} instead. + */ + @Deprecated + public MethodType dropParameterType(int num) { + return dropParameterTypes(num, num+1); + } + + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * @param nrtype a return parameter type to replace the old one with * @return the same type, except with the return type change */ @@ -291,6 +374,7 @@ /** Convenience method. * Report if this type contains a primitive argument or return value. + * The return type {@code void} counts as a primitive. * @return true if any of the types are primitives */ public boolean hasPrimitives() { @@ -300,39 +384,47 @@ /** Convenience method. * Report if this type contains a wrapper argument or return value. * Wrappers are types which box primitive values, such as {@link Integer}. + * The reference type {@code java.lang.Void} counts as a wrapper. * @return true if any of the types are wrappers */ public boolean hasWrappers() { return unwrap() != this; } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. - * Erase all reference types to Object. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. + * Erase all reference types to {@code Object}. + * All primitive types (including {@code void}) will remain unchanged. * @return a version of the original type with all reference types replaced */ public MethodType erase() { return form.erasedType(); } - /** Convenience method for {@link #makeGeneric(int)}. - * Convert all types, both reference and primitive, to Object. + /** Convenience method for {@link #genericMethodType(int)}. + * Convert all types, both reference and primitive, to {@code Object}. + * The expression {@code type.wrap().erase()} produces the same value + * as {@code type.generic()}. * @return a version of the original type with all types replaced */ public MethodType generic() { - return makeGeneric(parameterCount()); + return genericMethodType(parameterCount()); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * Convert all primitive types to their corresponding wrapper types. + * All reference types (including wrapper types) will remain unchanged. * A {@code void} return type is changed to the type {@code java.lang.Void}. + * The expression {@code type.wrap().erase()} produces the same value + * as {@code type.generic()}. * @return a version of the original type with all primitive types replaced */ public MethodType wrap() { return hasPrimitives() ? wrapWithPrims(this) : this; } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * Convert all wrapper types to their corresponding primitive types. + * All primitive types (including {@code void}) will remain unchanged. * A return type of {@code java.lang.Void} is changed to {@code void}. * @return a version of the original type with all wrapper types replaced */ @@ -391,6 +483,7 @@ /** * Convenience method to present the arguments as an array. + * Changes to the array will not result in changes to the type. * @return the parameter types (as a fresh copy if necessary) */ public Class[] parameterArray() { @@ -491,7 +584,7 @@ return form.parameterSlotCount(); } - /** Number of JVM stack slots which carry all parameters after + /** Number of JVM stack slots which carry all parameters including and after * the given position, which must be in the range of 0 to * {@code parameterCount} inclusive. Successive parameters are * more shallowly stacked, and parameters are indexed in the bytecodes @@ -532,7 +625,7 @@ return form.returnSlotCount(); } - /** Convenience method for {@link #make(java.lang.Class, java.lang.Class[])}. + /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. * Find or create an instance (interned) of the given method type. * Any class or interface name embedded in the signature string * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)} @@ -544,16 +637,16 @@ *

    * This method is included for the benfit of applications that must * generate bytecodes that process method handles and invokedynamic. - * @param bytecodeSignature a bytecode-level signature string "(T...)T" + * @param descriptor a bytecode-level signature string "(T...)T" * @param loader the class loader in which to look up the types * @return a method type matching the bytecode-level signature * @throws IllegalArgumentException if the string is not well-formed * @throws TypeNotPresentException if a named type cannot be found */ - public static MethodType fromBytecodeString(String bytecodeSignature, ClassLoader loader) + public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader) throws IllegalArgumentException, TypeNotPresentException { - List> types = BytecodeSignature.parseMethod(bytecodeSignature, loader); + List> types = BytecodeDescriptor.parseMethod(descriptor, loader); Class rtype = types.remove(types.size() - 1); Class[] ptypes = types.toArray(NO_PTYPES); return makeImpl(rtype, ptypes, true); @@ -565,11 +658,21 @@ *

    * This method is included for the benfit of applications that must * generate bytecodes that process method handles and invokedynamic. - * {@link #fromBytecodeString(java.lang.String, java.lang.ClassLoader)}, + * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader)}, * because the latter requires a suitable class loader argument. * @return the bytecode signature representation */ + public String toMethodDescriptorString() { + return BytecodeDescriptor.unparse(this); + } + + /** Temporary alias for toMethodDescriptorString; delete after M3. */ public String toBytecodeString() { - return BytecodeSignature.unparse(this); + return toMethodDescriptorString(); + } + /** Temporary alias for fromMethodDescriptorString; delete after M3. */ + public static MethodType fromBytecodeString(String descriptor, ClassLoader loader) + throws IllegalArgumentException, TypeNotPresentException { + return fromMethodDescriptorString(descriptor, loader); } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/dyn/package-info.java --- a/jdk/src/share/classes/java/dyn/package-info.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/dyn/package-info.java Wed Jul 05 17:05:01 2017 +0200 @@ -24,6 +24,7 @@ */ /** + * PROVISIONAL API, WORK IN PROGRESS: * This package contains dynamic language support provided directly by * the Java core class libraries and virtual machine. * @author John Rose, JSR 292 EG diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/lang/StrictMath.java --- a/jdk/src/share/classes/java/lang/StrictMath.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/lang/StrictMath.java Wed Jul 05 17:05:01 2017 +0200 @@ -26,6 +26,7 @@ package java.lang; import java.util.Random; import sun.misc.FpUtils; +import sun.misc.DoubleConsts; /** * The class {@code StrictMath} contains methods for performing basic @@ -316,7 +317,9 @@ * floating-point value that is greater than or equal to * the argument and is equal to a mathematical integer. */ - public static native double ceil(double a); + public static double ceil(double a) { + return floorOrCeil(a, -0.0, 1.0, 1.0); + } /** * Returns the largest (closest to positive infinity) @@ -333,7 +336,54 @@ * floating-point value that less than or equal to the argument * and is equal to a mathematical integer. */ - public static native double floor(double a); + public static double floor(double a) { + return floorOrCeil(a, -1.0, 0.0, -1.0); + } + + /** + * Internal method to share logic between floor and ceil. + * + * @param a the value to be floored or ceiled + * @param negativeBoundary result for values in (-1, 0) + * @param positiveBoundary result for values in (0, 1) + * @param increment value to add when the argument is non-integral + */ + private static double floorOrCeil(double a, + double negativeBoundary, + double positiveBoundary, + double sign) { + int exponent = Math.getExponent(a); + + if (exponent < 0) { + /* + * Absolute value of argument is less than 1. + * floorOrceil(-0.0) => -0.0 + * floorOrceil(+0.0) => +0.0 + */ + return ((a == 0.0) ? a : + ( (a < 0.0) ? negativeBoundary : positiveBoundary) ); + } else if (exponent >= 52) { + /* + * Infinity, NaN, or a value so large it must be integral. + */ + return a; + } + // Else the argument is either an integral value already XOR it + // has to be rounded to one. + assert exponent >= 0 && exponent <= 51; + + long doppel = Double.doubleToRawLongBits(a); + long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent; + + if ( (mask & doppel) == 0L ) + return a; // integral value + else { + double result = Double.longBitsToDouble(doppel & (~mask)); + if (sign*a > 0.0) + result = result + sign; + return result; + } + } /** * Returns the {@code double} value that is closest in value diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/lang/management/PlatformManagedObject.java --- a/jdk/src/share/classes/java/lang/management/PlatformManagedObject.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/lang/management/PlatformManagedObject.java Wed Jul 05 17:05:01 2017 +0200 @@ -32,7 +32,7 @@ * for monitoring and managing a component in the Java platform. * Each platform managed object has a unique * object name - * for the {@linkplain ManagementFactory.getPlatformMBeanServer + * for the {@linkplain ManagementFactory#getPlatformMBeanServer * platform MBeanServer} access. * All platform MXBeans will implement this interface. * diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/nio/X-Buffer.java.template --- a/jdk/src/share/classes/java/nio/X-Buffer.java.template Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/nio/X-Buffer.java.template Wed Jul 05 17:05:01 2017 +0200 @@ -32,24 +32,24 @@ #end[char] /** - * $A$ $fulltype$ buffer. + * $A$ $type$ buffer. * *

    This class defines {#if[byte]?six:four} categories of operations upon - * $fulltype$ buffers: + * $type$ buffers: * *

      * *
    • Absolute and relative {@link #get() get} and * {@link #put($type$) put} methods that read and write - * single $fulltype$s;

    • + * single $type$s;

      * *
    • Relative {@link #get($type$[]) bulk get} - * methods that transfer contiguous sequences of $fulltype$s from this buffer + * methods that transfer contiguous sequences of $type$s from this buffer * into an array; {#if[!byte]?and}

    • * *
    • Relative {@link #put($type$[]) bulk put} - * methods that transfer contiguous sequences of $fulltype$s from $a$ - * $fulltype$ array{#if[char]?, a string,} or some other $fulltype$ + * methods that transfer contiguous sequences of $type$s from $a$ + * $type$ array{#if[char]?, a string,} or some other $type$ * buffer into this buffer;{#if[!byte]? and}

    • * #if[byte] @@ -67,22 +67,22 @@ * *
    • Methods for {@link #compact compacting}, {@link * #duplicate duplicating}, and {@link #slice - * slicing} $a$ $fulltype$ buffer.

    • + * slicing} $a$ $type$ buffer.

      * *
    * - *

    $Fulltype$ buffers can be created either by {@link #allocate + *

    $Type$ buffers can be created either by {@link #allocate * allocation}, which allocates space for the buffer's * #if[byte] * * content, or by {@link #wrap($type$[]) wrapping} an - * existing $fulltype$ array {#if[char]?or string} into a buffer. + * existing $type$ array {#if[char]?or string} into a buffer. * #else[byte] * * content, by {@link #wrap($type$[]) wrapping} an existing - * $fulltype$ array {#if[char]?or string} into a buffer, or by creating a + * $type$ array {#if[char]?or string} into a buffer, or by creating a * view of an existing byte buffer. * #end[byte] @@ -189,12 +189,12 @@ * #if[!byte] * - *

    Like a byte buffer, $a$ $fulltype$ buffer is either Like a byte buffer, $a$ $type$ buffer is either direct or non-direct. A - * $fulltype$ buffer created via the wrap methods of this class will - * be non-direct. $A$ $fulltype$ buffer created as a view of a byte buffer will + * $type$ buffer created via the wrap methods of this class will + * be non-direct. $A$ $type$ buffer created as a view of a byte buffer will * be direct if, and only if, the byte buffer itself is direct. Whether or not - * $a$ $fulltype$ buffer is direct may be determined by invoking the {@link + * $a$ $type$ buffer is direct may be determined by invoking the {@link * #isDirect isDirect} method.

    * #end[!byte] @@ -287,7 +287,7 @@ #if[byte] /** - * Allocates a new direct $fulltype$ buffer. + * Allocates a new direct $type$ buffer. * *

    The new buffer's position will be zero, its limit will be its * capacity, its mark will be undefined, and each of its elements will be @@ -295,9 +295,9 @@ * {@link #hasArray backing array} is unspecified. * * @param capacity - * The new buffer's capacity, in $fulltype$s + * The new buffer's capacity, in $type$s * - * @return The new $fulltype$ buffer + * @return The new $type$ buffer * * @throws IllegalArgumentException * If the capacity is a negative integer @@ -309,7 +309,7 @@ #end[byte] /** - * Allocates a new $fulltype$ buffer. + * Allocates a new $type$ buffer. * *

    The new buffer's position will be zero, its limit will be its * capacity, its mark will be undefined, and each of its elements will be @@ -318,9 +318,9 @@ * offset} will be zero. * * @param capacity - * The new buffer's capacity, in $fulltype$s + * The new buffer's capacity, in $type$s * - * @return The new $fulltype$ buffer + * @return The new $type$ buffer * * @throws IllegalArgumentException * If the capacity is a negative integer @@ -332,9 +332,9 @@ } /** - * Wraps $a$ $fulltype$ array into a buffer. + * Wraps $a$ $type$ array into a buffer. * - *

    The new buffer will be backed by the given $fulltype$ array; + *

    The new buffer will be backed by the given $type$ array; * that is, modifications to the buffer will cause the array to be modified * and vice versa. The new buffer's capacity will be * array.length, its position will be offset, its limit @@ -356,7 +356,7 @@ * array.length - offset. * The new buffer's limit will be set to offset + length. * - * @return The new $fulltype$ buffer + * @return The new $type$ buffer * * @throws IndexOutOfBoundsException * If the preconditions on the offset and length @@ -373,9 +373,9 @@ } /** - * Wraps $a$ $fulltype$ array into a buffer. + * Wraps $a$ $type$ array into a buffer. * - *

    The new buffer will be backed by the given $fulltype$ array; + *

    The new buffer will be backed by the given $type$ array; * that is, modifications to the buffer will cause the array to be modified * and vice versa. The new buffer's capacity and limit will be * array.length, its position will be zero, and its mark will be @@ -386,7 +386,7 @@ * @param array * The array that will back this buffer * - * @return The new $fulltype$ buffer + * @return The new $type$ buffer */ public static $Type$Buffer wrap($type$[] array) { return wrap(array, 0, array.length); @@ -486,7 +486,7 @@ #end[char] /** - * Creates a new $fulltype$ buffer whose content is a shared subsequence of + * Creates a new $type$ buffer whose content is a shared subsequence of * this buffer's content. * *

    The content of the new buffer will start at this buffer's current @@ -495,17 +495,17 @@ * values will be independent. * *

    The new buffer's position will be zero, its capacity and its limit - * will be the number of $fulltype$s remaining in this buffer, and its mark + * will be the number of $type$s remaining in this buffer, and its mark * will be undefined. The new buffer will be direct if, and only if, this * buffer is direct, and it will be read-only if, and only if, this buffer * is read-only.

    * - * @return The new $fulltype$ buffer + * @return The new $type$ buffer */ public abstract $Type$Buffer slice(); /** - * Creates a new $fulltype$ buffer that shares this buffer's content. + * Creates a new $type$ buffer that shares this buffer's content. * *

    The content of the new buffer will be that of this buffer. Changes * to this buffer's content will be visible in the new buffer, and vice @@ -517,12 +517,12 @@ * and only if, this buffer is direct, and it will be read-only if, and * only if, this buffer is read-only.

    * - * @return The new $fulltype$ buffer + * @return The new $type$ buffer */ public abstract $Type$Buffer duplicate(); /** - * Creates a new, read-only $fulltype$ buffer that shares this buffer's + * Creates a new, read-only $type$ buffer that shares this buffer's * content. * *

    The content of the new buffer will be that of this buffer. Changes @@ -537,7 +537,7 @@ *

    If this buffer is itself read-only then this method behaves in * exactly the same way as the {@link #duplicate duplicate} method.

    * - * @return The new, read-only $fulltype$ buffer + * @return The new, read-only $type$ buffer */ public abstract $Type$Buffer asReadOnlyBuffer(); @@ -545,10 +545,10 @@ // -- Singleton get/put methods -- /** - * Relative get method. Reads the $fulltype$ at this buffer's + * Relative get method. Reads the $type$ at this buffer's * current position, and then increments the position.

    * - * @return The $fulltype$ at the buffer's current position + * @return The $type$ at the buffer's current position * * @throws BufferUnderflowException * If the buffer's current position is not smaller than its limit @@ -558,11 +558,11 @@ /** * Relative put method  (optional operation). * - *

    Writes the given $fulltype$ into this buffer at the current + *

    Writes the given $type$ into this buffer at the current * position, and then increments the position.

    * * @param $x$ - * The $fulltype$ to be written + * The $type$ to be written * * @return This buffer * @@ -575,13 +575,13 @@ public abstract $Type$Buffer put($type$ $x$); /** - * Absolute get method. Reads the $fulltype$ at the given + * Absolute get method. Reads the $type$ at the given * index.

    * * @param index - * The index from which the $fulltype$ will be read + * The index from which the $type$ will be read * - * @return The $fulltype$ at the given index + * @return The $type$ at the given index * * @throws IndexOutOfBoundsException * If index is negative @@ -592,14 +592,14 @@ /** * Absolute put method  (optional operation). * - *

    Writes the given $fulltype$ into this buffer at the given + *

    Writes the given $type$ into this buffer at the given * index.

    * * @param index - * The index at which the $fulltype$ will be written + * The index at which the $type$ will be written * * @param $x$ - * The $fulltype$ value to be written + * The $type$ value to be written * * @return This buffer * @@ -618,14 +618,14 @@ /** * Relative bulk get method. * - *

    This method transfers $fulltype$s from this buffer into the given - * destination array. If there are fewer $fulltype$s remaining in the + *

    This method transfers $type$s from this buffer into the given + * destination array. If there are fewer $type$s remaining in the * buffer than are required to satisfy the request, that is, if * length > remaining(), then no - * $fulltype$s are transferred and a {@link BufferUnderflowException} is + * $type$s are transferred and a {@link BufferUnderflowException} is * thrown. * - *

    Otherwise, this method copies length $fulltype$s from this + *

    Otherwise, this method copies length $type$s from this * buffer into the given array, starting at the current position of this * buffer and at the given offset in the array. The position of this * buffer is then incremented by length. @@ -638,26 +638,26 @@ * for (int i = off; i < off + len; i++) * dst[i] = src.get(); * - * except that it first checks that there are sufficient $fulltype$s in + * except that it first checks that there are sufficient $type$s in * this buffer and it is potentially much more efficient.

    * * @param dst - * The array into which $fulltype$s are to be written + * The array into which $type$s are to be written * * @param offset - * The offset within the array of the first $fulltype$ to be + * The offset within the array of the first $type$ to be * written; must be non-negative and no larger than * dst.length * * @param length - * The maximum number of $fulltype$s to be written to the given + * The maximum number of $type$s to be written to the given * array; must be non-negative and no larger than * dst.length - offset * * @return This buffer * * @throws BufferUnderflowException - * If there are fewer than length $fulltype$s + * If there are fewer than length $type$s * remaining in this buffer * * @throws IndexOutOfBoundsException @@ -677,7 +677,7 @@ /** * Relative bulk get method. * - *

    This method transfers $fulltype$s from this buffer into the given + *

    This method transfers $type$s from this buffer into the given * destination array. An invocation of this method of the form * src.get(a) behaves in exactly the same way as the invocation * @@ -687,7 +687,7 @@ * @return This buffer * * @throws BufferUnderflowException - * If there are fewer than length $fulltype$s + * If there are fewer than length $type$s * remaining in this buffer */ public $Type$Buffer get($type$[] dst) { @@ -700,15 +700,15 @@ /** * Relative bulk put method  (optional operation). * - *

    This method transfers the $fulltype$s remaining in the given source - * buffer into this buffer. If there are more $fulltype$s remaining in the + *

    This method transfers the $type$s remaining in the given source + * buffer into this buffer. If there are more $type$s remaining in the * source buffer than in this buffer, that is, if * src.remaining() > remaining(), - * then no $fulltype$s are transferred and a {@link + * then no $type$s are transferred and a {@link * BufferOverflowException} is thrown. * *

    Otherwise, this method copies - * n = src.remaining() $fulltype$s from the given + * n = src.remaining() $type$s from the given * buffer into this buffer, starting at each buffer's current position. * The positions of both buffers are then incremented by n. * @@ -723,14 +723,14 @@ * buffer and it is potentially much more efficient.

    * * @param src - * The source buffer from which $fulltype$s are to be read; + * The source buffer from which $type$s are to be read; * must not be this buffer * * @return This buffer * * @throws BufferOverflowException * If there is insufficient space in this buffer - * for the remaining $fulltype$s in the source buffer + * for the remaining $type$s in the source buffer * * @throws IllegalArgumentException * If the source buffer is this buffer @@ -752,14 +752,14 @@ /** * Relative bulk put method  (optional operation). * - *

    This method transfers $fulltype$s into this buffer from the given - * source array. If there are more $fulltype$s to be copied from the array + *

    This method transfers $type$s into this buffer from the given + * source array. If there are more $type$s to be copied from the array * than remain in this buffer, that is, if * length > remaining(), then no - * $fulltype$s are transferred and a {@link BufferOverflowException} is + * $type$s are transferred and a {@link BufferOverflowException} is * thrown. * - *

    Otherwise, this method copies length $fulltype$s from the + *

    Otherwise, this method copies length $type$s from the * given array into this buffer, starting at the given offset in the array * and at the current position of this buffer. The position of this buffer * is then incremented by length. @@ -776,14 +776,14 @@ * buffer and it is potentially much more efficient.

    * * @param src - * The array from which $fulltype$s are to be read + * The array from which $type$s are to be read * * @param offset - * The offset within the array of the first $fulltype$ to be read; + * The offset within the array of the first $type$ to be read; * must be non-negative and no larger than array.length * * @param length - * The number of $fulltype$s to be read from the given array; + * The number of $type$s to be read from the given array; * must be non-negative and no larger than * array.length - offset * @@ -813,7 +813,7 @@ * Relative bulk put method  (optional operation). * *

    This method transfers the entire content of the given source - * $fulltype$ array into this buffer. An invocation of this method of the + * $type$ array into this buffer. An invocation of this method of the * form dst.put(a) behaves in exactly the same way as the * invocation * @@ -837,15 +837,15 @@ /** * Relative bulk put method  (optional operation). * - *

    This method transfers $fulltype$s from the given string into this - * buffer. If there are more $fulltype$s to be copied from the string than + *

    This method transfers $type$s from the given string into this + * buffer. If there are more $type$s to be copied from the string than * remain in this buffer, that is, if * end - start > remaining(), - * then no $fulltype$s are transferred and a {@link + * then no $type$s are transferred and a {@link * BufferOverflowException} is thrown. * *

    Otherwise, this method copies - * n = end - start $fulltype$s + * n = end - start $type$s * from the given string into this buffer, starting at the given * start index and at the current position of this buffer. The * position of this buffer is then incremented by n. @@ -862,15 +862,15 @@ * buffer and it is potentially much more efficient.

    * * @param src - * The string from which $fulltype$s are to be read + * The string from which $type$s are to be read * * @param start - * The offset within the string of the first $fulltype$ to be read; + * The offset within the string of the first $type$ to be read; * must be non-negative and no larger than * string.length() * * @param end - * The offset within the string of the last $fulltype$ to be read, + * The offset within the string of the last $type$ to be read, * plus one; must be non-negative and no larger than * string.length() * @@ -921,7 +921,7 @@ // -- Other stuff -- /** - * Tells whether or not this buffer is backed by an accessible $fulltype$ + * Tells whether or not this buffer is backed by an accessible $type$ * array. * *

    If this method returns true then the {@link #array() array} @@ -936,7 +936,7 @@ } /** - * Returns the $fulltype$ array that backs this + * Returns the $type$ array that backs this * buffer  (optional operation). * *

    Modifications to this buffer's content will cause the returned @@ -993,17 +993,17 @@ /** * Compacts this buffer  (optional operation). * - *

    The $fulltype$s between the buffer's current position and its limit, + *

    The $type$s between the buffer's current position and its limit, * if any, are copied to the beginning of the buffer. That is, the - * $fulltype$ at index p = position() is copied - * to index zero, the $fulltype$ at index p + 1 is copied - * to index one, and so forth until the $fulltype$ at index + * $type$ at index p = position() is copied + * to index zero, the $type$ at index p + 1 is copied + * to index one, and so forth until the $type$ at index * limit() - 1 is copied to index * n = limit() - 1 - p. * The buffer's position is then set to n+1 and its limit is set to * its capacity. The mark, if defined, is discarded. * - *

    The buffer's position is set to the number of $fulltype$s copied, + *

    The buffer's position is set to the number of $type$s copied, * rather than to zero, so that an invocation of this method can be * followed immediately by an invocation of another relative put * method.

    @@ -1032,7 +1032,7 @@ public abstract $Type$Buffer compact(); /** - * Tells whether or not this $fulltype$ buffer is direct.

    + * Tells whether or not this $type$ buffer is direct.

    * * @return true if, and only if, this buffer is direct */ @@ -1098,6 +1098,13 @@ * *
  • The two sequences of remaining elements, considered * independently of their starting positions, are pointwise equal. +#if[floatingPointType] + * This method considers two $type$ elements {@code a} and {@code b} + * to be equal if + * {@code (a == b) || ($Fulltype$.isNaN(a) && $Fulltype$.isNaN(b))}. + * The values {@code -0.0} and {@code +0.0} are considered to be + * equal, unlike {@link $Fulltype$#equals(Object)}. +#end[floatingPointType] *

  • * * @@ -1118,24 +1125,37 @@ if (this.remaining() != that.remaining()) return false; int p = this.position(); - for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) { - $type$ v1 = this.get(i); - $type$ v2 = that.get(j); - if (v1 != v2) { - if ((v1 != v1) && (v2 != v2)) // For float and double - continue; + for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) + if (!equals(this.get(i), that.get(j))) return false; - } - } return true; } + private static boolean equals($type$ x, $type$ y) { +#if[floatingPointType] + return (x == y) || ($Fulltype$.isNaN(x) && $Fulltype$.isNaN(y)); +#else[floatingPointType] + return x == y; +#end[floatingPointType] + } + /** * Compares this buffer to another. * *

    Two $type$ buffers are compared by comparing their sequences of * remaining elements lexicographically, without regard to the starting * position of each sequence within its corresponding buffer. +#if[floatingPointType] + * Pairs of {@code $type$} elements are compared as if by invoking + * {@link $Fulltype$#compare($type$,$type$)}, except that + * {@code -0.0} and {@code 0.0} are considered to be equal. + * {@code $Fulltype$.NaN} is considered by this method to be equal + * to itself and greater than all other {@code $type$} values + * (including {@code $Fulltype$.POSITIVE_INFINITY}). +#else[floatingPointType] + * Pairs of {@code $type$} elements are compared as if by invoking + * {@link $Fulltype$#compare($type$,$type$)}. +#end[floatingPointType] * *

    A $type$ buffer is not comparable to any other type of object. * @@ -1145,20 +1165,23 @@ public int compareTo($Type$Buffer that) { int n = this.position() + Math.min(this.remaining(), that.remaining()); for (int i = this.position(), j = that.position(); i < n; i++, j++) { - $type$ v1 = this.get(i); - $type$ v2 = that.get(j); - if (v1 == v2) - continue; - if ((v1 != v1) && (v2 != v2)) // For float and double - continue; - if (v1 < v2) - return -1; - return +1; + int cmp = compare(this.get(i), that.get(j)); + if (cmp != 0) + return cmp; } return this.remaining() - that.remaining(); } - + private static int compare($type$ x, $type$ y) { +#if[floatingPointType] + return ((x < y) ? -1 : + (x > y) ? +1 : + (x == y) ? 0 : + $Fulltype$.isNaN(x) ? ($Fulltype$.isNaN(y) ? 0 : +1) : -1); +#else[floatingPointType] + return $Fulltype$.compare(x, y); +#end[floatingPointType] + } // -- Other char stuff -- @@ -1326,7 +1349,7 @@ } /** - * Appends the specified $fulltype$ to this + * Appends the specified $type$ to this * buffer  (optional operation). * *

    An invocation of this method of the form dst.append($x$) @@ -1336,7 +1359,7 @@ * dst.put($x$) * * @param $x$ - * The 16-bit $fulltype$ to append + * The 16-bit $type$ to append * * @return This buffer * @@ -1362,10 +1385,10 @@ /** * Retrieves this buffer's byte order. * - *

    The byte order of $a$ $fulltype$ buffer created by allocation or by + *

    The byte order of $a$ $type$ buffer created by allocation or by * wrapping an existing $type$ array is the {@link * ByteOrder#nativeOrder native order} of the underlying - * hardware. The byte order of $a$ $fulltype$ buffer created as a view of a byte buffer is that of the * byte buffer at the moment that the view is created.

    * diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/rmi/activation/Activatable.java --- a/jdk/src/share/classes/java/rmi/activation/Activatable.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/rmi/activation/Activatable.java Wed Jul 05 17:05:01 2017 +0200 @@ -73,7 +73,7 @@ * can be handled properly. * *

    This method invokes the {@link - * exportObject(Remote,String,MarshalledObject,boolean,port) + * #exportObject(Remote,String,MarshalledObject,boolean,int) * exportObject} method with this object, and the specified location, * data, restart mode, and port. Subsequent calls to {@link #getID} * will return the activation identifier returned from the call to @@ -120,7 +120,7 @@ * can be handled properly. * *

    This method invokes the {@link - * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory) + * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory) * exportObject} method with this object, and the specified location, * data, restart mode, port, and client and server socket factories. * Subsequent calls to {@link #getID} will return the activation @@ -312,7 +312,7 @@ * separately, so that exceptions can be handled properly. * *

    This method invokes the {@link - * exportObject(Remote,String,MarshalledObject,boolean,port,RMIClientSocketFactory,RMIServerSocketFactory) + * #exportObject(Remote,String,MarshalledObject,boolean,int,RMIClientSocketFactory,RMIServerSocketFactory) * exportObject} method with the specified object, location, data, * restart mode, and port, and null for both client and * server socket factories, and then returns the resulting activation diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/rmi/registry/LocateRegistry.java --- a/jdk/src/share/classes/java/rmi/registry/LocateRegistry.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/rmi/registry/LocateRegistry.java Wed Jul 05 17:05:01 2017 +0200 @@ -187,7 +187,7 @@ * host that accepts requests on the specified port. * *

    The Registry instance is exported as if the static - * {@link UnicastRemoteObject.exportObject(Remote,int) + * {@link UnicastRemoteObject#exportObject(Remote,int) * UnicastRemoteObject.exportObject} method is invoked, passing the * Registry instance and the specified port as * arguments, except that the Registry instance is @@ -213,7 +213,7 @@ * *

    The Registry instance is exported as if * the static {@link - * UnicastRemoteObject.exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory) + * UnicastRemoteObject#exportObject(Remote,int,RMIClientSocketFactory,RMIServerSocketFactory) * UnicastRemoteObject.exportObject} method is invoked, passing the * Registry instance, the specified port, the * specified RMIClientSocketFactory, and the specified diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java --- a/jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java Wed Jul 05 17:05:01 2017 +0200 @@ -138,7 +138,6 @@ * instance * @throws Throwable the exception to throw from the method invocation * on the proxy instance - * @see **/ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/security/cert/CertPathValidatorException.java --- a/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java Wed Jul 05 17:05:01 2017 +0200 @@ -216,7 +216,7 @@ /** * Returns the reason that the validation failed. The reason is * associated with the index of the certificate returned by - * {@link getIndex}. + * {@link #getIndex}. * * @return the reason that the validation failed, or * BasicReason.UNSPECIFIED if a reason has not been diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/text/Bidi.java --- a/jdk/src/share/classes/java/text/Bidi.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/text/Bidi.java Wed Jul 05 17:05:01 2017 +0200 @@ -121,9 +121,9 @@ * * @param paragraph a paragraph of text with optional character and paragraph attribute information * - * @see TextAttribute#BIDI_EMBEDDING - * @see TextAttribute#NUMERIC_SHAPING - * @see TextAttribute#RUN_DIRECTION + * @see java.awt.font.TextAttribute#BIDI_EMBEDDING + * @see java.awt.font.TextAttribute#NUMERIC_SHAPING + * @see java.awt.font.TextAttribute#RUN_DIRECTION */ public Bidi(AttributedCharacterIterator paragraph) { if (paragraph == null) { diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/util/Objects.java --- a/jdk/src/share/classes/java/util/Objects.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/util/Objects.java Wed Jul 05 17:05:01 2017 +0200 @@ -119,7 +119,7 @@ * * @param values the values to be hashed * @return a hash value of the sequence of input values - * @see Arrays#hashCode + * @see Arrays#hashCode(Object[]) * @see List#hashCode */ public static int hash(Object... values) { diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/java/util/logging/PlatformLoggingMXBean.java --- a/jdk/src/share/classes/java/util/logging/PlatformLoggingMXBean.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/java/util/logging/PlatformLoggingMXBean.java Wed Jul 05 17:05:01 2017 +0200 @@ -51,7 +51,7 @@ * The {@link PlatformManagedObject#getObjectName} method * can be used to obtain its {@code ObjectName}. * - * @See java.lang.management.PlatformManagedObject + * @see java.lang.management.PlatformManagedObject * * @author Mandy Chung * @since 1.7 diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/javax/accessibility/AccessibleContext.java --- a/jdk/src/share/classes/javax/accessibility/AccessibleContext.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/javax/accessibility/AccessibleContext.java Wed Jul 05 17:05:01 2017 +0200 @@ -296,7 +296,7 @@ * * @see #getAccessibleText * @see #addPropertyChangeListener - * @see #AccessibleText.AccessibleTextSequence + * @see AccessibleTextSequence */ public static final String ACCESSIBLE_TEXT_PROPERTY = "AccessibleText"; @@ -311,7 +311,7 @@ * * @see #getAccessibleText * @see #addPropertyChangeListener - * @see #AccessibleText.AccessibleTextSequence + * @see AccessibleTextSequence * * @since 1.5 */ @@ -334,7 +334,7 @@ * * @see #getAccessibleText * @see #addPropertyChangeListener - * @see #AccessibleText.AccessibleAttributeSequence + * @see AccessibleAttributeSequence * * @since 1.5 */ diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java --- a/jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/javax/accessibility/AccessibleExtendedText.java Wed Jul 05 17:05:01 2017 +0200 @@ -45,7 +45,6 @@ * @see Accessible#getAccessibleContext * @see AccessibleContext * @see AccessibleContext#getAccessibleText - * @see AccessibleText.AccessibleTextChunk * * @author Peter Korn * @author Lynn Monsanto diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java --- a/jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/javax/accessibility/AccessibleKeyBinding.java Wed Jul 05 17:05:01 2017 +0200 @@ -32,16 +32,11 @@ * the standard mechanism for an assistive technology to determine the * key bindings which exist for this object. * Any object that has such key bindings should support this - * interface. Applications can determine if an object supports the - * AccessibleKeyBinding interface by first obtaining its AccessibleContext - * (see @link Accessible} and then calling the - * {@link AccessibleContext#getAccessibleKeyBinding} method. If the return - * value is not null, the object supports this interface. + * interface. * * @see Accessible * @see Accessible#getAccessibleContext * @see AccessibleContext - * @see AccessibleContext#getAccessibleKeyBinding * * @author Lynn Monsanto * @since 1.4 @@ -58,21 +53,7 @@ /** * Returns a key binding for this object. The value returned is an * java.lang.Object which must be cast to appropriate type depending - * on the underlying implementation of the key. For example, if the - * Object returned is a javax.swing.KeyStroke, the user of this - * method should do the following: - * - * Component c = - * AccessibleContext ac = c.getAccessibleContext(); - * AccessibleKeyBinding akb = ac.getAccessibleKeyBinding(); - * for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) { - * Object o = akb.getAccessibleKeyBinding(i); - * if (o instanceof javax.swing.KeyStroke) { - * javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o; - * - * } - * } - * + * on the underlying implementation of the key. * * @param i zero-based index of the key bindings * @return a javax.lang.Object which specifies the key binding diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/org/ietf/jgss/GSSName.java --- a/jdk/src/share/classes/org/ietf/jgss/GSSName.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/org/ietf/jgss/GSSName.java Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,11 +103,12 @@ * follows: service@hostname.

    * * It represents the following Oid value:
    - * { 1(iso), 3(org), 6(dod), 1(internet), 5(security), - * 6(nametypes), 2(gss-host-based-services) } + * { iso(1) member-body(2) United + * States(840) mit(113554) infosys(1) gssapi(2) generic(1) service_name(4) + * } */ public static final Oid NT_HOSTBASED_SERVICE - = Oid.getInstance("1.3.6.1.5.6.2"); + = Oid.getInstance("1.2.840.113554.1.2.1.4"); /** * Name type to indicate a named user on a local system.

    diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java --- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java Wed Jul 05 17:05:01 2017 +0200 @@ -326,7 +326,7 @@ } // generate references and signature value - List allReferences = new ArrayList(si.getReferences()); + List allReferences = new ArrayList(); // traverse the Signature and register all objects with IDs that // may contain References @@ -356,6 +356,9 @@ } } } + // always add SignedInfo references after Manifest references so + // that Manifest reference are digested first + allReferences.addAll(si.getReferences()); // generate/digest each reference for (int i = 0, size = allReferences.size(); i < size; i++) { diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java --- a/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java Wed Jul 05 17:05:01 2017 +0200 @@ -30,7 +30,7 @@ import java.dyn.*; import java.util.Arrays; import static sun.dyn.MethodHandleNatives.Constants.*; -import static sun.dyn.MethodHandleImpl.newIllegalArgumentException; +import static sun.dyn.MemberName.newIllegalArgumentException; /** * This method handle performs simple conversion or checking of a single argument. @@ -302,7 +302,22 @@ */ private static int type2size(int type) { assert(type >= T_BOOLEAN && type <= T_OBJECT); - return (type == T_FLOAT || type == T_DOUBLE) ? 2 : 1; + return (type == T_LONG || type == T_DOUBLE) ? 2 : 1; + } + private static int type2size(Class type) { + return type2size(basicType(type)); + } + + /** The given stackMove is the number of slots pushed. + * It might be negative. Scale it (multiply) by the + * VM's notion of how an address changes with a push, + * to get the raw SP change for stackMove. + * Then shift and mask it into the correct field. + */ + private static long insertStackMove(int stackMove) { + // following variable must be long to avoid sign extension after '<<' + long spChange = stackMove * MethodHandleNatives.JVM_STACK_MOVE_UNIT; + return (spChange & CONV_STACK_MOVE_MASK) << CONV_STACK_MOVE_SHIFT; } /** Construct an adapter conversion descriptor for a single-argument conversion. */ @@ -310,16 +325,16 @@ assert(src == (src & 0xF)); assert(dest == (dest & 0xF)); assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF); - long stackMove = type2size(dest) - type2size(src); + int stackMove = type2size(dest) - type2size(src); return ((long) argnum << 32 | (long) convOp << CONV_OP_SHIFT | (int) src << CONV_SRC_TYPE_SHIFT | (int) dest << CONV_DEST_TYPE_SHIFT | - stackMove << CONV_STACK_MOVE_SHIFT + insertStackMove(stackMove) ); } private static long makeConv(int convOp, int argnum, int stackMove) { - assert(convOp >= OP_SWAP_ARGS && convOp <= OP_SPREAD_ARGS); + assert(convOp >= OP_DUP_ARGS && convOp <= OP_SPREAD_ARGS); byte src = 0, dest = 0; if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS) src = dest = T_OBJECT; @@ -327,12 +342,21 @@ (long) convOp << CONV_OP_SHIFT | (int) src << CONV_SRC_TYPE_SHIFT | (int) dest << CONV_DEST_TYPE_SHIFT | - stackMove << CONV_STACK_MOVE_SHIFT + insertStackMove(stackMove) + ); + } + private static long makeSwapConv(int convOp, int srcArg, byte type, int destSlot) { + assert(convOp >= OP_SWAP_ARGS && convOp <= OP_ROT_ARGS); + return ((long) srcArg << 32 | + (long) convOp << CONV_OP_SHIFT | + (int) type << CONV_SRC_TYPE_SHIFT | + (int) type << CONV_DEST_TYPE_SHIFT | + (int) destSlot << CONV_VMINFO_SHIFT ); } private static long makeConv(int convOp) { - assert(convOp == OP_RETYPE_ONLY); - return (long) convOp << CONV_OP_SHIFT; // stackMove, src, dst, argnum all zero + assert(convOp == OP_RETYPE_ONLY || convOp == OP_RETYPE_RAW); + return ((long)-1 << 32) | (convOp << CONV_OP_SHIFT); // stackMove, src, dst all zero } private static int convCode(long conv) { return (int)conv; @@ -348,16 +372,6 @@ /** One of OP_RETYPE_ONLY, etc. */ int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; } - @Override - public String toString() { - return addTypeString(this, "Adapted[" + basicToString(nonAdapter((MethodHandle)vmtarget)) + "]"); - } - - private static MethodHandle nonAdapter(MethodHandle mh) { - return (MethodHandle) - MethodHandleNatives.getTarget(mh, ETF_DIRECT_HANDLE); - } - /* Return one plus the position of the first non-trivial difference * between the given types. This is not a symmetric operation; * we are considering adapting the targetType to adapterType. @@ -399,14 +413,14 @@ //if (false) return 1; // never adaptable! return -1; // some significant difference } - private static int diffParamTypes(MethodType adapterType, int tstart, - MethodType targetType, int astart, + private static int diffParamTypes(MethodType adapterType, int astart, + MethodType targetType, int tstart, int nargs, boolean raw) { assert(nargs >= 0); int res = 0; for (int i = 0; i < nargs; i++) { - Class src = adapterType.parameterType(tstart+i); - Class dest = targetType.parameterType(astart+i); + Class src = adapterType.parameterType(astart+i); + Class dest = targetType.parameterType(tstart+i); if ((!raw ? VerifyType.canPassUnchecked(src, dest) : VerifyType.canPassRaw(src, dest) @@ -422,7 +436,7 @@ /** Can a retyping adapter (alone) validly convert the target to newType? */ public static boolean canRetypeOnly(MethodType newType, MethodType targetType) { - return canRetypeOnly(newType, targetType, false); + return canRetype(newType, targetType, false); } /** Can a retyping adapter (alone) convert the target to newType? * It is allowed to widen subword types and void to int, to make bitwise @@ -430,14 +444,14 @@ * reference conversions on return. This last feature requires that the * caller be trusted, and perform explicit cast conversions on return values. */ - static boolean canRawRetypeOnly(MethodType newType, MethodType targetType) { - return canRetypeOnly(newType, targetType, true); + public static boolean canRetypeRaw(MethodType newType, MethodType targetType) { + return canRetype(newType, targetType, true); } - static boolean canRetypeOnly(MethodType newType, MethodType targetType, boolean raw) { - if (!convOpSupported(OP_RETYPE_ONLY)) return false; + static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) { + if (!convOpSupported(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY)) return false; int diff = diffTypes(newType, targetType, raw); // %%% This assert is too strong. Factor diff into VerifyType and reconcile. - assert((diff == 0) == VerifyType.isNullConversion(newType, targetType)); + assert(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType)); return diff == 0; } @@ -447,19 +461,21 @@ */ public static MethodHandle makeRetypeOnly(Access token, MethodType newType, MethodHandle target) { - return makeRetypeOnly(token, newType, target, false); + return makeRetype(token, newType, target, false); } - public static MethodHandle makeRawRetypeOnly(Access token, + public static MethodHandle makeRetypeRaw(Access token, MethodType newType, MethodHandle target) { - return makeRetypeOnly(token, newType, target, true); + return makeRetype(token, newType, target, true); } - static MethodHandle makeRetypeOnly(Access token, + static MethodHandle makeRetype(Access token, MethodType newType, MethodHandle target, boolean raw) { Access.check(token); - if (!canRetypeOnly(newType, target.type(), raw)) + MethodType oldType = target.type(); + if (oldType == newType) return target; + if (!canRetype(newType, oldType, raw)) return null; // TO DO: clone the target guy, whatever he is, with new type. - return new AdapterMethodHandle(target, newType, makeConv(OP_RETYPE_ONLY)); + return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY)); } /** Can a checkcast adapter validly convert the target to newType? @@ -492,7 +508,7 @@ Access.check(token); if (!canCheckCast(newType, target.type(), arg, castType)) return null; - long conv = makeConv(OP_CHECK_CAST, arg, 0); + long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT); return new AdapterMethodHandle(target, newType, conv, castType); } @@ -537,10 +553,9 @@ int arg, Class convType) { Access.check(token); MethodType oldType = target.type(); - Class src = newType.parameterType(arg); - Class dst = oldType.parameterType(arg); if (!canPrimCast(newType, oldType, arg, convType)) return null; + Class src = newType.parameterType(arg); long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType)); return new AdapterMethodHandle(target, newType, conv); } @@ -607,8 +622,6 @@ return null; } - // TO DO: makeSwapArguments, makeRotateArguments, makeDuplicateArguments - /** Can an adapter simply drop arguments to convert the target to newType? */ public static boolean canDropArguments(MethodType newType, MethodType targetType, int dropArgPos, int dropArgCount) { @@ -643,26 +656,195 @@ Access.check(token); if (dropArgCount == 0) return makeRetypeOnly(IMPL_TOKEN, newType, target); - MethodType mt = target.type(); - int argCount = mt.parameterCount(); - if (!canDropArguments(newType, mt, dropArgPos, dropArgCount)) + if (!canDropArguments(newType, target.type(), dropArgPos, dropArgCount)) + return null; + // in arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ] + // out arglist: [0: ...keep1 | dpos: keep2... ] + int keep2InPos = dropArgPos + dropArgCount; + int dropSlot = newType.parameterSlotDepth(keep2InPos); + int keep1InSlot = newType.parameterSlotDepth(dropArgPos); + int slotCount = keep1InSlot - dropSlot; + assert(slotCount >= dropArgCount); + assert(target.type().parameterSlotCount() + slotCount == newType.parameterSlotCount()); + long conv = makeConv(OP_DROP_ARGS, dropArgPos + dropArgCount - 1, -slotCount); + return new AdapterMethodHandle(target, newType, conv); + } + + /** Can an adapter duplicate an argument to convert the target to newType? */ + public static boolean canDupArguments(MethodType newType, MethodType targetType, + int dupArgPos, int dupArgCount) { + if (!convOpSupported(OP_DUP_ARGS)) return false; + if (diffReturnTypes(newType, targetType, false) != 0) + return false; + int nptypes = newType.parameterCount(); + if (dupArgCount < 0 || dupArgPos + dupArgCount > nptypes) + return false; + if (targetType.parameterCount() != nptypes + dupArgCount) + return false; + // parameter types must be the same up to the duplicated arguments + if (diffParamTypes(newType, 0, targetType, 0, nptypes, false) != 0) + return false; + // duplicated types must be, well, duplicates + if (diffParamTypes(newType, dupArgPos, targetType, nptypes, dupArgCount, false) != 0) + return false; + return true; + } + + /** Factory method: Duplicate the selected argument. + * Return null if this is not possible. + */ + public static MethodHandle makeDupArguments(Access token, + MethodType newType, MethodHandle target, + int dupArgPos, int dupArgCount) { + Access.check(token); + if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount)) return null; - int dropSlotCount, dropSlotPos; - if (dropArgCount >= argCount) { - assert(dropArgPos == argCount-1); - dropSlotPos = 0; - dropSlotCount = mt.parameterSlotCount(); + if (dupArgCount == 0) + return target; + // in arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... ] + // out arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... | dup... ] + int keep2InPos = dupArgPos + dupArgCount; + int dupSlot = newType.parameterSlotDepth(keep2InPos); + int keep1InSlot = newType.parameterSlotDepth(dupArgPos); + int slotCount = keep1InSlot - dupSlot; + assert(target.type().parameterSlotCount() - slotCount == newType.parameterSlotCount()); + long conv = makeConv(OP_DUP_ARGS, dupArgPos + dupArgCount - 1, slotCount); + return new AdapterMethodHandle(target, newType, conv); + } + + /** Can an adapter swap two arguments to convert the target to newType? */ + public static boolean canSwapArguments(MethodType newType, MethodType targetType, + int swapArg1, int swapArg2) { + if (!convOpSupported(OP_SWAP_ARGS)) return false; + if (diffReturnTypes(newType, targetType, false) != 0) + return false; + if (swapArg1 >= swapArg2) return false; // caller resp + int nptypes = newType.parameterCount(); + if (targetType.parameterCount() != nptypes) + return false; + if (swapArg1 < 0 || swapArg2 >= nptypes) + return false; + if (diffParamTypes(newType, 0, targetType, 0, swapArg1, false) != 0) + return false; + if (diffParamTypes(newType, swapArg1, targetType, swapArg2, 1, false) != 0) + return false; + if (diffParamTypes(newType, swapArg1+1, targetType, swapArg1+1, swapArg2-swapArg1-1, false) != 0) + return false; + if (diffParamTypes(newType, swapArg2, targetType, swapArg1, 1, false) != 0) + return false; + if (diffParamTypes(newType, swapArg2+1, targetType, swapArg2+1, nptypes-swapArg2-1, false) != 0) + return false; + return true; + } + + /** Factory method: Swap the selected arguments. + * Return null if this is not possible. + */ + public static MethodHandle makeSwapArguments(Access token, + MethodType newType, MethodHandle target, + int swapArg1, int swapArg2) { + Access.check(token); + if (swapArg1 == swapArg2) + return target; + if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; } + if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2)) + return null; + Class swapType = newType.parameterType(swapArg1); + // in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ] + // out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ] + int swapSlot2 = newType.parameterSlotDepth(swapArg2 + 1); + long conv = makeSwapConv(OP_SWAP_ARGS, swapArg1, basicType(swapType), swapSlot2); + return new AdapterMethodHandle(target, newType, conv); + } + + static int positiveRotation(int argCount, int rotateBy) { + assert(argCount > 0); + if (rotateBy >= 0) { + if (rotateBy < argCount) + return rotateBy; + return rotateBy % argCount; + } else if (rotateBy >= -argCount) { + return rotateBy + argCount; } else { - // arglist: [0: keep... | dpos: drop... | dpos+dcount: keep... ] - int lastDroppedArg = dropArgPos + dropArgCount - 1; - int lastKeptArg = dropArgPos - 1; // might be -1, which is OK - dropSlotPos = mt.parameterSlotDepth(1+lastDroppedArg); - int lastKeptSlot = mt.parameterSlotDepth(1+lastKeptArg); - dropSlotCount = lastKeptSlot - dropSlotPos; - assert(dropSlotCount >= dropArgCount); + return (-1-((-1-rotateBy) % argCount)) + argCount; } - long conv = makeConv(OP_DROP_ARGS, dropArgPos, +dropSlotCount); - return new AdapterMethodHandle(target, newType, dropSlotCount, conv); + } + + final static int MAX_ARG_ROTATION = 1; + + /** Can an adapter rotate arguments to convert the target to newType? */ + public static boolean canRotateArguments(MethodType newType, MethodType targetType, + int firstArg, int argCount, int rotateBy) { + if (!convOpSupported(OP_ROT_ARGS)) return false; + if (argCount <= 2) return false; // must be a swap, not a rotate + rotateBy = positiveRotation(argCount, rotateBy); + if (rotateBy == 0) return false; // no rotation + if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION) + return false; // too many argument positions + // Rotate incoming args right N to the out args, N in 1..(argCouunt-1). + if (diffReturnTypes(newType, targetType, false) != 0) + return false; + int nptypes = newType.parameterCount(); + if (targetType.parameterCount() != nptypes) + return false; + if (firstArg < 0 || firstArg >= nptypes) return false; + int argLimit = firstArg + argCount; + if (argLimit > nptypes) return false; + if (diffParamTypes(newType, 0, targetType, 0, firstArg, false) != 0) + return false; + int newChunk1 = argCount - rotateBy, newChunk2 = rotateBy; + // swap new chunk1 with target chunk2 + if (diffParamTypes(newType, firstArg, targetType, argLimit-newChunk1, newChunk1, false) != 0) + return false; + // swap new chunk2 with target chunk1 + if (diffParamTypes(newType, firstArg+newChunk1, targetType, firstArg, newChunk2, false) != 0) + return false; + return true; + } + + /** Factory method: Rotate the selected argument range. + * Return null if this is not possible. + */ + public static MethodHandle makeRotateArguments(Access token, + MethodType newType, MethodHandle target, + int firstArg, int argCount, int rotateBy) { + Access.check(token); + rotateBy = positiveRotation(argCount, rotateBy); + if (!canRotateArguments(newType, target.type(), firstArg, argCount, rotateBy)) + return null; + // Decide whether it should be done as a right or left rotation, + // on the JVM stack. Return the number of stack slots to rotate by, + // positive if right, negative if left. + int limit = firstArg + argCount; + int depth0 = newType.parameterSlotDepth(firstArg); + int depth1 = newType.parameterSlotDepth(limit-rotateBy); + int depth2 = newType.parameterSlotDepth(limit); + int chunk1Slots = depth0 - depth1; assert(chunk1Slots > 0); + int chunk2Slots = depth1 - depth2; assert(chunk2Slots > 0); + // From here on out, it assumes a single-argument shift. + assert(MAX_ARG_ROTATION == 1); + int srcArg, dstArg; + byte basicType; + if (chunk2Slots <= chunk1Slots) { + // Rotate right/down N (rotateBy = +N, N small, c2 small): + // in arglist: [0: ...keep1 | arg1: c1... | limit-N: c2 | limit: keep2... ] + // out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1... | limit: keep2... ] + srcArg = limit-1; + dstArg = firstArg; + basicType = basicType(newType.parameterType(srcArg)); + assert(chunk2Slots == type2size(basicType)); + } else { + // Rotate left/up N (rotateBy = -N, N small, c1 small): + // in arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2... | limit: keep2... ] + // out arglist: [0: ...keep1 | arg1: c2 ... | limit-N: c1 | limit: keep2... ] + srcArg = firstArg; + dstArg = limit-1; + basicType = basicType(newType.parameterType(srcArg)); + assert(chunk1Slots == type2size(basicType)); + } + int dstSlot = newType.parameterSlotDepth(dstArg + 1); + long conv = makeSwapConv(OP_ROT_ARGS, srcArg, basicType, dstSlot); + return new AdapterMethodHandle(target, newType, conv); } /** Can an adapter spread an argument to convert the target to newType? */ @@ -676,10 +858,10 @@ if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0) return false; int afterPos = spreadArgPos + spreadArgCount; - int afterCount = nptypes - afterPos; + int afterCount = nptypes - (spreadArgPos + 1); if (spreadArgPos < 0 || spreadArgPos >= nptypes || spreadArgCount < 0 || - targetType.parameterCount() != nptypes - 1 + spreadArgCount) + targetType.parameterCount() != afterPos + afterCount) return false; // parameter types after the spread point must also be the same if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0) @@ -697,32 +879,40 @@ return true; } + /** Factory method: Spread selected argument. */ public static MethodHandle makeSpreadArguments(Access token, MethodType newType, MethodHandle target, Class spreadArgType, int spreadArgPos, int spreadArgCount) { Access.check(token); - MethodType mt = target.type(); - int argCount = mt.parameterCount(); - if (!canSpreadArguments(newType, mt, spreadArgType, spreadArgPos, spreadArgCount)) + MethodType targetType = target.type(); + if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount)) return null; - int spreadSlotCount, spreadSlotPos; - if (spreadArgCount >= argCount) { - assert(spreadArgPos == argCount-1); - spreadSlotPos = 0; - spreadSlotCount = mt.parameterSlotCount(); - } else { - // arglist: [0: keep... | dpos: spread... | dpos+dcount: keep... ] - int lastSpreadArg = spreadArgPos + spreadArgCount - 1; - int lastKeptArg = spreadArgPos - 1; // might be -1, which is OK - spreadSlotPos = mt.parameterSlotDepth(1+lastSpreadArg); - int lastKeptSlot = mt.parameterSlotDepth(1+lastKeptArg); - spreadSlotCount = lastKeptSlot - spreadSlotPos; - assert(spreadSlotCount >= spreadArgCount); - } - long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, spreadSlotCount); - return new AdapterMethodHandle(target, newType, conv, spreadArgType); + // in arglist: [0: ...keep1 | spos: spreadArg | spos+1: keep2... ] + // out arglist: [0: ...keep1 | spos: spread... | spos+scount: keep2... ] + int keep2OutPos = spreadArgPos + spreadArgCount; + int spreadSlot = targetType.parameterSlotDepth(keep2OutPos); + int keep1OutSlot = targetType.parameterSlotDepth(spreadArgPos); + int slotCount = keep1OutSlot - spreadSlot; + assert(spreadSlot == newType.parameterSlotDepth(spreadArgPos+1)); + assert(slotCount >= spreadArgCount); + long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, slotCount-1); + MethodHandle res = new AdapterMethodHandle(target, newType, conv, spreadArgType); + assert(res.type().parameterType(spreadArgPos) == spreadArgType); + return res; } // TO DO: makeCollectArguments, makeFlyby, makeRicochet + + @Override + public String toString() { + return nonAdapter((MethodHandle)vmtarget).toString(); + } + + private static MethodHandle nonAdapter(MethodHandle mh) { + while (mh instanceof AdapterMethodHandle) { + mh = (MethodHandle) mh.vmtarget; + } + return mh; + } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/BoundMethodHandle.java --- a/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/BoundMethodHandle.java Wed Jul 05 17:05:01 2017 +0200 @@ -28,6 +28,10 @@ import sun.dyn.util.VerifyType; import sun.dyn.util.Wrapper; import java.dyn.*; +import java.util.List; +import sun.dyn.MethodHandleNatives.Constants; +import static sun.dyn.MethodHandleImpl.IMPL_LOOKUP; +import static sun.dyn.MemberName.newIllegalArgumentException; /** * The flavor of method handle which emulates an invoke instruction @@ -35,18 +39,23 @@ * when the handle is created, not when it is invoked. * @author jrose */ -public class BoundMethodHandle extends MethodHandle { +public class BoundMethodHandle extends MethodHandle { //MethodHandle vmtarget; // next BMH or final DMH or methodOop private final Object argument; // argument to insert private final int vmargslot; // position at which it is inserted + private static final Access IMPL_TOKEN = Access.getToken(); + private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(IMPL_TOKEN); + // Constructors in this class *must* be package scoped or private. + // Exception: JavaMethodHandle constructors are protected. + // (The link between JMH and BMH is temporary.) /** Bind a direct MH to its receiver (or first ref. argument). * The JVM will pre-dispatch the MH if it is not already static. */ BoundMethodHandle(DirectMethodHandle mh, Object argument) { - super(Access.TOKEN, mh.type().dropParameterType(0)); + super(Access.TOKEN, mh.type().dropParameterTypes(0, 1)); // check the type now, once for all: this.argument = checkReferenceArgument(argument, mh, 0); this.vmargslot = this.type().parameterSlotCount(); @@ -56,32 +65,34 @@ } else { this.vmtarget = mh; } - } - - private static final int REF_ARG = 0, PRIM_ARG = 1, SELF_ARG = 2; + } /** Insert an argument into an arbitrary method handle. * If argnum is zero, inserts the first argument, etc. * The argument type must be a reference. */ BoundMethodHandle(MethodHandle mh, Object argument, int argnum) { - this(mh, argument, argnum, mh.type().parameterType(argnum).isPrimitive() ? PRIM_ARG : REF_ARG); + this(mh.type().dropParameterTypes(argnum, argnum+1), + mh, argument, argnum); } /** Insert an argument into an arbitrary method handle. * If argnum is zero, inserts the first argument, etc. */ - BoundMethodHandle(MethodHandle mh, Object argument, int argnum, int whichArg) { - super(Access.TOKEN, mh.type().dropParameterType(argnum)); - if (whichArg == PRIM_ARG) + BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) { + super(Access.TOKEN, type); + if (mh.type().parameterType(argnum).isPrimitive()) this.argument = bindPrimitiveArgument(argument, mh, argnum); else { - if (whichArg == SELF_ARG) argument = this; this.argument = checkReferenceArgument(argument, mh, argnum); } - this.vmargslot = this.type().parameterSlotDepth(argnum); + this.vmargslot = type.parameterSlotDepth(argnum); + initTarget(mh, argnum); + } + + private void initTarget(MethodHandle mh, int argnum) { if (MethodHandleNatives.JVM_SUPPORT) { - this.vmtarget = null; // maybe updated by JVM + this.vmtarget = null; // maybe updated by JVM MethodHandleNatives.init(this, mh, argnum); } else { this.vmtarget = mh; @@ -97,29 +108,65 @@ assert(this.getClass() == AdapterMethodHandle.class); } - /** Initialize the current object as a method handle, binding it - * as the {@code argnum}th argument of the method handle {@code entryPoint}. - * The invocation type of the resulting method handle will be the - * same as {@code entryPoint}, except that the {@code argnum}th argument - * type will be dropped. - */ - public BoundMethodHandle(MethodHandle entryPoint, int argnum) { - this(entryPoint, null, argnum, SELF_ARG); - - // Note: If the conversion fails, perhaps because of a bad entryPoint, - // the MethodHandle.type field will not be filled in, and therefore - // no MH.invoke call will ever succeed. The caller may retain a pointer - // to the broken method handle, but no harm can be done with it. - } - - /** Initialize the current object as a method handle, binding it + /** Initialize the current object as a Java method handle, binding it * as the first argument of the method handle {@code entryPoint}. * The invocation type of the resulting method handle will be the * same as {@code entryPoint}, except that the first argument * type will be dropped. */ - public BoundMethodHandle(MethodHandle entryPoint) { - this(entryPoint, null, 0, SELF_ARG); + protected BoundMethodHandle(MethodHandle entryPoint) { + super(Access.TOKEN, entryPoint.type().dropParameterTypes(0, 1)); + this.argument = this; // kludge; get rid of + this.vmargslot = this.type().parameterSlotDepth(0); + initTarget(entryPoint, 0); + assert(this instanceof JavaMethodHandle); + } + + /** Initialize the current object as a Java method handle. + */ + protected BoundMethodHandle(String entryPointName, MethodType type, boolean matchArity) { + super(Access.TOKEN, null); + MethodHandle entryPoint + = findJavaMethodHandleEntryPoint(this.getClass(), + entryPointName, type, matchArity); + MethodHandleImpl.initType(this, entryPoint.type().dropParameterTypes(0, 1)); + this.argument = this; // kludge; get rid of + this.vmargslot = this.type().parameterSlotDepth(0); + initTarget(entryPoint, 0); + assert(this instanceof JavaMethodHandle); + } + + private static + MethodHandle findJavaMethodHandleEntryPoint(Class caller, + String name, + MethodType type, + boolean matchArity) { + if (matchArity) type.getClass(); // elicit NPE + List methods = IMPL_NAMES.getMethods(caller, true, name, null, caller); + MethodType foundType = null; + MemberName foundMethod = null; + for (MemberName method : methods) { + MethodType mtype = method.getMethodType(); + if (type != null && type.parameterCount() != mtype.parameterCount()) + continue; + else if (foundType == null) + foundType = mtype; + else if (foundType != mtype) + throw newIllegalArgumentException("more than one method named "+name+" in "+caller.getName()); + // discard overrides + if (foundMethod == null) + foundMethod = method; + else if (foundMethod.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) + foundMethod = method; + } + if (foundMethod == null) + throw newIllegalArgumentException("no method named "+name+" in "+caller.getName()); + MethodHandle entryPoint = MethodHandleImpl.findMethod(IMPL_TOKEN, foundMethod, true, caller); + if (type != null) { + MethodType epType = type.insertParameterTypes(0, entryPoint.type().parameterType(0)); + entryPoint = MethodHandles.convertArguments(entryPoint, epType); + } + return entryPoint; } /** Make sure the given {@code argument} can be used as {@code argnum}-th @@ -175,6 +222,24 @@ @Override public String toString() { - return "Bound[" + super.toString() + "]"; + MethodHandle mh = this; + while (mh instanceof BoundMethodHandle) { + Object info = MethodHandleNatives.getTargetInfo(mh); + if (info instanceof MethodHandle) { + mh = (MethodHandle) info; + } else { + String name = null; + if (info instanceof MemberName) + name = ((MemberName)info).getName(); + if (name != null) + return name; + else + return super.toString(); // , probably + } + assert(mh != this); + if (mh instanceof JavaMethodHandle) + break; // access JMH.toString(), not BMH.toString() + } + return mh.toString(); } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/CallSiteImpl.java --- a/jdk/src/share/classes/sun/dyn/CallSiteImpl.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/CallSiteImpl.java Wed Jul 05 17:05:01 2017 +0200 @@ -26,34 +26,51 @@ package sun.dyn; import java.dyn.*; +import java.util.logging.Level; +import java.util.logging.Logger; /** - * The CallSite privately created by the JVM at every invokedynamic instruction. + * Parts of CallSite known to the JVM. + * FIXME: Merge all this into CallSite proper. * @author jrose */ -class CallSiteImpl extends CallSite { - // Fields used only by the JVM. Do not use or change. +public class CallSiteImpl { + // Field used only by the JVM. Do not use or change. private Object vmmethod; // Values supplied by the JVM: - int callerMID, callerBCI; + protected int callerMID, callerBCI; + + private MethodHandle target; + protected final Object caller; // usually a class + protected final String name; + protected final MethodType type; - private CallSiteImpl(Class caller, String name, MethodType type) { - super(caller, name, type); + /** called only directly from CallSite() */ + protected CallSiteImpl(Access token, Object caller, String name, MethodType type) { + Access.check(token); + this.caller = caller; + this.name = name; + this.type = type; } - @Override - public void setTarget(MethodHandle mh) { - checkTarget(mh); - if (MethodHandleNatives.JVM_SUPPORT) - MethodHandleNatives.linkCallSite(this, (MethodHandle) mh); - else - super.setTarget(mh); + /** native version of setTarget */ + protected void setTarget(MethodHandle mh) { + //System.out.println("setTarget "+this+" := "+mh); + // XXX I don't know how to fix this properly. +// if (false && MethodHandleNatives.JVM_SUPPORT) // FIXME: enable this +// MethodHandleNatives.linkCallSite(this, mh); +// else + this.target = mh; + } + + protected MethodHandle getTarget() { + return target; } private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE = MethodHandleImpl.IMPL_LOOKUP.findStatic(CallSite.class, "privateInitializeCallSite", - MethodType.make(void.class, CallSite.class, int.class, int.class)); + MethodType.methodType(void.class, CallSite.class, int.class, int.class)); // this is the up-call from the JVM: static CallSite makeSite(Class caller, String name, MethodType type, @@ -61,10 +78,25 @@ MethodHandle bsm = Linkage.getBootstrapMethod(caller); if (bsm == null) throw new InvokeDynamicBootstrapError("class has no bootstrap method: "+caller); - CallSite site = bsm.invoke(caller, name, type); + CallSite site; + try { + site = bsm.invoke(caller, name, type); + } catch (Throwable ex) { + throw new InvokeDynamicBootstrapError("exception thrown while linking", ex); + } if (site == null) throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller); - PRIVATE_INITIALIZE_CALL_SITE.invoke(site, callerMID, callerBCI); + if (site.type() != type) + throw new InvokeDynamicBootstrapError("call site type not initialized correctly: "+site); + if (site.callerClass() != caller) + throw new InvokeDynamicBootstrapError("call site caller not initialized correctly: "+site); + if ((Object)site.name() != name) + throw new InvokeDynamicBootstrapError("call site name not initialized correctly: "+site); + try { + PRIVATE_INITIALIZE_CALL_SITE.invoke(site, callerMID, callerBCI); + } catch (Throwable ex) { + throw new InvokeDynamicBootstrapError("call site initialization exception", ex); + } return site; } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/FilterGeneric.java --- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java Wed Jul 05 17:05:01 2017 +0200 @@ -31,174 +31,159 @@ import java.dyn.NoAccessException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import static sun.dyn.MemberName.newIllegalArgumentException; /** - * "Flyby adapters" which apply arbitrary conversions to arguments + * These adapters apply arbitrary conversions to arguments * on the way to a ultimate target. * For simplicity, these are all generically typed. * @author jrose */ class FilterGeneric { - // type for the outgoing call (will be generic) - private final MethodType targetType; - // position of (first) argument to participate in filtering - private final short argumentPosition; - // number of arguments to participate in filtering - private final short argumentCount; - // how the result interacts with the filtered arguments: Prepend, Append, Replace, Discard - private final char replaceMode; - // prototype adapter (clone and customize for each new target & conversion!) - private final Adapter adapter; - // entry point for adapter (Adapter mh, a...) => ... - private final MethodHandle entryPoint; - // more of them (loosely cached) - private FilterGeneric variations; + // type for the incoming call (will be generic) + private final MethodType entryType; + // prototype adapters (clone and customize for each new target & conversion!) + private final Adapter[] adapters; - /** Compute and cache information common to all unboxing adapters - * that can call out to targets of the erasure-family of the given erased type. + /** Compute and cache information common to all filtering adapters + * with the given generic type */ - // TO DO: Make this private. - FilterGeneric(MethodType targetType, short argumentPosition, short argumentCount, char replaceMode) { - if (argumentCount == 0) { - if (replaceMode == 'P' || replaceMode == 'A') replaceMode = 'R'; - if (replaceMode == 'I') argumentPosition = 0; - } - this.targetType = targetType; - this.argumentPosition = argumentPosition; - this.argumentCount = argumentCount; - this.replaceMode = replaceMode; - validate(targetType, argumentPosition, argumentCount, replaceMode); - Adapter ad = findAdapter(targetType, argumentPosition, argumentCount, replaceMode, filterType()); - if (ad == null) - ad = buildAdapterFromBytecodes(targetType, argumentPosition, argumentCount, replaceMode, filterType()); - this.adapter = ad; - this.entryPoint = ad.prototypeEntryPoint(); + FilterGeneric(MethodType entryType) { + this.entryType = entryType; + int tableSize = Kind.LIMIT.invokerIndex(1 + entryType.parameterCount()); + this.adapters = new Adapter[tableSize]; } - Adapter makeInstance(MethodHandle filter, MethodHandle target) { - return adapter.makeInstance(entryPoint, filter, target); + Adapter getAdapter(Kind kind, int pos) { + int index = kind.invokerIndex(pos); + Adapter ad = adapters[index]; + if (ad != null) return ad; + ad = findAdapter(entryType, kind, pos); + if (ad == null) + ad = buildAdapterFromBytecodes(entryType, kind, pos); + adapters[index] = ad; + return ad; + } + + Adapter makeInstance(Kind kind, int pos, MethodHandle filter, MethodHandle target) { + Adapter ad = getAdapter(kind, pos); + return ad.makeInstance(ad.prototypeEntryPoint(), filter, target); + } + + /** Build an adapter of the given generic type, which invokes filter + * on the selected incoming argument before passing it to the target. + * @param pos the argument to filter + * @param filter the function to call on the argument + * @param target the target to call with the modified argument list + * @return an adapter method handle + */ + public static MethodHandle makeArgumentFilter(int pos, MethodHandle filter, MethodHandle target) { + return make(Kind.value, pos, filter, target); } - /** Build an adapter of the given generic type, which invokes typedTarget - * on the incoming arguments, after unboxing as necessary. - * The return value is boxed if necessary. - * @param genericType the required type of the result - * @param typedTarget the target + /** Build an adapter of the given generic type, which invokes a combiner + * on a selected group of leading arguments. + * The result of the combiner is prepended before all those arguments. + * @param combiner the function to call on the selected leading arguments + * @param target the target to call with the modified argument list * @return an adapter method handle */ - public static MethodHandle make(MethodHandle target, int pos, MethodHandle filter) { - return FilterGeneric.of(target.type(), (short)pos, (short)1, 'R').makeInstance(filter, target); + public static MethodHandle makeArgumentFolder(MethodHandle combiner, MethodHandle target) { + int num = combiner.type().parameterCount(); + return make(Kind.fold, num, combiner, target); } - /** Return the adapter information for this type's erasure. */ - static FilterGeneric of(MethodType type, short ap, short ac, char mode) { - if (type.generic() != type) - throw new IllegalArgumentException("must be generic: "+type); - validate(type, ap, ac, mode); - MethodTypeImpl form = MethodTypeImpl.of(type); - FilterGeneric filterGen = form.filterGeneric; - if (filterGen == null) - form.filterGeneric = filterGen = new FilterGeneric(type, (short)0, (short)1, 'R'); - return find(filterGen, ap, ac, mode); + /** Build an adapter of the given generic type, which invokes a filter + * on the incoming arguments, reified as a group. + * The argument may be modified (by side effects in the filter). + * The arguments, possibly modified, are passed on to the target. + * @param filter the function to call on the arguments + * @param target the target to call with the possibly-modified argument list + * @return an adapter method handle + */ + public static MethodHandle makeFlyby(MethodHandle filter, MethodHandle target) { + return make(Kind.flyby, 0, filter, target); } - static FilterGeneric find(FilterGeneric gen, short ap, short ac, char mode) { - for (;;) { - if (gen.argumentPosition == ap && - gen.argumentCount == ac && - gen.replaceMode == mode) { - return gen; - } - FilterGeneric gen2 = gen.variations; - if (gen2 == null) break; - gen = gen2; - } - FilterGeneric gen2 = new FilterGeneric(gen.targetType, ap, ac, mode); - gen.variations = gen2; // OK if this smashes another cached chain - return gen2; + /** Build an adapter of the given generic type, which invokes a collector + * on the selected incoming argument and all following arguments. + * The result of the collector replaces all those arguments. + * @param collector the function to call on the selected trailing arguments + * @param target the target to call with the modified argument list + * @return an adapter method handle + */ + public static MethodHandle makeArgumentCollector(MethodHandle collector, MethodHandle target) { + int pos = target.type().parameterCount() - 1; + return make(Kind.collect, pos, collector, target); } - private static void validate(MethodType type, short ap, short ac, char mode) { - int endpos = ap + ac; - switch (mode) { - case 'P': case 'A': case 'R': case 'D': - if (ap >= 0 && ac >= 0 && - endpos >= 0 && endpos <= type.parameterCount()) - return; - default: - throw new InternalError("configuration "+patternName(ap, ac, mode)); - } + static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) { + FilterGeneric fgen = of(kind, pos, filter.type(), target.type()); + return fgen.makeInstance(kind, pos, filter, target); + } + + /** Return the adapter information for this target and filter type. */ + static FilterGeneric of(Kind kind, int pos, MethodType filterType, MethodType targetType) { + MethodType entryType = entryType(kind, pos, filterType, targetType); + if (entryType.generic() != entryType) + throw newIllegalArgumentException("must be generic: "+entryType); + MethodTypeImpl form = MethodTypeImpl.of(entryType); + FilterGeneric filterGen = form.filterGeneric; + if (filterGen == null) + form.filterGeneric = filterGen = new FilterGeneric(entryType); + return filterGen; } public String toString() { - return "FilterGeneric/"+patternName()+targetType; - } - - String patternName() { - return patternName(argumentPosition, argumentCount, replaceMode); - } - - static String patternName(short ap, short ac, char mode) { - return ""+mode+ap+(ac>1?"_"+ac:""); - } - - Class filterType() { - return Object.class; // result of filter operation; an uninteresting type + return "FilterGeneric/"+entryType; } - static MethodType targetType(MethodType entryType, short ap, short ac, char mode, - Class arg) { + static MethodType targetType(MethodType entryType, Kind kind, int pos, MethodType filterType) { MethodType type = entryType; - int pos = ap; - switch (mode) { - case 'A': - pos += ac; - case 'P': - type = type.insertParameterType(pos, arg); + switch (kind) { + case value: + case flyby: + break; // no change + case fold: + type = type.insertParameterTypes(0, filterType.returnType()); break; - case 'I': - for (int i = 1; i < ac; i++) - type = type.dropParameterType(pos); - assert(type.parameterType(pos) == arg); + case collect: + type = type.dropParameterTypes(pos, type.parameterCount()); + type = type.insertParameterTypes(pos, filterType.returnType()); break; - case 'D': - break; + default: + throw new InternalError(); } return type; } - static MethodType entryType(MethodType targetType, short ap, short ac, char mode, - Class arg) { + static MethodType entryType(Kind kind, int pos, MethodType filterType, MethodType targetType) { MethodType type = targetType; - int pos = ap; - switch (mode) { - case 'A': - pos += ac; - case 'P': - type = type.dropParameterType(pos); + switch (kind) { + case value: + case flyby: + break; // no change + case fold: + type = type.dropParameterTypes(0, 1); break; - case 'I': - for (int i = 1; i < ac; i++) - type = type.insertParameterType(pos, arg); - assert(type.parameterType(pos) == arg); + case collect: + type = type.dropParameterTypes(pos, pos+1); + type = type.insertParameterTypes(pos, filterType.parameterList()); break; - case 'D': - break; + default: + throw new InternalError(); } return type; } /* Create an adapter that handles spreading calls for the given type. */ - static Adapter findAdapter(MethodType targetType, short ap, short ac, char mode, Class arg) { - MethodType entryType = entryType(targetType, ap, ac, mode, arg); - int argc = targetType.parameterCount(); - String pname = patternName(ap, ac, mode); + static Adapter findAdapter(MethodType entryType, Kind kind, int pos) { + int argc = entryType.parameterCount(); String cname0 = "F"+argc; - String cname1 = "F"+argc+mode; - String cname2 = "F"+argc+pname; - String[] cnames = { cname0, cname1, cname1+"X", cname2 }; - String iname = "invoke_"+pname; - // e.g., F5R; invoke_R3 + String cname1 = "F"+argc+kind.key; + String[] cnames = { cname0, cname1 }; + String iname = kind.invokerName(pos); + // e.g., F5; invoke_C3 for (String cname : cnames) { Class acls = Adapter.findSubClass(cname); if (acls == null) continue; @@ -220,7 +205,10 @@ // Produce an instance configured as a prototype. return ctor.newInstance(entryPoint); } catch (IllegalArgumentException ex) { - } catch (InvocationTargetException ex) { + } catch (InvocationTargetException wex) { + Throwable ex = wex.getTargetException(); + if (ex instanceof Error) throw (Error)ex; + if (ex instanceof RuntimeException) throw (RuntimeException)ex; } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } @@ -228,7 +216,7 @@ return null; } - static Adapter buildAdapterFromBytecodes(MethodType targetType, short ap, short ac, char mode, Class arg) { + static Adapter buildAdapterFromBytecodes(MethodType entryType, Kind kind, int pos) { throw new UnsupportedOperationException("NYI"); } @@ -242,8 +230,13 @@ * generated once per type erasure family, and reused across adapters. */ static abstract class Adapter extends JavaMethodHandle { - protected final MethodHandle filter; - protected final MethodHandle target; + protected final MethodHandle filter; // transforms one or more arguments + protected final MethodHandle target; // ultimate target + + @Override + public String toString() { + return target.toString(); + } protected boolean isPrototype() { return target == null; } protected Adapter(MethodHandle entryPoint) { @@ -287,52 +280,4221 @@ } } - //* generated classes follow this pattern: - static class F1RX extends Adapter { - protected F1RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype - protected F1RX(MethodHandle e, MethodHandle f, MethodHandle t) - { super(e, f, t); } - protected F1RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) - { return new F1RX(e, f, t); } - protected Object filter(Object a0) { return filter.invoke(a0); } - protected Object target(Object a0) { return target.invoke(a0); } - protected Object invoke_R0(Object a0) { return target(filter(a0)); } - } - static class F2RX extends Adapter { - protected F2RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype - protected F2RX(MethodHandle e, MethodHandle f, MethodHandle t) - { super(e, f, t); } - protected F2RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) - { return new F2RX(e, f, t); } - protected Object filter(Object a0) { return filter.invoke(a0); } - protected Object target(Object a0, Object a1) { return target.invoke(a0, a1); } - protected Object invoke_R0(Object a0, Object a1) { return target(filter(a0), a1); } - protected Object invoke_R1(Object a0, Object a1) { return target(a0, filter(a1)); } + static enum Kind { + value('V'), // filter and replace Nth argument value + fold('F'), // fold first N arguments, prepend result + collect('C'), // collect last N arguments, replace with result + flyby('Y'), // reify entire argument list, filter, pass to target + LIMIT('?'); + static final int COUNT = LIMIT.ordinal(); + + final char key; + Kind(char key) { this.key = key; } + String invokerName(int pos) { return "invoke_"+key+""+pos; } + int invokerIndex(int pos) { return pos * COUNT + ordinal(); } } - static class F3RX extends Adapter { - protected F3RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype - protected F3RX(MethodHandle e, MethodHandle f, MethodHandle t) + + /* generated classes follow this pattern: + static class F1X extends Adapter { + protected F1X(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F1X(MethodHandle e, MethodHandle f, MethodHandle t) { super(e, f, t); } - protected F3RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) - { return new F3RX(e, f, t); } - protected Object filter(Object a0) { return filter.invoke(a0); } - protected Object target(Object a0, Object a1, Object a2) { return target.invoke(a0, a1, a2); } - protected Object invoke_R0(Object a0, Object a1, Object a2) { return target(filter(a0), a1, a2); } - protected Object invoke_R1(Object a0, Object a1, Object a2) { return target(a0, filter(a1), a2); } - protected Object invoke_R2(Object a0, Object a1, Object a2) { return target(a0, a1, filter(a2)); } + protected F1X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) + { return new F1X(e, f, t); } + protected Object invoke_V0(Object a0) { return target.invoke(filter.invoke(a0)); } + protected Object invoke_F0(Object a0) { return target.invoke(filter.invoke(), a0); } + protected Object invoke_F1(Object a0) { return target.invoke(filter.invoke(a0), a0); } + protected Object invoke_C0(Object a0) { return target.invoke(filter.invoke(a0)); } + protected Object invoke_C1(Object a0) { return target.invoke(a0, filter.invoke()); } + protected Object invoke_Y0(Object a0) { Object[] av = { a0 }; + filter.invoke(av); return target.invoke(av[0]); } } - static class F4RX extends Adapter { - protected F4RX(MethodHandle entryPoint) { super(entryPoint); } // to build prototype - protected F4RX(MethodHandle e, MethodHandle f, MethodHandle t) + static class F2X extends Adapter { + protected F2X(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F2X(MethodHandle e, MethodHandle f, MethodHandle t) { super(e, f, t); } - protected F4RX makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) - { return new F4RX(e, f, t); } - protected Object filter(Object a0) { return filter.invoke(a0); } - protected Object target(Object a0, Object a1, Object a2, Object a3) { return target.invoke(a0, a1, a2, a3); } - protected Object invoke_R0(Object a0, Object a1, Object a2, Object a3) { return target(filter(a0), a1, a2, a3); } - protected Object invoke_R1(Object a0, Object a1, Object a2, Object a3) { return target(a0, filter(a1), a2, a3); } - protected Object invoke_R2(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, filter(a2), a3); } - protected Object invoke_R3(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, filter(a3)); } + protected F2X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) + { return new F2X(e, f, t); } + protected Object invoke_V0(Object a0, Object a1) { return target.invoke(filter.invoke(a0), a1); } + protected Object invoke_V1(Object a0, Object a1) { return target.invoke(a0, filter.invoke(a1)); } + protected Object invoke_F0(Object a0, Object a1) { return target.invoke(filter.invoke(), a0, a1); } + protected Object invoke_F1(Object a0, Object a1) { return target.invoke(filter.invoke(a0), a0, a1); } + protected Object invoke_F2(Object a0, Object a1) { return target.invoke(filter.invoke(a0, a1), a0, a1); } + protected Object invoke_C0(Object a0, Object a1) { return target.invoke(filter.invoke(a0, a1)); } + protected Object invoke_C1(Object a0, Object a1) { return target.invoke(a0, filter.invoke(a1)); } + protected Object invoke_C2(Object a0, Object a1) { return target.invoke(a0, a1, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 }; + filter.invoke(av); return target.invoke(av[0], av[1]); } } // */ + + // This one is written by hand: + static class F0 extends Adapter { + protected F0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F0(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F0 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F0(e, f, t); } + protected Object invoke_F0() throws Throwable { + return target.invoke(filter.invoke()); } + protected Object invoke_C0() throws Throwable { + return target.invoke(filter.invoke()); } + static final Object[] NO_ARGS = { }; + protected Object invoke_Y0() throws Throwable { + filter.invoke(NO_ARGS); // make the flyby + return target.invoke(); } + } + +/* + : SHELL; n=FilterGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -ea -cp . genclasses | sed 's| *[/]/ *$||') >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~ +//{{{ +import java.util.*; +class genclasses { + static String[][] TEMPLATES = { { + "@for@ N=1..20", + " //@each-cat@", + " static class @cat@ extends Adapter {", + " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype", + " protected @cat@(MethodHandle e, MethodHandle f, MethodHandle t) {", + " super(e, f, t); }", + " protected @cat@ makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {", + " return new @cat@(e, f, t); }", + " //@each-P@", + " protected Object invoke_V@P@(@Tvav@) throws Throwable {", + " return target.invoke(@a0_@@Psp@filter.invoke(a@P@)@_aN@); }", + " //@end-P@", + " //@each-P@", + " protected Object invoke_F@P@(@Tvav@) throws Throwable {", + " return target.invoke(filter.invoke(@a0@),", + " @av@); }", + " //@end-P@", + " protected Object invoke_F@N@(@Tvav@) throws Throwable {", + " return target.invoke(filter.invoke(@av@),", + " @av@); }", + " //@each-P@", + " protected Object invoke_C@P@(@Tvav@) throws Throwable {", + " return target.invoke(@a0_@filter.invoke(a@P@@_aN@)); }", + " //@end-P@", + " protected Object invoke_C@N@(@Tvav@) throws Throwable {", + " return target.invoke(@av@, filter.invoke()); }", + " protected Object invoke_Y0(@Tvav@) throws Throwable {", + " Object[] av = { @av@ };", + " filter.invoke(av); // make the flyby", + " return target.invoke(@av[i]@); }", + " }", + } }; + static final String NEWLINE_INDENT = " //\n "; + enum VAR { + cat, N, P, Tvav, av, a0, a0_, _aN, Psp, av_i_; + public final String pattern = "@"+toString().replace('_','.')+"@"; + public String binding = toString(); + static void makeBindings(boolean topLevel, int inargs, int pos) { + assert(-1 <= pos && pos < inargs); + VAR.cat.binding = "F"+inargs; + VAR.N.binding = String.valueOf(inargs); // incoming arg count + VAR.P.binding = String.valueOf(pos); // selected arg position + String[] av = new String[inargs]; + String[] Tvav = new String[inargs]; + String[] av_i_ = new String[inargs]; + for (int i = 0; i < inargs; i++) { + av[i] = arg(i); + av_i_[i] = "av["+i+"]"; + String spc = ""; + if (i > 0 && i % 4 == 0) spc = NEWLINE_INDENT+(pos>9?" ":"")+" "; + Tvav[i] = spc+param("Object", av[i]); + } + VAR.av.binding = comma(av); + VAR.av_i_.binding = comma(av_i_); + VAR.Tvav.binding = comma(Tvav); + if (pos >= 0) { + VAR.Psp.binding = (pos > 0 && pos % 10 == 0) ? NEWLINE_INDENT : ""; + String[] a0 = new String[pos]; + String[] aN = new String[inargs - (pos+1)]; + for (int i = 0; i < pos; i++) { + String spc = ""; + if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT; + a0[i] = spc+av[i]; + } + VAR.a0.binding = comma(a0); + VAR.a0_.binding = comma(a0, ", "); + for (int i = pos+1; i < inargs; i++) { + String spc = ""; + if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT; + aN[i - (pos+1)] = spc+av[i]; + } + VAR._aN.binding = comma(", ", aN); + } + } + static String arg(int i) { return "a"+i; } + static String param(String t, String a) { return t+" "+a; } + static String comma(String[] v) { return comma(v, ""); } + static String comma(String[] v, String sep) { return comma("", v, sep); } + static String comma(String sep, String[] v) { return comma(sep, v, ""); } + static String comma(String sep1, String[] v, String sep2) { + if (v.length == 0) return ""; + String res = v[0]; + for (int i = 1; i < v.length; i++) res += ", "+v[i]; + return sep1 + res + sep2; + } + static String transform(String string) { + for (VAR var : values()) + string = string.replaceAll(var.pattern, var.binding); + return string; + } + } + static String[] stringsIn(String[] strings, int beg, int end) { + return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length)); + } + static String[] stringsBefore(String[] strings, int pos) { + return stringsIn(strings, 0, pos); + } + static String[] stringsAfter(String[] strings, int pos) { + return stringsIn(strings, pos, strings.length); + } + static int indexAfter(String[] strings, int pos, String tag) { + return Math.min(indexBefore(strings, pos, tag) + 1, strings.length); + } + static int indexBefore(String[] strings, int pos, String tag) { + for (int i = pos, end = strings.length; ; i++) { + if (i == end || strings[i].endsWith(tag)) return i; + } + } + static int MIN_ARITY, MAX_ARITY; + public static void main(String... av) { + for (String[] template : TEMPLATES) { + int forLinesLimit = indexBefore(template, 0, "@each-cat@"); + String[] forLines = stringsBefore(template, forLinesLimit); + template = stringsAfter(template, forLinesLimit); + for (String forLine : forLines) + expandTemplate(forLine, template); + } + } + static void expandTemplate(String forLine, String[] template) { + String[] params = forLine.split("[^0-9]+"); + if (params[0].length() == 0) params = stringsAfter(params, 1); + System.out.println("//params="+Arrays.asList(params)); + int pcur = 0; + MIN_ARITY = Integer.valueOf(params[pcur++]); + MAX_ARITY = Integer.valueOf(params[pcur++]); + if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine); + for (int inargs = MIN_ARITY; inargs <= MAX_ARITY; inargs++) { + expandTemplate(template, true, inargs, -1); + } + } + static void expandTemplate(String[] template, boolean topLevel, int inargs, int pos) { + VAR.makeBindings(topLevel, inargs, pos); + for (int i = 0; i < template.length; i++) { + String line = template[i]; + if (line.endsWith("@each-cat@")) { + // ignore + } else if (line.endsWith("@each-P@")) { + int blockEnd = indexAfter(template, i, "@end-P@"); + String[] block = stringsIn(template, i+1, blockEnd-1); + for (int pos1 = Math.max(0,pos); pos1 < inargs; pos1++) + expandTemplate(block, false, inargs, pos1); + VAR.makeBindings(topLevel, inargs, pos); + i = blockEnd-1; continue; + } else { + System.out.println(VAR.transform(line)); + } + } + } } +//}}} */ +//params=[1, 20] + static class F1 extends Adapter { + protected F1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F1(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F1 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F1(e, f, t); } + protected Object invoke_V0(Object a0) throws Throwable { + return target.invoke(filter.invoke(a0)); } + protected Object invoke_F0(Object a0) throws Throwable { + return target.invoke(filter.invoke(), + a0); } + protected Object invoke_F1(Object a0) throws Throwable { + return target.invoke(filter.invoke(a0), + a0); } + protected Object invoke_C0(Object a0) throws Throwable { + return target.invoke(filter.invoke(a0)); } + protected Object invoke_C1(Object a0) throws Throwable { + return target.invoke(a0, filter.invoke()); } + protected Object invoke_Y0(Object a0) throws Throwable { + Object[] av = { a0 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0]); } + } + static class F2 extends Adapter { + protected F2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F2(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F2 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F2(e, f, t); } + protected Object invoke_V0(Object a0, Object a1) throws Throwable { + return target.invoke(filter.invoke(a0), a1); } + protected Object invoke_V1(Object a0, Object a1) throws Throwable { + return target.invoke(a0, filter.invoke(a1)); } + protected Object invoke_F0(Object a0, Object a1) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1); } + protected Object invoke_F1(Object a0, Object a1) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1); } + protected Object invoke_F2(Object a0, Object a1) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1); } + protected Object invoke_C0(Object a0, Object a1) throws Throwable { + return target.invoke(filter.invoke(a0, a1)); } + protected Object invoke_C1(Object a0, Object a1) throws Throwable { + return target.invoke(a0, filter.invoke(a1)); } + protected Object invoke_C2(Object a0, Object a1) throws Throwable { + return target.invoke(a0, a1, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1) throws Throwable { + Object[] av = { a0, a1 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1]); } + } + static class F3 extends Adapter { + protected F3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F3(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F3 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F3(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2); } + protected Object invoke_V1(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2); } + protected Object invoke_V2(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2)); } + protected Object invoke_F0(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2); } + protected Object invoke_F1(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2); } + protected Object invoke_F2(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2); } + protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2); } + protected Object invoke_C0(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2)); } + protected Object invoke_C1(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2)); } + protected Object invoke_C2(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2)); } + protected Object invoke_C3(Object a0, Object a1, Object a2) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable { + Object[] av = { a0, a1, a2 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2]); } + } + static class F4 extends Adapter { + protected F4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F4(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F4 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F4(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable { + Object[] av = { a0, a1, a2, a3 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3]); } + } + static class F5 extends Adapter { + protected F5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F5(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F5 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F5(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4]); } + } + static class F6 extends Adapter { + protected F6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F6(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F6 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F6(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5]); } + } + static class F7 extends Adapter { + protected F7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F7(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F7 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F7(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6]); } + } + static class F8 extends Adapter { + protected F8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F8(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F8 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F8(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7]); } + } + static class F9 extends Adapter { + protected F9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F9(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F9 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F9(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8]); } + } + static class F10 extends Adapter { + protected F10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F10(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F10 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F10(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9]); } + } + static class F11 extends Adapter { + protected F11(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F11(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F11 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F11(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10]); } + } + static class F12 extends Adapter { + protected F12(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F12(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F12 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F12(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11]); } + } + static class F13 extends Adapter { + protected F13(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F13(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F13 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F13(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12]); } + } + static class F14 extends Adapter { + protected F14(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F14(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F14 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F14(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12, a13); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12, a13); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12, a13); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12, a13); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12, a13); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12), a13); } + protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12, a13)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12, a13)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12, a13)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12, a13)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13)); } + protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13]); } + } + static class F15 extends Adapter { + protected F15(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F15(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F15 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F15(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12, a13, a14); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12, a13, a14); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12, a13, a14); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12, a13, a14); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12), a13, a14); } + protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13), a14); } + protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12, a13, a14)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12, a13, a14)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12, a13, a14)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13, a14)); } + protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14)); } + protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14]); } + } + static class F16 extends Adapter { + protected F16(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F16(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F16 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F16(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12, a13, a14, a15); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12, a13, a14, a15); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12, a13, a14, a15); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12), a13, a14, a15); } + protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13), a14, a15); } + protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14), a15); } + protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12, a13, a14, a15)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12, a13, a14, a15)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13, a14, a15)); } + protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14, a15)); } + protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15)); } + protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15]); } + } + static class F17 extends Adapter { + protected F17(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F17(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F17 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F17(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12, a13, a14, a15, a16); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12, a13, a14, a15, a16); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12), a13, a14, a15, a16); } + protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13), a14, a15, a16); } + protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14), a15, a16); } + protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15), a16); } + protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12, a13, a14, a15, a16)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12, a13, a14, a15, a16)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13, a14, a15, a16)); } + protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14, a15, a16)); } + protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15, a16)); } + protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16)); } + protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16]); } + } + static class F18 extends Adapter { + protected F18(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F18(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F18 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F18(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12, a13, a14, a15, a16, a17); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12), a13, a14, a15, a16, a17); } + protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13), a14, a15, a16, a17); } + protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14), a15, a16, a17); } + protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15), a16, a17); } + protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16), a17); } + protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12, a13, a14, a15, a16, a17)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13, a14, a15, a16, a17)); } + protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14, a15, a16, a17)); } + protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15, a16, a17)); } + protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16, a17)); } + protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17)); } + protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17]); } + } + static class F19 extends Adapter { + protected F19(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F19(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F19 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F19(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12), a13, a14, a15, a16, a17, a18); } + protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13), a14, a15, a16, a17, a18); } + protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14), a15, a16, a17, a18); } + protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15), a16, a17, a18); } + protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16), a17, a18); } + protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17), a18); } + protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12, a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13, a14, a15, a16, a17, a18)); } + protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14, a15, a16, a17, a18)); } + protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15, a16, a17, a18)); } + protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16, a17, a18)); } + protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17, a18)); } + protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18)); } + protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18]); } + } + static class F20 extends Adapter { + protected F20(MethodHandle entryPoint) { super(entryPoint); } // to build prototype + protected F20(MethodHandle e, MethodHandle f, MethodHandle t) { + super(e, f, t); } + protected F20 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) { + return new F20(e, f, t); } + protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, filter.invoke(a1), a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2), a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3), a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4), a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5), a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6), a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7), a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8), a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9), + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + filter.invoke(a10), a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11), a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12), a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13), a14, a15, a16, a17, a18, a19); } + protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14), a15, a16, a17, a18, a19); } + protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15), a16, a17, a18, a19); } + protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16), a17, a18, a19); } + protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17), a18, a19); } + protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18), a19); } + protected Object invoke_V19(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invoke(a19)); } + protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_F20(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19), + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } + protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(filter.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, filter.invoke(a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, filter.invoke(a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, filter.invoke(a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, filter.invoke(a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, filter.invoke(a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, filter.invoke(a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, filter.invoke(a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, filter.invoke(a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invoke(a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invoke(a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, filter.invoke(a11, a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, filter.invoke(a12, a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, filter.invoke(a13, a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, filter.invoke(a14, a15, a16, a17, a18, a19)); } + protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, filter.invoke(a15, a16, a17, a18, a19)); } + protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, filter.invoke(a16, a17, a18, a19)); } + protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, filter.invoke(a17, a18, a19)); } + protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, filter.invoke(a18, a19)); } + protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invoke(a19)); } + protected Object invoke_C20(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, filter.invoke()); } + protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9, Object a10, Object a11, + Object a12, Object a13, Object a14, Object a15, + Object a16, Object a17, Object a18, Object a19) throws Throwable { + Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 }; + filter.invoke(av); // make the flyby + return target.invoke(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18], av[19]); } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/FilterOneArgument.java --- a/jdk/src/share/classes/sun/dyn/FilterOneArgument.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/FilterOneArgument.java Wed Jul 05 17:05:01 2017 +0200 @@ -27,7 +27,6 @@ import java.dyn.JavaMethodHandle; import java.dyn.MethodHandle; -import java.dyn.MethodHandles; import java.dyn.MethodType; /** @@ -42,16 +41,21 @@ protected final MethodHandle filter; // Object -> Object protected final MethodHandle target; // Object -> Object - protected Object entryPoint(Object argument) { - Object filteredArgument = filter.invoke(argument); - return target.invoke(filteredArgument); + @Override + public String toString() { + return target.toString(); } - private static final MethodHandle entryPoint = - MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "entryPoint", MethodType.makeGeneric(1)); + protected Object invoke(Object argument) throws Throwable { + Object filteredArgument = filter.invoke(argument); + return target.invoke(filteredArgument); + } + + private static final MethodHandle INVOKE = + MethodHandleImpl.IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke", MethodType.genericMethodType(1)); protected FilterOneArgument(MethodHandle filter, MethodHandle target) { - super(entryPoint); + super(INVOKE); this.filter = filter; this.target = target; } @@ -62,10 +66,6 @@ return new FilterOneArgument(filter, target); } - public String toString() { - return filter + "|>" + target; - } - // MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) { // MethodHandle filter = make(filter1, filter2); // return make(filter, target); diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/FromGeneric.java --- a/jdk/src/share/classes/sun/dyn/FromGeneric.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/FromGeneric.java Wed Jul 05 17:05:01 2017 +0200 @@ -36,8 +36,8 @@ import sun.dyn.util.Wrapper; /** - * Adapters which mediate between incoming calls which are not generic - * and outgoing calls which are. Any call can be represented generically + * Adapters which mediate between incoming calls which are generic + * and outgoing calls which are not. Any call can be represented generically * boxing up its arguments, and (on return) unboxing the return value. *

    * A call is "generic" (in MethodHandle terms) if its MethodType features @@ -50,9 +50,6 @@ * either binds internally or else takes as a leading argument). * (To stretch the term, adapter-like method handles may have multiple * targets or be polymorphic across multiple call types.) - *

    - * This adapter can sometimes be more directly implemented - * by the JVM's built-in OP_SPREAD_ARGS adapter. * @author jrose */ class FromGeneric { @@ -99,7 +96,7 @@ } this.internalType = internalType0; this.adapter = ad; - MethodType tepType = targetType.insertParameterType(0, adapter.getClass()); + MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass()); this.entryPoint = ad.prototypeEntryPoint(); this.returnConversion = computeReturnConversion(targetType, internalType0); this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0); @@ -146,7 +143,7 @@ if (fixArgs == null) throw new InternalError("bad fixArgs"); // reinterpret the calling sequence as raw: - MethodHandle retyper = AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, + MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, Invokers.invokerType(internalType), fixArgs); if (retyper == null) throw new InternalError("bad retyper"); @@ -226,7 +223,10 @@ // Produce an instance configured as a prototype. return ctor.newInstance(entryPoint); } catch (IllegalArgumentException ex) { - } catch (InvocationTargetException ex) { + } catch (InvocationTargetException wex) { + Throwable ex = wex.getTargetException(); + if (ex instanceof Error) throw (Error)ex; + if (ex instanceof RuntimeException) throw (RuntimeException)ex; } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } @@ -260,6 +260,11 @@ protected final MethodHandle convert; // raw(R) => Object protected final MethodHandle target; // (any**N) => R + @Override + public String toString() { + return target.toString(); + } + protected boolean isPrototype() { return target == null; } protected Adapter(MethodHandle entryPoint) { this(entryPoint, null, entryPoint, null); @@ -284,11 +289,11 @@ // { return new ThisType(entryPoint, convert, target); } /// Conversions on the value returned from the target. - protected Object convert_L(Object result) { return convert.invoke(result); } - protected Object convert_I(int result) { return convert.invoke(result); } - protected Object convert_J(long result) { return convert.invoke(result); } - protected Object convert_F(float result) { return convert.invoke(result); } - protected Object convert_D(double result) { return convert.invoke(result); } + protected Object convert_L(Object result) throws Throwable { return convert.invoke(result); } + protected Object convert_I(int result) throws Throwable { return convert.invoke(result); } + protected Object convert_J(long result) throws Throwable { return convert.invoke(result); } + protected Object convert_F(float result) throws Throwable { return convert.invoke(result); } + protected Object convert_D(double result) throws Throwable { return convert.invoke(result); } static private final String CLASS_PREFIX; // "sun.dyn.FromGeneric$" static { @@ -317,11 +322,11 @@ { super(e, i, c, t); } protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new xA2(e, i, c, t); } - protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.invoke(target, a0, a1)); } - protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.invoke(target, a0, a1)); } - protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.invoke(target, a0, a1)); } - protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.invoke(target, a0, a1)); } - protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.invoke(target, a0, a1)); } + protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.invoke(target, a0, a1)); } + protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.invoke(target, a0, a1)); } + protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.invoke(target, a0, a1)); } + protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.invoke(target, a0, a1)); } + protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.invoke(target, a0, a1)); } } // */ @@ -342,7 +347,7 @@ " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)", " { return new @cat@(e, i, c, t); }", " //@each-R@", - " protected Object invoke_@catN@(@Tvav@) { return convert_@Rc@(invoker.<@R@>invoke(target@av@)); }", + " protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@(invoker.<@R@>invoke(target@av@)); }", " //@end-R@", " }", } }; @@ -498,11 +503,11 @@ { super(e, i, c, t); } protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); } - protected Object invoke_L0() { return convert_L(invoker.invoke(target)); } - protected Object invoke_I0() { return convert_I(invoker.invoke(target)); } - protected Object invoke_J0() { return convert_J(invoker.invoke(target)); } - protected Object invoke_F0() { return convert_F(invoker.invoke(target)); } - protected Object invoke_D0() { return convert_D(invoker.invoke(target)); } + protected Object invoke_L0() throws Throwable { return convert_L(invoker.invoke(target)); } + protected Object invoke_I0() throws Throwable { return convert_I(invoker.invoke(target)); } + protected Object invoke_J0() throws Throwable { return convert_J(invoker.invoke(target)); } + protected Object invoke_F0() throws Throwable { return convert_F(invoker.invoke(target)); } + protected Object invoke_D0() throws Throwable { return convert_D(invoker.invoke(target)); } } static class A1 extends Adapter { protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -510,11 +515,11 @@ { super(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } - protected Object invoke_L1(Object a0) { return convert_L(invoker.invoke(target, a0)); } - protected Object invoke_I1(Object a0) { return convert_I(invoker.invoke(target, a0)); } - protected Object invoke_J1(Object a0) { return convert_J(invoker.invoke(target, a0)); } - protected Object invoke_F1(Object a0) { return convert_F(invoker.invoke(target, a0)); } - protected Object invoke_D1(Object a0) { return convert_D(invoker.invoke(target, a0)); } + protected Object invoke_L1(Object a0) throws Throwable { return convert_L(invoker.invoke(target, a0)); } + protected Object invoke_I1(Object a0) throws Throwable { return convert_I(invoker.invoke(target, a0)); } + protected Object invoke_J1(Object a0) throws Throwable { return convert_J(invoker.invoke(target, a0)); } + protected Object invoke_F1(Object a0) throws Throwable { return convert_F(invoker.invoke(target, a0)); } + protected Object invoke_D1(Object a0) throws Throwable { return convert_D(invoker.invoke(target, a0)); } } static class A2 extends Adapter { protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -522,11 +527,11 @@ { super(e, i, c, t); } protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); } - protected Object invoke_L2(Object a0, Object a1) { return convert_L(invoker.invoke(target, a0, a1)); } - protected Object invoke_I2(Object a0, Object a1) { return convert_I(invoker.invoke(target, a0, a1)); } - protected Object invoke_J2(Object a0, Object a1) { return convert_J(invoker.invoke(target, a0, a1)); } - protected Object invoke_F2(Object a0, Object a1) { return convert_F(invoker.invoke(target, a0, a1)); } - protected Object invoke_D2(Object a0, Object a1) { return convert_D(invoker.invoke(target, a0, a1)); } + protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L(invoker.invoke(target, a0, a1)); } + protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I(invoker.invoke(target, a0, a1)); } + protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J(invoker.invoke(target, a0, a1)); } + protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F(invoker.invoke(target, a0, a1)); } + protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D(invoker.invoke(target, a0, a1)); } } static class A3 extends Adapter { protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -534,11 +539,11 @@ { super(e, i, c, t); } protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); } - protected Object invoke_L3(Object a0, Object a1, Object a2) { return convert_L(invoker.invoke(target, a0, a1, a2)); } - protected Object invoke_I3(Object a0, Object a1, Object a2) { return convert_I(invoker.invoke(target, a0, a1, a2)); } - protected Object invoke_J3(Object a0, Object a1, Object a2) { return convert_J(invoker.invoke(target, a0, a1, a2)); } - protected Object invoke_F3(Object a0, Object a1, Object a2) { return convert_F(invoker.invoke(target, a0, a1, a2)); } - protected Object invoke_D3(Object a0, Object a1, Object a2) { return convert_D(invoker.invoke(target, a0, a1, a2)); } + protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2)); } + protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2)); } + protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2)); } + protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2)); } + protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2)); } } static class A4 extends Adapter { protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -546,11 +551,11 @@ { super(e, i, c, t); } protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); } - protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) { return convert_L(invoker.invoke(target, a0, a1, a2, a3)); } - protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) { return convert_I(invoker.invoke(target, a0, a1, a2, a3)); } - protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) { return convert_J(invoker.invoke(target, a0, a1, a2, a3)); } - protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) { return convert_F(invoker.invoke(target, a0, a1, a2, a3)); } - protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) { return convert_D(invoker.invoke(target, a0, a1, a2, a3)); } + protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2, a3)); } + protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2, a3)); } + protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2, a3)); } + protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2, a3)); } + protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2, a3)); } } static class A5 extends Adapter { protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -558,11 +563,11 @@ { super(e, i, c, t); } protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); } - protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4)); } - protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4)); } - protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4)); } - protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4)); } - protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4)); } + protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4)); } + protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4)); } + protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4)); } + protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4)); } + protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4)); } } static class A6 extends Adapter { protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -570,11 +575,11 @@ { super(e, i, c, t); } protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); } - protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } - protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } + protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5)); } } static class A7 extends Adapter { protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -582,11 +587,11 @@ { super(e, i, c, t); } protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); } - protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6)); } } static class A8 extends Adapter { protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -594,11 +599,11 @@ { super(e, i, c, t); } protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); } - protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7)); } } static class A9 extends Adapter { protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -606,11 +611,11 @@ { super(e, i, c, t); } protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); } - protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); } } static class A10 extends Adapter { protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype @@ -618,10 +623,10 @@ { super(e, i, c, t); } protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); } - protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D(invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/Invokers.java --- a/jdk/src/share/classes/sun/dyn/Invokers.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/Invokers.java Wed Jul 05 17:05:01 2017 +0200 @@ -44,16 +44,20 @@ // generic (untyped) invoker for the outgoing call private /*lazy*/ MethodHandle genericInvoker; + // generic (untyped) invoker for the outgoing call; accepts a single Object[] + private final /*lazy*/ MethodHandle[] varargsInvokers; + /** Compute and cache information common to all collecting adapters * that implement members of the erasure-family of the given erased type. */ public Invokers(Access token, MethodType targetType) { Access.check(token); this.targetType = targetType; + this.varargsInvokers = new MethodHandle[targetType.parameterCount()+1]; } public static MethodType invokerType(MethodType targetType) { - return targetType.insertParameterType(0, MethodHandle.class); + return targetType.insertParameterTypes(0, MethodHandle.class); } public MethodHandle exactInvoker() { @@ -76,8 +80,14 @@ return invoker; } - public MethodHandle varargsInvoker() { - throw new UnsupportedOperationException("NYI"); + public MethodHandle varargsInvoker(int objectArgCount) { + MethodHandle vaInvoker = varargsInvokers[objectArgCount]; + if (vaInvoker != null) return vaInvoker; + MethodHandle gInvoker = genericInvoker(); + MethodType vaType = MethodType.genericMethodType(objectArgCount, true); + vaInvoker = MethodHandles.spreadArguments(gInvoker, invokerType(vaType)); + varargsInvokers[objectArgCount] = vaInvoker; + return vaInvoker; } public String toString() { diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/MemberName.java --- a/jdk/src/share/classes/sun/dyn/MemberName.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/MemberName.java Wed Jul 05 17:05:01 2017 +0200 @@ -25,7 +25,7 @@ package sun.dyn; -import sun.dyn.util.BytecodeSignature; +import sun.dyn.util.BytecodeDescriptor; import java.dyn.*; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -33,6 +33,7 @@ import java.lang.reflect.Member; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -93,7 +94,7 @@ } if (type instanceof String) { String sig = (String) type; - MethodType res = MethodType.fromBytecodeString(sig, getClassLoader()); + MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader()); this.type = res; return res; } @@ -101,7 +102,7 @@ Object[] typeInfo = (Object[]) type; Class[] ptypes = (Class[]) typeInfo[1]; Class rtype = (Class) typeInfo[0]; - MethodType res = MethodType.make(rtype, ptypes); + MethodType res = MethodType.methodType(rtype, ptypes); this.type = res; return res; } @@ -111,7 +112,7 @@ public MethodType getInvocationType() { MethodType itype = getMethodType(); if (!isStatic()) - itype = itype.insertParameterType(0, clazz); + itype = itype.insertParameterTypes(0, clazz); return itype; } @@ -135,7 +136,7 @@ } if (type instanceof String) { String sig = (String) type; - MethodType mtype = MethodType.fromBytecodeString("()"+sig, getClassLoader()); + MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader()); Class res = mtype.returnType(); this.type = res; return res; @@ -155,9 +156,9 @@ if (type instanceof String) return (String) type; if (isInvocable()) - return BytecodeSignature.unparse(getMethodType()); + return BytecodeDescriptor.unparse(getMethodType()); else - return BytecodeSignature.unparse(getFieldType()); + return BytecodeDescriptor.unparse(getFieldType()); } public int getModifiers() { @@ -353,6 +354,8 @@ return type.toString(); // class java.lang.String // else it is a field, method, or constructor StringBuilder buf = new StringBuilder(); + if (!isResolved()) + buf.append("*."); if (getDeclaringClass() != null) { buf.append(getName(clazz)); buf.append('.'); @@ -381,7 +384,7 @@ private static String getName(Object obj) { if (obj instanceof Class) return ((Class)obj).getName(); - return obj.toString(); + return String.valueOf(obj); } // Queries to the JVM: @@ -408,6 +411,9 @@ public static NoAccessException newNoAccessException(MemberName name, Class lookupClass) { return newNoAccessException("cannot access", name, lookupClass); } + public static NoAccessException newNoAccessException(MemberName name, MethodHandles.Lookup lookup) { + return newNoAccessException(name, lookup.lookupClass()); + } public static NoAccessException newNoAccessException(String message, MemberName name, Class lookupClass) { message += ": " + name; @@ -436,7 +442,7 @@ matchFlags &= ALLOWED_FLAGS; String matchSig = null; if (matchType != null) { - matchSig = BytecodeSignature.unparse(matchType); + matchSig = BytecodeDescriptor.unparse(matchType); if (matchSig.startsWith("(")) matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE); else @@ -447,17 +453,18 @@ MemberName[] buf = newMemberBuffer(len1); int totalCount = 0; ArrayList bufs = null; + int bufCount = 0; for (;;) { - int bufCount = MethodHandleNatives.getMembers(defc, + bufCount = MethodHandleNatives.getMembers(defc, matchName, matchSig, matchFlags, lookupClass, totalCount, buf); if (bufCount <= buf.length) { - if (bufCount >= 0) - totalCount += bufCount; + if (bufCount < 0) bufCount = 0; + totalCount += bufCount; break; } - // JVM returned tp us with an intentional overflow! + // JVM returned to us with an intentional overflow! totalCount += buf.length; int excess = bufCount - buf.length; if (bufs == null) bufs = new ArrayList(1); @@ -473,7 +480,7 @@ Collections.addAll(result, buf0); } } - Collections.addAll(result, buf); + result.addAll(Arrays.asList(buf).subList(0, bufCount)); // Signature matching is not the same as type matching, since // one signature might correspond to several types. // So if matchType is a Class or MethodType, refilter the results. diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/MethodHandleImpl.java --- a/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/MethodHandleImpl.java Wed Jul 05 17:05:01 2017 +0200 @@ -25,12 +25,25 @@ package sun.dyn; +import java.dyn.JavaMethodHandle; import java.dyn.MethodHandle; import java.dyn.MethodHandles; import java.dyn.MethodHandles.Lookup; import java.dyn.MethodType; +import java.util.logging.Level; +import java.util.logging.Logger; import sun.dyn.util.VerifyType; import java.dyn.NoAccessException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import sun.dyn.empty.Empty; +import sun.dyn.util.ValueConversions; +import sun.dyn.util.Wrapper; +import sun.misc.Unsafe; import static sun.dyn.MemberName.newIllegalArgumentException; import static sun.dyn.MemberName.newNoAccessException; @@ -57,6 +70,25 @@ static final int INT_FIELD = 0; static final long LONG_FIELD = 0; + /** Access methods for the internals of MethodHandle, supplied to + * MethodHandleImpl as a trusted agent. + */ + static public interface MethodHandleFriend { + void initType(MethodHandle mh, MethodType type); + } + public static void setMethodHandleFriend(Access token, MethodHandleFriend am) { + Access.check(token); + if (METHOD_HANDLE_FRIEND != null) + throw new InternalError(); // just once + METHOD_HANDLE_FRIEND = am; + } + static private MethodHandleFriend METHOD_HANDLE_FRIEND; + + // NOT public + static void initType(MethodHandle mh, MethodType type) { + METHOD_HANDLE_FRIEND.initType(mh, type); + } + // type is defined in java.dyn.MethodHandle, which is platform-independent // vmentry (a void* field) is used *only* by by the JVM. @@ -106,8 +138,8 @@ } static { - // Force initialization: - Lookup.PUBLIC_LOOKUP.lookupClass(); + // Force initialization of Lookup, so it calls us back as initLookup: + MethodHandles.publicLookup(); if (IMPL_LOOKUP_INIT == null) throw new InternalError(); } @@ -151,7 +183,7 @@ // adjust the advertised receiver type to be exactly the one requested // (in the case of invokespecial, this will be the calling class) Class recvType = method.getDeclaringClass(); - mtype = mtype.insertParameterType(0, recvType); + mtype = mtype.insertParameterTypes(0, recvType); if (method.isConstructor()) doDispatch = true; // FIXME: JVM has trouble building MH.invoke sites for @@ -170,21 +202,223 @@ public static MethodHandle accessField(Access token, - MemberName member, boolean isSetter, - Class lookupClass) { + MemberName member, boolean isSetter, + Class lookupClass) { Access.check(token); - // FIXME: Use sun.misc.Unsafe to dig up the dirt on the field. - throw new UnsupportedOperationException("Not yet implemented"); + // Use sun. misc.Unsafe to dig up the dirt on the field. + MethodHandle mh = new FieldAccessor(token, member, isSetter); + return mh; } public static MethodHandle accessArrayElement(Access token, - Class arrayClass, boolean isSetter) { + Class arrayClass, boolean isSetter) { Access.check(token); if (!arrayClass.isArray()) throw newIllegalArgumentException("not an array: "+arrayClass); - // FIXME: Use sun.misc.Unsafe to dig up the dirt on the array. - throw new UnsupportedOperationException("Not yet implemented"); + Class elemClass = arrayClass.getComponentType(); + MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass); + if (mhs == null) { + if (!FieldAccessor.doCache(elemClass)) + return FieldAccessor.ahandle(arrayClass, isSetter); + mhs = new MethodHandle[] { + FieldAccessor.ahandle(arrayClass, false), + FieldAccessor.ahandle(arrayClass, true) + }; + if (mhs[0].type().parameterType(0) == Class.class) { + mhs[0] = MethodHandles.insertArguments(mhs[0], 0, elemClass); + mhs[1] = MethodHandles.insertArguments(mhs[1], 0, elemClass); + } + synchronized (FieldAccessor.ARRAY_CACHE) {} // memory barrier + FieldAccessor.ARRAY_CACHE.put(elemClass, mhs); + } + return mhs[isSetter ? 1 : 0]; + } + + static final class FieldAccessor extends JavaMethodHandle { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + final Object base; // for static refs only + final long offset; + final String name; + + public FieldAccessor(Access token, MemberName field, boolean isSetter) { + super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic())); + this.offset = (long) field.getVMIndex(token); + this.name = field.getName(); + this.base = staticBase(field); + } + public String toString() { return name; } + + int getFieldI(C obj) { return unsafe.getInt(obj, offset); } + void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); } + long getFieldJ(C obj) { return unsafe.getLong(obj, offset); } + void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); } + float getFieldF(C obj) { return unsafe.getFloat(obj, offset); } + void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); } + double getFieldD(C obj) { return unsafe.getDouble(obj, offset); } + void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); } + boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); } + void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); } + byte getFieldB(C obj) { return unsafe.getByte(obj, offset); } + void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); } + short getFieldS(C obj) { return unsafe.getShort(obj, offset); } + void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); } + char getFieldC(C obj) { return unsafe.getChar(obj, offset); } + void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); } + @SuppressWarnings("unchecked") + V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); } + @SuppressWarnings("unchecked") + void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); } + // cast (V) is OK here, since we wrap convertArguments around the MH. + + static Object staticBase(MemberName field) { + if (!field.isStatic()) return null; + Class c = field.getDeclaringClass(); + java.lang.reflect.Field f; + try { + // FIXME: Should not have to create 'f' to get this value. + f = c.getDeclaredField(field.getName()); + return unsafe.staticFieldBase(f); + } catch (Exception ee) { + Error e = new InternalError(); + e.initCause(ee); + throw e; + } + } + + int getStaticI() { return unsafe.getInt(base, offset); } + void setStaticI(int x) { unsafe.putInt(base, offset, x); } + long getStaticJ() { return unsafe.getLong(base, offset); } + void setStaticJ(long x) { unsafe.putLong(base, offset, x); } + float getStaticF() { return unsafe.getFloat(base, offset); } + void setStaticF(float x) { unsafe.putFloat(base, offset, x); } + double getStaticD() { return unsafe.getDouble(base, offset); } + void setStaticD(double x) { unsafe.putDouble(base, offset, x); } + boolean getStaticZ() { return unsafe.getBoolean(base, offset); } + void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); } + byte getStaticB() { return unsafe.getByte(base, offset); } + void setStaticB(byte x) { unsafe.putByte(base, offset, x); } + short getStaticS() { return unsafe.getShort(base, offset); } + void setStaticS(short x) { unsafe.putShort(base, offset, x); } + char getStaticC() { return unsafe.getChar(base, offset); } + void setStaticC(char x) { unsafe.putChar(base, offset, x); } + V getStaticL() { return (V) unsafe.getObject(base, offset); } + void setStaticL(V x) { unsafe.putObject(base, offset, x); } + + static String fname(Class vclass, boolean isSetter, boolean isStatic) { + String stem; + if (!isStatic) + stem = (!isSetter ? "getField" : "setField"); + else + stem = (!isSetter ? "getStatic" : "setStatic"); + return stem + Wrapper.basicTypeChar(vclass); + } + static MethodType ftype(Class cclass, Class vclass, boolean isSetter, boolean isStatic) { + MethodType type; + if (!isStatic) { + if (!isSetter) + return MethodType.methodType(vclass, cclass); + else + return MethodType.methodType(void.class, cclass, vclass); + } else { + if (!isSetter) + return MethodType.methodType(vclass); + else + return MethodType.methodType(void.class, vclass); + } + } + static MethodHandle fhandle(Class cclass, Class vclass, boolean isSetter, boolean isStatic) { + String name = FieldAccessor.fname(vclass, isSetter, isStatic); + if (cclass.isPrimitive()) throw newIllegalArgumentException("primitive "+cclass); + Class ecclass = Object.class; //erase this type + Class evclass = vclass; + if (!evclass.isPrimitive()) evclass = Object.class; + MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic); + MethodHandle mh; + try { + mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type); + } catch (NoAccessException ee) { + Error e = new InternalError("name,type="+name+type); + e.initCause(ee); + throw e; + } + if (evclass != vclass || (!isStatic && ecclass != cclass)) { + MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic); + strongType = strongType.insertParameterTypes(0, FieldAccessor.class); + mh = MethodHandles.convertArguments(mh, strongType); + } + return mh; + } + + /// Support for array element access + static final HashMap, MethodHandle[]> ARRAY_CACHE = + new HashMap, MethodHandle[]>(); + // FIXME: Cache on the classes themselves, not here. + static boolean doCache(Class elemClass) { + if (elemClass.isPrimitive()) return true; + ClassLoader cl = elemClass.getClassLoader(); + return cl == null || cl == ClassLoader.getSystemClassLoader(); + } + static int getElementI(int[] a, int i) { return a[i]; } + static void setElementI(int[] a, int i, int x) { a[i] = x; } + static long getElementJ(long[] a, int i) { return a[i]; } + static void setElementJ(long[] a, int i, long x) { a[i] = x; } + static float getElementF(float[] a, int i) { return a[i]; } + static void setElementF(float[] a, int i, float x) { a[i] = x; } + static double getElementD(double[] a, int i) { return a[i]; } + static void setElementD(double[] a, int i, double x) { a[i] = x; } + static boolean getElementZ(boolean[] a, int i) { return a[i]; } + static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; } + static byte getElementB(byte[] a, int i) { return a[i]; } + static void setElementB(byte[] a, int i, byte x) { a[i] = x; } + static short getElementS(short[] a, int i) { return a[i]; } + static void setElementS(short[] a, int i, short x) { a[i] = x; } + static char getElementC(char[] a, int i) { return a[i]; } + static void setElementC(char[] a, int i, char x) { a[i] = x; } + static Object getElementL(Object[] a, int i) { return a[i]; } + static void setElementL(Object[] a, int i, Object x) { a[i] = x; } + static V getElementL(Class aclass, V[] a, int i) { return aclass.cast(a)[i]; } + static void setElementL(Class aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; } + + static String aname(Class aclass, boolean isSetter) { + Class vclass = aclass.getComponentType(); + if (vclass == null) throw new IllegalArgumentException(); + return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass); + } + static MethodType atype(Class aclass, boolean isSetter) { + Class vclass = aclass.getComponentType(); + if (!isSetter) + return MethodType.methodType(vclass, aclass, int.class); + else + return MethodType.methodType(void.class, aclass, int.class, vclass); + } + static MethodHandle ahandle(Class aclass, boolean isSetter) { + Class vclass = aclass.getComponentType(); + String name = FieldAccessor.aname(aclass, isSetter); + Class caclass = null; + if (!vclass.isPrimitive() && vclass != Object.class) { + caclass = aclass; + aclass = Object[].class; + vclass = Object.class; + } + MethodType type = FieldAccessor.atype(aclass, isSetter); + if (caclass != null) + type = type.insertParameterTypes(0, Class.class); + MethodHandle mh; + try { + mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type); + } catch (NoAccessException ee) { + Error e = new InternalError("name,type="+name+type); + e.initCause(ee); + throw e; + } + if (caclass != null) { + MethodType strongType = FieldAccessor.atype(caclass, isSetter); + mh = MethodHandles.insertArguments(mh, 0, caclass); + mh = MethodHandles.convertArguments(mh, strongType); + } + return mh; + } } /** Bind a predetermined first argument to the given direct method handle. @@ -203,8 +437,11 @@ if (info instanceof DirectMethodHandle) { DirectMethodHandle dmh = (DirectMethodHandle) info; if (receiver == null || - dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) - target = dmh; + dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) { + MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0); + MethodType newType = target.type().dropParameterTypes(0, 1); + return convertArguments(token, bmh, newType, bmh.type(), null); + } } } if (target instanceof DirectMethodHandle) @@ -223,7 +460,7 @@ MethodHandle bindArgument(Access token, MethodHandle target, int argnum, Object receiver) { Access.check(token); - throw new UnsupportedOperationException("NYI"); + return new BoundMethodHandle(target, receiver, argnum); } public static MethodHandle convertArguments(Access token, @@ -232,6 +469,189 @@ MethodType oldType, int[] permutationOrNull) { Access.check(token); + if (permutationOrNull != null) { + int outargs = oldType.parameterCount(), inargs = newType.parameterCount(); + if (permutationOrNull.length != outargs) + throw newIllegalArgumentException("wrong number of arguments in permutation"); + // Make the individual outgoing argument types match up first. + Class[] callTypeArgs = new Class[outargs]; + for (int i = 0; i < outargs; i++) + callTypeArgs[i] = newType.parameterType(permutationOrNull[i]); + MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs); + target = convertArguments(token, target, callType, oldType, null); + assert(target != null); + oldType = target.type(); + List goal = new ArrayList(); // i*TOKEN + List state = new ArrayList(); // i*TOKEN + List drops = new ArrayList(); // not tokens + List dups = new ArrayList(); // not tokens + final int TOKEN = 10; // to mark items which are symbolic only + // state represents the argument values coming into target + for (int i = 0; i < outargs; i++) { + state.add(permutationOrNull[i] * TOKEN); + } + // goal represents the desired state + for (int i = 0; i < inargs; i++) { + if (state.contains(i * TOKEN)) { + goal.add(i * TOKEN); + } else { + // adapter must initially drop all unused arguments + drops.add(i); + } + } + // detect duplications + while (state.size() > goal.size()) { + for (int i2 = 0; i2 < state.size(); i2++) { + int arg1 = state.get(i2); + int i1 = state.indexOf(arg1); + if (i1 != i2) { + // found duplicate occurrence at i2 + int arg2 = (inargs++) * TOKEN; + state.set(i2, arg2); + dups.add(goal.indexOf(arg1)); + goal.add(arg2); + } + } + } + assert(state.size() == goal.size()); + int size = goal.size(); + while (!state.equals(goal)) { + // Look for a maximal sequence of adjacent misplaced arguments, + // and try to rotate them into place. + int bestRotArg = -10 * TOKEN, bestRotLen = 0; + int thisRotArg = -10 * TOKEN, thisRotLen = 0; + for (int i = 0; i < size; i++) { + int arg = state.get(i); + // Does this argument match the current run? + if (arg == thisRotArg + TOKEN) { + thisRotArg = arg; + thisRotLen += 1; + if (bestRotLen < thisRotLen) { + bestRotLen = thisRotLen; + bestRotArg = thisRotArg; + } + } else { + // The old sequence (if any) stops here. + thisRotLen = 0; + thisRotArg = -10 * TOKEN; + // But maybe a new one starts here also. + int wantArg = goal.get(i); + final int MAX_ARG_ROTATION = AdapterMethodHandle.MAX_ARG_ROTATION; + if (arg != wantArg && + arg >= wantArg - TOKEN * MAX_ARG_ROTATION && + arg <= wantArg + TOKEN * MAX_ARG_ROTATION) { + thisRotArg = arg; + thisRotLen = 1; + } + } + } + if (bestRotLen >= 2) { + // Do a rotation if it can improve argument positioning + // by at least 2 arguments. This is not always optimal, + // but it seems to catch common cases. + int dstEnd = state.indexOf(bestRotArg); + int srcEnd = goal.indexOf(bestRotArg); + int rotBy = dstEnd - srcEnd; + int dstBeg = dstEnd - (bestRotLen - 1); + int srcBeg = srcEnd - (bestRotLen - 1); + assert((dstEnd | dstBeg | srcEnd | srcBeg) >= 0); // no negs + // Make a span which covers both source and destination. + int rotBeg = Math.min(dstBeg, srcBeg); + int rotEnd = Math.max(dstEnd, srcEnd); + int score = 0; + for (int i = rotBeg; i <= rotEnd; i++) { + if ((int)state.get(i) != (int)goal.get(i)) + score += 1; + } + List rotSpan = state.subList(rotBeg, rotEnd+1); + Collections.rotate(rotSpan, -rotBy); // reverse direction + for (int i = rotBeg; i <= rotEnd; i++) { + if ((int)state.get(i) != (int)goal.get(i)) + score -= 1; + } + if (score >= 2) { + // Improved at least two argument positions. Do it. + List> ptypes = Arrays.asList(oldType.parameterArray()); + Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy); + MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes); + MethodHandle nextTarget + = AdapterMethodHandle.makeRotateArguments(token, rotType, target, + rotBeg, rotSpan.size(), rotBy); + if (nextTarget != null) { + //System.out.println("Rot: "+rotSpan+" by "+rotBy); + target = nextTarget; + oldType = rotType; + continue; + } + } + // Else de-rotate, and drop through to the swap-fest. + Collections.rotate(rotSpan, rotBy); + } + + // Now swap like the wind! + List> ptypes = Arrays.asList(oldType.parameterArray()); + for (int i = 0; i < size; i++) { + // What argument do I want here? + int arg = goal.get(i); + if (arg != state.get(i)) { + // Where is it now? + int j = state.indexOf(arg); + Collections.swap(ptypes, i, j); + MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes); + target = AdapterMethodHandle.makeSwapArguments(token, swapType, target, i, j); + if (target == null) throw newIllegalArgumentException("cannot swap"); + assert(target.type() == swapType); + oldType = swapType; + Collections.swap(state, i, j); + } + } + // One pass of swapping must finish the job. + assert(state.equals(goal)); + } + while (!dups.isEmpty()) { + // Grab a contiguous trailing sequence of dups. + int grab = dups.size() - 1; + int dupArgPos = dups.get(grab), dupArgCount = 1; + while (grab - 1 >= 0) { + int dup0 = dups.get(grab - 1); + if (dup0 != dupArgPos - 1) break; + dupArgPos -= 1; + dupArgCount += 1; + grab -= 1; + } + //if (dupArgCount > 1) System.out.println("Dup: "+dups.subList(grab, dups.size())); + dups.subList(grab, dups.size()).clear(); + // In the new target type drop that many args from the tail: + List> ptypes = oldType.parameterList(); + ptypes = ptypes.subList(0, ptypes.size() - dupArgCount); + MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes); + target = AdapterMethodHandle.makeDupArguments(token, dupType, target, dupArgPos, dupArgCount); + if (target == null) + throw newIllegalArgumentException("cannot dup"); + oldType = target.type(); + } + while (!drops.isEmpty()) { + // Grab a contiguous initial sequence of drops. + int dropArgPos = drops.get(0), dropArgCount = 1; + while (dropArgCount < drops.size()) { + int drop1 = drops.get(dropArgCount); + if (drop1 != dropArgPos + dropArgCount) break; + dropArgCount += 1; + } + //if (dropArgCount > 1) System.out.println("Drop: "+drops.subList(0, dropArgCount)); + drops.subList(0, dropArgCount).clear(); + List> dropTypes = newType.parameterList() + .subList(dropArgPos, dropArgPos + dropArgCount); + MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes); + target = AdapterMethodHandle.makeDropArguments(token, dropType, target, dropArgPos, dropArgCount); + if (target == null) throw newIllegalArgumentException("cannot drop"); + oldType = target.type(); + } + } + if (newType == oldType) + return target; + if (oldType.parameterCount() != newType.parameterCount()) + throw newIllegalArgumentException("mismatched parameter count"); MethodHandle res = AdapterMethodHandle.makePairwiseConvert(token, newType, target); if (res != null) return res; @@ -241,7 +661,7 @@ // Use a heavier method: Convert all the arguments to Object, // then back to the desired types. We might have to use Java-based // method handles to do this. - MethodType objType = MethodType.makeGeneric(argc); + MethodType objType = MethodType.genericMethodType(argc); MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(token, objType, target); if (objTarget == null) objTarget = FromGeneric.make(target); @@ -272,83 +692,386 @@ Class[] ptypes = oldType.parameterArray(); for (int i = 0; i < spreadCount; i++) ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i); - MethodType midType = MethodType.make(newType.returnType(), ptypes); + MethodType midType = MethodType.methodType(newType.returnType(), ptypes); // after spreading, some arguments may need further conversion - target = convertArguments(token, target, midType, oldType, null); - if (target == null) + MethodHandle target2 = convertArguments(token, target, midType, oldType, null); + if (target2 == null) throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType); - res = AdapterMethodHandle.makeSpreadArguments(token, newType, target, spreadArgType, spreadArg, spreadCount); + res = AdapterMethodHandle.makeSpreadArguments(token, newType, target2, spreadArgType, spreadArg, spreadCount); + if (res != null) + return res; + res = SpreadGeneric.make(target2, spreadCount); + if (res != null) + res = convertArguments(token, res, newType, res.type(), null); return res; } public static MethodHandle collectArguments(Access token, MethodHandle target, MethodType newType, - int collectArg) { - if (collectArg > 0) - throw new UnsupportedOperationException("NYI"); - throw new UnsupportedOperationException("NYI"); + int collectArg, + MethodHandle collector) { + MethodType oldType = target.type(); // (a...,c)=>r + if (collector == null) { + int numCollect = newType.parameterCount() - oldType.parameterCount() + 1; + collector = ValueConversions.varargsArray(numCollect); + } + // newType // (a..., b...)=>r + MethodType colType = collector.type(); // (b...)=>c + // oldType // (a..., b...)=>r + assert(newType.parameterCount() == collectArg + colType.parameterCount()); + assert(oldType.parameterCount() == collectArg + 1); + MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null); + MethodHandle gcollector = convertArguments(token, collector, colType.generic(), colType, null); + if (gtarget == null || gcollector == null) return null; + MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget); + MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null); + return result; } + + public static MethodHandle filterArgument(Access token, + MethodHandle target, + int pos, + MethodHandle filter) { + Access.check(token); + MethodType ttype = target.type(), gttype = ttype.generic(); + if (ttype != gttype) { + target = convertArguments(token, target, gttype, ttype, null); + ttype = gttype; + } + MethodType ftype = filter.type(), gftype = ftype.generic(); + if (ftype.parameterCount() != 1) + throw new InternalError(); + if (ftype != gftype) { + filter = convertArguments(token, filter, gftype, ftype, null); + ftype = gftype; + } + if (ftype == ttype) { + // simple unary case + return FilterOneArgument.make(filter, target); + } + return FilterGeneric.makeArgumentFilter(pos, filter, target); + } + + public static MethodHandle foldArguments(Access token, + MethodHandle target, + MethodType newType, + MethodHandle combiner) { + Access.check(token); + MethodType oldType = target.type(); + MethodType ctype = combiner.type(); + MethodHandle gtarget = convertArguments(token, target, oldType.generic(), oldType, null); + MethodHandle gcombiner = convertArguments(token, combiner, ctype.generic(), ctype, null); + if (gtarget == null || gcombiner == null) return null; + MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget); + MethodHandle result = convertArguments(token, gresult, newType, gresult.type(), null); + return result; + } + public static MethodHandle dropArguments(Access token, MethodHandle target, MethodType newType, int argnum) { Access.check(token); + int drops = newType.parameterCount() - target.type().parameterCount(); + MethodHandle res = AdapterMethodHandle.makeDropArguments(token, newType, target, argnum, drops); + if (res != null) + return res; throw new UnsupportedOperationException("NYI"); } + private static class GuardWithTest extends JavaMethodHandle { + private final MethodHandle test, target, fallback; + public GuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) { + this(INVOKES[target.type().parameterCount()], test, target, fallback); + } + public GuardWithTest(MethodHandle invoker, + MethodHandle test, MethodHandle target, MethodHandle fallback) { + super(invoker); + this.test = test; + this.target = target; + this.fallback = fallback; + } + @Override + public String toString() { + return target.toString(); + } + private Object invoke_V(Object... av) throws Throwable { + if (test.invoke(av)) + return target.invoke(av); + return fallback.invoke(av); + } + private Object invoke_L0() throws Throwable { + if (test.invoke()) + return target.invoke(); + return fallback.invoke(); + } + private Object invoke_L1(Object a0) throws Throwable { + if (test.invoke(a0)) + return target.invoke(a0); + return fallback.invoke(a0); + } + private Object invoke_L2(Object a0, Object a1) throws Throwable { + if (test.invoke(a0, a1)) + return target.invoke(a0, a1); + return fallback.invoke(a0, a1); + } + private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { + if (test.invoke(a0, a1, a2)) + return target.invoke(a0, a1, a2); + return fallback.invoke(a0, a1, a2); + } + private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { + if (test.invoke(a0, a1, a2, a3)) + return target.invoke(a0, a1, a2, a3); + return fallback.invoke(a0, a1, a2, a3); + } + private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { + if (test.invoke(a0, a1, a2, a3, a4)) + return target.invoke(a0, a1, a2, a3, a4); + return fallback.invoke(a0, a1, a2, a3, a4); + } + private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { + if (test.invoke(a0, a1, a2, a3, a4, a5)) + return target.invoke(a0, a1, a2, a3, a4, a5); + return fallback.invoke(a0, a1, a2, a3, a4, a5); + } + private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { + if (test.invoke(a0, a1, a2, a3, a4, a5, a6)) + return target.invoke(a0, a1, a2, a3, a4, a5, a6); + return fallback.invoke(a0, a1, a2, a3, a4, a5, a6); + } + private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { + if (test.invoke(a0, a1, a2, a3, a4, a5, a6, a7)) + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7); + return fallback.invoke(a0, a1, a2, a3, a4, a5, a6, a7); + } + static MethodHandle[] makeInvokes() { + ArrayList invokes = new ArrayList(); + MethodHandles.Lookup lookup = IMPL_LOOKUP; + for (;;) { + int nargs = invokes.size(); + String name = "invoke_L"+nargs; + MethodHandle invoke = null; + try { + invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs)); + } catch (NoAccessException ex) { + } + if (invoke == null) break; + invokes.add(invoke); + } + assert(invokes.size() == 9); // current number of methods + return invokes.toArray(new MethodHandle[0]); + }; + static final MethodHandle[] INVOKES = makeInvokes(); + // For testing use this: + //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); + static final MethodHandle VARARGS_INVOKE; + static { + try { + VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true)); + } catch (NoAccessException ex) { + throw new InternalError(""); + } + } + } + public static MethodHandle makeGuardWithTest(Access token, - final MethodHandle test, - final MethodHandle target, - final MethodHandle fallback) { + MethodHandle test, + MethodHandle target, + MethodHandle fallback) { Access.check(token); - // %%% This is just a sketch. It needs to be de-boxed. - // Adjust the handles to accept varargs lists. MethodType type = target.type(); - Class rtype = type.returnType(); - if (type.parameterCount() != 1 || type.parameterType(0).isPrimitive()) { - MethodType vatestType = MethodType.make(boolean.class, Object[].class); - MethodType vatargetType = MethodType.make(rtype, Object[].class); - MethodHandle vaguard = makeGuardWithTest(token, - MethodHandles.spreadArguments(test, vatestType), - MethodHandles.spreadArguments(target, vatargetType), - MethodHandles.spreadArguments(fallback, vatargetType)); - return MethodHandles.collectArguments(vaguard, type); + int nargs = type.parameterCount(); + if (nargs < GuardWithTest.INVOKES.length) { + MethodType gtype = type.generic(); + MethodHandle gtest = convertArguments(token, test, gtype.changeReturnType(boolean.class), test.type(), null); + MethodHandle gtarget = convertArguments(token, target, gtype, type, null); + MethodHandle gfallback = convertArguments(token, fallback, gtype, type, null); + if (gtest == null || gtarget == null || gfallback == null) return null; + MethodHandle gguard = new GuardWithTest(gtest, gtarget, gfallback); + return convertArguments(token, gguard, type, gtype, null); + } else { + MethodType gtype = MethodType.genericMethodType(0, true); + MethodHandle gtest = spreadArguments(token, test, gtype.changeReturnType(boolean.class), 0); + MethodHandle gtarget = spreadArguments(token, target, gtype, 0); + MethodHandle gfallback = spreadArguments(token, fallback, gtype, 0); + MethodHandle gguard = new GuardWithTest(GuardWithTest.VARARGS_INVOKE, gtest, gtarget, gfallback); + if (gtest == null || gtarget == null || gfallback == null) return null; + return collectArguments(token, gguard, type, 0, null); + } + } + + private static class GuardWithCatch extends JavaMethodHandle { + private final MethodHandle target; + private final Class exType; + private final MethodHandle catcher; + public GuardWithCatch(MethodHandle target, Class exType, MethodHandle catcher) { + this(INVOKES[target.type().parameterCount()], target, exType, catcher); + } + public GuardWithCatch(MethodHandle invoker, + MethodHandle target, Class exType, MethodHandle catcher) { + super(invoker); + this.target = target; + this.exType = exType; + this.catcher = catcher; } - if (rtype.isPrimitive()) { - MethodType boxtype = type.changeReturnType(Object.class); - MethodHandle boxguard = makeGuardWithTest(token, - test, - MethodHandles.convertArguments(target, boxtype), - MethodHandles.convertArguments(fallback, boxtype)); - return MethodHandles.convertArguments(boxguard, type); + @Override + public String toString() { + return target.toString(); + } + private Object invoke_V(Object... av) throws Throwable { + try { + return target.invoke(av); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, av); + } + } + private Object invoke_L0() throws Throwable { + try { + return target.invoke(); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t); + } } - // Got here? Reduced calling sequence to Object(Object). - class Guarder { - Object invoke(Object x) { - // If javac supports MethodHandle.invoke directly: - //z = vatest.invoke(arguments); - // If javac does not support direct MH.invoke calls: - boolean z = (Boolean) MethodHandles.invoke_1(test, x); - MethodHandle mh = (z ? target : fallback); - return MethodHandles.invoke_1(mh, x); + private Object invoke_L1(Object a0) throws Throwable { + try { + return target.invoke(a0); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0); } - MethodHandle handle() { - MethodType invokeType = MethodType.makeGeneric(0, true); - MethodHandle vh = IMPL_LOOKUP.bind(this, "invoke", invokeType); - return MethodHandles.collectArguments(vh, target.type()); + } + private Object invoke_L2(Object a0, Object a1) throws Throwable { + try { + return target.invoke(a0, a1); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0, a1); + } + } + private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { + try { + return target.invoke(a0, a1, a2); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0, a1, a2); } } - return new Guarder().handle(); + private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { + try { + return target.invoke(a0, a1, a2, a3); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0, a1, a2, a3); + } + } + private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { + try { + return target.invoke(a0, a1, a2, a3, a4); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0, a1, a2, a3, a4); + } + } + private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { + try { + return target.invoke(a0, a1, a2, a3, a4, a5); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0, a1, a2, a3, a4, a5); + } + } + private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { + try { + return target.invoke(a0, a1, a2, a3, a4, a5, a6); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0, a1, a2, a3, a4, a5, a6); + } + } + private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { + try { + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7); + } catch (Throwable t) { + if (!exType.isInstance(t)) throw t; + return catcher.invoke(t, a0, a1, a2, a3, a4, a5, a6, a7); + } + } + static MethodHandle[] makeInvokes() { + ArrayList invokes = new ArrayList(); + MethodHandles.Lookup lookup = IMPL_LOOKUP; + for (;;) { + int nargs = invokes.size(); + String name = "invoke_L"+nargs; + MethodHandle invoke = null; + try { + invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs)); + } catch (NoAccessException ex) { + } + if (invoke == null) break; + invokes.add(invoke); + } + assert(invokes.size() == 9); // current number of methods + return invokes.toArray(new MethodHandle[0]); + }; + static final MethodHandle[] INVOKES = makeInvokes(); + // For testing use this: + //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2); + static final MethodHandle VARARGS_INVOKE; + static { + try { + VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true)); + } catch (NoAccessException ex) { + throw new InternalError(""); + } + } + } + + + public static + MethodHandle makeGuardWithCatch(Access token, + MethodHandle target, + Class exType, + MethodHandle catcher) { + Access.check(token); + MethodType type = target.type(); + MethodType ctype = catcher.type(); + int nargs = type.parameterCount(); + if (nargs < GuardWithCatch.INVOKES.length) { + MethodType gtype = type.generic(); + MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); + MethodHandle gtarget = convertArguments(token, target, gtype, type, null); + MethodHandle gcatcher = convertArguments(token, catcher, gcatchType, ctype, null); + MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher); + if (gtarget == null || gcatcher == null || gguard == null) return null; + return convertArguments(token, gguard, type, gtype, null); + } else { + MethodType gtype = MethodType.genericMethodType(0, true); + MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class); + MethodHandle gtarget = spreadArguments(token, target, gtype, 0); + MethodHandle gcatcher = spreadArguments(token, catcher, gcatchType, 1); + MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher); + if (gtarget == null || gcatcher == null || gguard == null) return null; + return collectArguments(token, gguard, type, 0, null); + } } public static - MethodHandle combineArguments(Access token, MethodHandle target, MethodHandle checker, int pos) { + MethodHandle throwException(Access token, MethodType type) { Access.check(token); - throw new UnsupportedOperationException("Not yet implemented"); + return AdapterMethodHandle.makeRetypeRaw(token, type, THROW_EXCEPTION); } - protected static String basicToString(MethodHandle target) { + static final MethodHandle THROW_EXCEPTION + = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException", + MethodType.methodType(Empty.class, Throwable.class)); + static Empty throwException(T t) throws T { throw t; } + + public static String getNameString(Access token, MethodHandle target) { + Access.check(token); MemberName name = null; if (target != null) name = MethodHandleNatives.getMethodName(target); @@ -357,17 +1080,30 @@ return name.getName(); } - protected static String addTypeString(MethodHandle target, String name) { - if (target == null) return name; - return name+target.type(); + public static String addTypeString(MethodHandle target) { + if (target == null) return "null"; + return target.toString() + target.type(); } - static RuntimeException newIllegalArgumentException(String string) { - return new IllegalArgumentException(string); + + public static void checkSpreadArgument(Object av, int n) { + if (av == null ? n != 0 : ((Object[])av).length != n) + throw newIllegalArgumentException("Array is not of length "+n); } - @Override - public String toString() { - MethodHandle self = (MethodHandle) this; - return addTypeString(self, basicToString(self)); + public static void raiseException(int code, Object actual, Object required) { + String message; + // disregard the identity of the actual object, if it is not a class: + if (!(actual instanceof Class) && !(actual instanceof MethodType)) + actual = actual.getClass(); + if (actual != null) + message = "required "+required+" but encountered "+actual; + else + message = "required "+required; + switch (code) { + case 192: // checkcast + throw new ClassCastException(message); + default: + throw new InternalError("unexpected code "+code+": "+message); + } } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/MethodHandleNatives.java --- a/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/MethodHandleNatives.java Wed Jul 05 17:05:01 2017 +0200 @@ -25,6 +25,7 @@ package sun.dyn; +import java.dyn.CallSite; import java.dyn.MethodHandle; import java.dyn.MethodType; import java.lang.reflect.AccessibleObject; @@ -60,7 +61,7 @@ static native void init(MethodType self); /** Tell the JVM that we need to change the target of an invokedynamic. */ - static native void linkCallSite(CallSiteImpl site, MethodHandle target); + static native void linkCallSite(CallSite site, MethodHandle target); /** Fetch the vmtarget field. * It will be sanitized as necessary to avoid exposing non-Java references. @@ -84,8 +85,7 @@ } /** Fetch the target of this method handle. - * If it directly targets a method, return a tuple of method info. - * The info is of the form new Object[]{defclass, name, sig, refclass}. + * If it directly targets a method, return a MemberName for the method. * If it is chained to another method handle, return that handle. */ static Object getTargetInfo(MethodHandle self) { @@ -123,7 +123,7 @@ registerNatives(); JVM_SUPPORT_ = true; JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT); - JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_LIMIT); + JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT); //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init"); } catch (UnsatisfiedLinkError ee) { // ignore; if we use init() methods later we'll see linkage errors @@ -149,7 +149,7 @@ // MethodHandleImpl static final int // for getConstant GC_JVM_PUSH_LIMIT = 0, - GC_JVM_STACK_MOVE_LIMIT = 1; + GC_JVM_STACK_MOVE_UNIT = 1; static final int ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) @@ -178,19 +178,20 @@ */ static final int OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype - OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument - OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another - OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive - OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI) - OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg) - OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg) - OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS) - OP_DROP_ARGS = 0x8, // remove one or more argument slots - OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI) - OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size) - OP_FLYBY = 0xB, // operate first on reified argument list (NYI) - OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI) - CONV_OP_LIMIT = 0xD; // limit of CONV_OP enumeration + OP_RETYPE_RAW = 0x1, // no argument changes; straight retype + OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument + OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another + OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive + OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI) + OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg) + OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg) + OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS) + OP_DROP_ARGS = 0x9, // remove one or more argument slots + OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI) + OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size) + OP_FLYBY = 0xC, // operate first on reified argument list (NYI) + OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI) + CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration /** Shift and mask values for decoding the AMH.conversion field. * These numbers are shared with the JVM for creating AMHs. */ @@ -209,6 +210,7 @@ // TODO: The following expression should be replaced by // a JVM query. ((1<[] ptypes(MethodType mt); @@ -150,7 +151,7 @@ this.argToSlotTable = argToSlotTab; this.slotToArgTable = slotToArgTab; - if (pslotCount >= 256) throw new IllegalArgumentException("too many arguments"); + if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments"); // send a few bits down to the JVM: this.vmslots = parameterSlotCount(); @@ -378,10 +379,10 @@ static MethodTypeImpl findForm(MethodType mt) { MethodType erased = canonicalize(mt, ERASE, ERASE); if (erased == null) { - // It is already erased. Make a new MethodTypeForm. + // It is already erased. Make a new MethodTypeImpl. return METHOD_TYPE_FRIEND.newMethodTypeForm(mt); } else { - // Share the MethodTypeForm with the erased version. + // Share the MethodTypeImpl with the erased version. return METHOD_TYPE_FRIEND.form(erased); } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/SpreadGeneric.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/dyn/SpreadGeneric.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,682 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.dyn; + +import java.dyn.JavaMethodHandle; +import java.dyn.MethodHandle; +import java.dyn.MethodHandles; +import java.dyn.MethodType; +import java.dyn.NoAccessException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import sun.dyn.util.ValueConversions; +import static sun.dyn.MemberName.newIllegalArgumentException; + +/** + * Generic spread adapter. + * Expands a final argument into multiple (zero or more) arguments, keeping the others the same. + * @author jrose + */ +class SpreadGeneric { + // type for the outgoing call + private final MethodType targetType; + // number of arguments to spread + private final int spreadCount; + // prototype adapter (clone and customize for each new target!) + private final Adapter adapter; + // entry point for adapter (Adapter mh, a...) => ... + private final MethodHandle entryPoint; + + /** Compute and cache information common to all spreading adapters + * that accept calls of the given (generic) type. + */ + private SpreadGeneric(MethodType targetType, int spreadCount) { + assert(targetType == targetType.generic()); + this.targetType = targetType; + this.spreadCount = spreadCount; + // the target invoker will generally need casts on reference arguments + MethodHandle[] ep = { null }; + Adapter ad = findAdapter(this, ep); + if (ad != null) { + this.adapter = ad; + this.entryPoint = ep[0]; + return; + } + this.adapter = buildAdapterFromBytecodes(targetType, spreadCount, ep); + this.entryPoint = ep[0]; + } + + /** From targetType remove the last spreadCount arguments, and instead + * append a simple Object argument. + */ + static MethodType preSpreadType(MethodType targetType, int spreadCount) { + @SuppressWarnings("unchecked") + ArrayList> params = new ArrayList(targetType.parameterList()); + int outargs = params.size(); + params.subList(outargs - spreadCount, outargs).clear(); + params.add(Object.class); + return MethodType.methodType(targetType.returnType(), params); + } + + MethodHandle makeInstance(MethodHandle target) { + MethodType type = target.type(); + if (type != targetType) { + throw new UnsupportedOperationException("NYI type="+type); + } + return adapter.makeInstance(this, target); + } + + /** Build an adapter of the given generic type, which invokes typedTarget + * on the incoming arguments, after unboxing as necessary. + * The return value is boxed if necessary. + * @param genericType the required type of the result + * @param typedTarget the target + * @return an adapter method handle + */ + public static MethodHandle make(MethodHandle target, int spreadCount) { + MethodType type = target.type(); + MethodType gtype = type.generic(); + if (type == gtype) { + return SpreadGeneric.of(type, spreadCount).makeInstance(target); + } else { + MethodHandle gtarget = FromGeneric.make(target); + assert(gtarget.type() == gtype); + MethodHandle gspread = SpreadGeneric.of(gtype, spreadCount).makeInstance(gtarget); + return ToGeneric.make(preSpreadType(type, spreadCount), gspread); + } + } + + /** Return the adapter information for this type's erasure. */ + static SpreadGeneric of(MethodType targetType, int spreadCount) { + if (targetType != targetType.generic()) + throw new UnsupportedOperationException("NYI type="+targetType); + MethodTypeImpl form = MethodTypeImpl.of(targetType); + int outcount = form.parameterCount(); + assert(spreadCount <= outcount); + SpreadGeneric[] spreadGens = form.spreadGeneric; + if (spreadGens == null) + form.spreadGeneric = spreadGens = new SpreadGeneric[outcount+1]; + SpreadGeneric spreadGen = spreadGens[spreadCount]; + if (spreadGen == null) + spreadGens[spreadCount] = spreadGen = new SpreadGeneric(form.erasedType(), spreadCount); + return spreadGen; + } + + public String toString() { + return getClass().getSimpleName()+targetType+"["+spreadCount+"]"; + } + + // This mini-api is called from an Adapter to manage the spread. + /** A check/coercion that happens once before any selections. */ + protected Object check(Object av, int n) { + MethodHandleImpl.checkSpreadArgument(av, n); + return av; + } + + /** The selection operator for spreading; note that it takes Object not Object[]. */ + protected Object select(Object av, int n) { + return ((Object[])av)[n]; + } + /* + protected int select_I(Object av, int n) { + // maybe return ((int[])select)[n] + throw new UnsupportedOperationException("subclass resp."); + } + protected int select_J(Object av, int n) { + // maybe return ((long[])select)[n] + throw new UnsupportedOperationException("subclass resp."); + } + // */ + + /* Create an adapter that handles spreading calls for the given type. */ + static Adapter findAdapter(SpreadGeneric outer, MethodHandle[] ep) { + MethodType targetType = outer.targetType; + int spreadCount = outer.spreadCount; + int outargs = targetType.parameterCount(); + int inargs = outargs - spreadCount; + if (inargs < 0) return null; + MethodType entryType = MethodType.genericMethodType(inargs + 1); // 1 for av + String cname1 = "S" + outargs; + String[] cnames = { cname1 }; + String iname = "invoke_S"+spreadCount; + // e.g., D5I2, D5, L5I2, L5; invoke_D5 + for (String cname : cnames) { + Class acls = Adapter.findSubClass(cname); + if (acls == null) continue; + // see if it has the required invoke method + MethodHandle entryPoint = null; + try { + entryPoint = MethodHandleImpl.IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls); + } catch (NoAccessException ex) { + } + if (entryPoint == null) continue; + Constructor ctor = null; + try { + ctor = acls.getDeclaredConstructor(SpreadGeneric.class); + } catch (NoSuchMethodException ex) { + } catch (SecurityException ex) { + } + if (ctor == null) continue; + try { + // Produce an instance configured as a prototype. + Adapter ad = ctor.newInstance(outer); + ep[0] = entryPoint; + return ad; + } catch (IllegalArgumentException ex) { + } catch (InvocationTargetException wex) { + Throwable ex = wex.getTargetException(); + if (ex instanceof Error) throw (Error)ex; + if (ex instanceof RuntimeException) throw (RuntimeException)ex; + } catch (InstantiationException ex) { + } catch (IllegalAccessException ex) { + } + } + return null; + } + + static Adapter buildAdapterFromBytecodes(MethodType targetType, + int spreadCount, MethodHandle[] ep) { + throw new UnsupportedOperationException("NYI"); + } + + /** + * This adapter takes some untyped arguments, and returns an untyped result. + * Internally, it applies the invoker to the target, which causes the + * objects to be unboxed; the result is a raw type in L/I/J/F/D. + * This result is passed to convert, which is responsible for + * converting the raw result into a boxed object. + * The invoker is kept separate from the target because it can be + * generated once per type erasure family, and reused across adapters. + */ + static abstract class Adapter extends JavaMethodHandle { + /* + * class X<> extends Adapter { + * (Object**N)=>R target; + * static int S = N-M; + * Object invoke(Object**M a, Object v) = target(a..., v[0]...v[S-1]); + * } + */ + protected final SpreadGeneric outer; + protected final MethodHandle target; // (any**N) => R + + @Override + public String toString() { + return target.toString(); + } + + static final MethodHandle NO_ENTRY = ValueConversions.identity(); + + protected boolean isPrototype() { return target == null; } + protected Adapter(SpreadGeneric outer) { + super(NO_ENTRY); + this.outer = outer; + this.target = null; + assert(isPrototype()); + } + + protected Adapter(SpreadGeneric outer, MethodHandle target) { + super(outer.entryPoint); + this.outer = outer; + this.target = target; + } + + /** Make a copy of self, with new fields. */ + protected abstract Adapter makeInstance(SpreadGeneric outer, MethodHandle target); + // { return new ThisType(outer, target); } + + protected Object check(Object av, int n) { + return outer.check(av, n); + } + protected Object select(Object av, int n) { + return outer.select(av, n); + } + + static private final String CLASS_PREFIX; // "sun.dyn.SpreadGeneric$" + static { + String aname = Adapter.class.getName(); + String sname = Adapter.class.getSimpleName(); + if (!aname.endsWith(sname)) throw new InternalError(); + CLASS_PREFIX = aname.substring(0, aname.length() - sname.length()); + } + /** Find a sibing class of Adapter. */ + static Class findSubClass(String name) { + String cname = Adapter.CLASS_PREFIX + name; + try { + return Class.forName(cname).asSubclass(Adapter.class); + } catch (ClassNotFoundException ex) { + return null; + } catch (ClassCastException ex) { + return null; + } + } + } + + /* generated classes follow this pattern: + static class xS2 extends Adapter { + protected xS2(SpreadGeneric outer) { super(outer); } // to build prototype + protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0); + return target.invoke(a0, a1)); } + protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1); + return target.invoke(a0, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1); + return target.invoke( + super.select(av,0), super.select(av,1)); } + } + // */ + +/* +: SHELL; n=SpreadGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~ +//{{{ +import java.util.*; +class genclasses { + static String[][] TEMPLATES = { { + "@for@ N=0..10", + " //@each-cat@", + " static class @cat@ extends Adapter {", + " protected @cat@(SpreadGeneric outer) { super(outer); } // to build prototype", + " protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }", + " protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }", + " protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);", + " return target.invoke(@av@); }", + " //@each-S@", + " protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);", + " return target.invoke(@av,@@sv@); }", + " //@end-S@", + " }", + } }; + static final String NEWLINE_INDENT = "\n "; + enum VAR { + cat, N, S, av, av_, Tvav_, sv; + public final String pattern = "@"+toString().replace('_','.')+"@"; + public String binding = toString(); + static void makeBindings(boolean topLevel, int outargs, int spread) { + int inargs = outargs - spread; + VAR.cat.binding = "S"+outargs; + VAR.N.binding = String.valueOf(outargs); // outgoing arg count + VAR.S.binding = String.valueOf(spread); // spread count + String[] av = new String[inargs]; + String[] Tvav = new String[inargs]; + for (int i = 0; i < inargs; i++) { + av[i] = arg(i); + Tvav[i] = param("Object", av[i]); + } + VAR.av.binding = comma(av); + VAR.av_.binding = comma(av, ", "); + VAR.Tvav_.binding = comma(Tvav, ", "); + String[] sv = new String[spread]; + for (int i = 0; i < spread; i++) { + String spc = ""; + if (i % 4 == 0) spc = NEWLINE_INDENT; + sv[i] = spc+"super.select(av,"+i+")"; + } + VAR.sv.binding = comma(sv); + } + static String arg(int i) { return "a"+i; } + static String param(String t, String a) { return t+" "+a; } + static String comma(String[] v) { return comma(v, ""); } + static String comma(String[] v, String sep) { + if (v.length == 0) return ""; + String res = v[0]; + for (int i = 1; i < v.length; i++) res += ", "+v[i]; + return res + sep; + } + static String transform(String string) { + for (VAR var : values()) + string = string.replaceAll(var.pattern, var.binding); + return string; + } + } + static String[] stringsIn(String[] strings, int beg, int end) { + return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length)); + } + static String[] stringsBefore(String[] strings, int pos) { + return stringsIn(strings, 0, pos); + } + static String[] stringsAfter(String[] strings, int pos) { + return stringsIn(strings, pos, strings.length); + } + static int indexAfter(String[] strings, int pos, String tag) { + return Math.min(indexBefore(strings, pos, tag) + 1, strings.length); + } + static int indexBefore(String[] strings, int pos, String tag) { + for (int i = pos, end = strings.length; ; i++) { + if (i == end || strings[i].endsWith(tag)) return i; + } + } + static int MIN_ARITY, MAX_ARITY; + public static void main(String... av) { + for (String[] template : TEMPLATES) { + int forLinesLimit = indexBefore(template, 0, "@each-cat@"); + String[] forLines = stringsBefore(template, forLinesLimit); + template = stringsAfter(template, forLinesLimit); + for (String forLine : forLines) + expandTemplate(forLine, template); + } + } + static void expandTemplate(String forLine, String[] template) { + String[] params = forLine.split("[^0-9]+"); + if (params[0].length() == 0) params = stringsAfter(params, 1); + System.out.println("//params="+Arrays.asList(params)); + int pcur = 0; + MIN_ARITY = Integer.valueOf(params[pcur++]); + MAX_ARITY = Integer.valueOf(params[pcur++]); + if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine); + for (int outargs = MIN_ARITY; outargs <= MAX_ARITY; outargs++) { + expandTemplate(template, true, outargs, 0); + } + } + static void expandTemplate(String[] template, boolean topLevel, int outargs, int spread) { + VAR.makeBindings(topLevel, outargs, spread); + for (int i = 0; i < template.length; i++) { + String line = template[i]; + if (line.endsWith("@each-cat@")) { + // ignore + } else if (line.endsWith("@each-S@")) { + int blockEnd = indexAfter(template, i, "@end-S@"); + String[] block = stringsIn(template, i+1, blockEnd-1); + for (int spread1 = spread+1; spread1 <= outargs; spread1++) + expandTemplate(block, false, outargs, spread1); + VAR.makeBindings(topLevel, outargs, spread); + i = blockEnd-1; continue; + } else { + System.out.println(VAR.transform(line)); + } + } + } +} +//}}} */ +//params=[0, 10] + static class S0 extends Adapter { + protected S0(SpreadGeneric outer) { super(outer); } // to build prototype + protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); } + protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(); } + } + static class S1 extends Adapter { + protected S1(SpreadGeneric outer) { super(outer); } // to build prototype + protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); } + protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0); } + protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1); + return target.invoke( + super.select(av,0)); } + } + static class S2 extends Adapter { + protected S2(SpreadGeneric outer) { super(outer); } // to build prototype + protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1); } + protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, + super.select(av,0)); } + protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2); + return target.invoke( + super.select(av,0), super.select(av,1)); } + } + static class S3 extends Adapter { + protected S3(SpreadGeneric outer) { super(outer); } // to build prototype + protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2); } + protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2)); } + } + static class S4 extends Adapter { + protected S4(SpreadGeneric outer) { super(outer); } // to build prototype + protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2, a3); } + protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, a2, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, a1, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3); + return target.invoke(a0, + super.select(av,0), super.select(av,1), super.select(av,2)); } + protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } + } + static class S5 extends Adapter { + protected S5(SpreadGeneric outer) { super(outer); } // to build prototype + protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2, a3, a4); } + protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, a2, a3, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, a1, a2, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3); + return target.invoke(a0, a1, + super.select(av,0), super.select(av,1), super.select(av,2)); } + protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4); + return target.invoke(a0, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } + protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4)); } + } + static class S6 extends Adapter { + protected S6(SpreadGeneric outer) { super(outer); } // to build prototype + protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2, a3, a4, a5); } + protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, a2, a3, a4, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, a1, a2, a3, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3); + return target.invoke(a0, a1, a2, + super.select(av,0), super.select(av,1), super.select(av,2)); } + protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4); + return target.invoke(a0, a1, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } + protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5); + return target.invoke(a0, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4)); } + protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5)); } + } + static class S7 extends Adapter { + protected S7(SpreadGeneric outer) { super(outer); } // to build prototype + protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, a2, a3, a4, a5, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, a1, a2, a3, a4, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3); + return target.invoke(a0, a1, a2, a3, + super.select(av,0), super.select(av,1), super.select(av,2)); } + protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4); + return target.invoke(a0, a1, a2, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } + protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5); + return target.invoke(a0, a1, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4)); } + protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6); + return target.invoke(a0, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5)); } + protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6)); } + } + static class S8 extends Adapter { + protected S8(SpreadGeneric outer) { super(outer); } // to build prototype + protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, a1, a2, a3, a4, a5, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3); + return target.invoke(a0, a1, a2, a3, a4, + super.select(av,0), super.select(av,1), super.select(av,2)); } + protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4); + return target.invoke(a0, a1, a2, a3, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } + protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5); + return target.invoke(a0, a1, a2, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4)); } + protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6); + return target.invoke(a0, a1, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5)); } + protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7); + return target.invoke(a0, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6)); } + protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); } + } + static class S9 extends Adapter { + protected S9(SpreadGeneric outer) { super(outer); } // to build prototype + protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3); + return target.invoke(a0, a1, a2, a3, a4, a5, + super.select(av,0), super.select(av,1), super.select(av,2)); } + protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4); + return target.invoke(a0, a1, a2, a3, a4, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } + protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5); + return target.invoke(a0, a1, a2, a3, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4)); } + protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6); + return target.invoke(a0, a1, a2, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5)); } + protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7); + return target.invoke(a0, a1, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6)); } + protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8); + return target.invoke(a0, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); } + protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7), + super.select(av,8)); } + } + static class S10 extends Adapter { + protected S10(SpreadGeneric outer) { super(outer); } // to build prototype + protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); } + protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); } + protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, a8, + super.select(av,0)); } + protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, a7, + super.select(av,0), super.select(av,1)); } + protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3); + return target.invoke(a0, a1, a2, a3, a4, a5, a6, + super.select(av,0), super.select(av,1), super.select(av,2)); } + protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4); + return target.invoke(a0, a1, a2, a3, a4, a5, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); } + protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5); + return target.invoke(a0, a1, a2, a3, a4, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4)); } + protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6); + return target.invoke(a0, a1, a2, a3, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5)); } + protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7); + return target.invoke(a0, a1, a2, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6)); } + protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8); + return target.invoke(a0, a1, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); } + protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9); + return target.invoke(a0, + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7), + super.select(av,8)); } + protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10); + return target.invoke( + super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3), + super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7), + super.select(av,8), super.select(av,9)); } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/ToGeneric.java --- a/jdk/src/share/classes/sun/dyn/ToGeneric.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/ToGeneric.java Wed Jul 05 17:05:01 2017 +0200 @@ -34,6 +34,7 @@ import java.lang.reflect.InvocationTargetException; import sun.dyn.util.ValueConversions; import sun.dyn.util.Wrapper; +import static sun.dyn.MemberName.newIllegalArgumentException; /** * Adapters which mediate between incoming calls which are not generic @@ -68,7 +69,7 @@ // conversion which unboxes a primitive return value private final MethodHandle returnConversion; - /** Compute and cache information common to all collecting adapters + /** Compute and cache information common to all generifying (boxing) adapters * that implement members of the erasure-family of the given erased type. */ private ToGeneric(MethodType entryType) { @@ -111,30 +112,48 @@ // primitive arguments according to their "raw" types int/long MethodType intsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsInts(); ad = findAdapter(rawEntryTypeInit = intsAtEnd); - if (ad == null) { + MethodHandle rawEntryPoint; + if (ad != null) { + rawEntryPoint = ad.prototypeEntryPoint(); + } else { // Perhaps the adapter is available only for longs. // If so, we can use it, but there will have to be a little // more stack motion on each call. MethodType longsAtEnd = MethodTypeImpl.of(primsAtEnd).primsAsLongs(); ad = findAdapter(rawEntryTypeInit = longsAtEnd); - if (ad == null) { + if (ad != null) { + MethodType eptWithLongs = longsAtEnd.insertParameterTypes(0, ad.getClass()); + MethodType eptWithInts = intsAtEnd.insertParameterTypes(0, ad.getClass()); + rawEntryPoint = ad.prototypeEntryPoint(); + MethodType midType = eptWithLongs; // will change longs to ints + for (int i = 0, nargs = midType.parameterCount(); i < nargs; i++) { + if (midType.parameterType(i) != eptWithInts.parameterType(i)) { + assert(midType.parameterType(i) == long.class); + assert(eptWithInts.parameterType(i) == int.class); + MethodType nextType = midType.changeParameterType(i, int.class); + rawEntryPoint = MethodHandle.convertArguments(Access.TOKEN, + rawEntryPoint, nextType, midType, null); + midType = nextType; + } + } + assert(midType == eptWithInts); + } else { // If there is no statically compiled adapter, // build one by means of dynamic bytecode generation. ad = buildAdapterFromBytecodes(rawEntryTypeInit = intsAtEnd); + rawEntryPoint = ad.prototypeEntryPoint(); } } - MethodHandle rawEntryPoint = ad.prototypeEntryPoint(); - MethodType tepType = entryType.insertParameterType(0, ad.getClass()); + MethodType tepType = entryType.insertParameterTypes(0, ad.getClass()); this.entryPoint = - AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, rawEntryPoint); + AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, rawEntryPoint); if (this.entryPoint == null) throw new UnsupportedOperationException("cannot retype to "+entryType - +" from "+rawEntryPoint.type().dropParameterType(0)); + +" from "+rawEntryPoint.type().dropParameterTypes(0, 1)); this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false); this.rawEntryType = rawEntryTypeInit; this.adapter = ad; - this.invoker = makeRawArgumentFilter(invoker0, - rawEntryPoint.type().dropParameterType(0), entryType); + this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType); } /** A generic argument list will be created by a call of type 'raw'. @@ -157,8 +176,8 @@ if (filteredInvoker == null) throw new UnsupportedOperationException("NYI"); } MethodHandle reboxer = ValueConversions.rebox(dst, false); - FilterGeneric gen = new FilterGeneric(filteredInvoker.type(), (short)(1+i), (short)1, 'R'); - filteredInvoker = gen.makeInstance(reboxer, filteredInvoker); + filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker); + if (filteredInvoker == null) throw new InternalError(); } if (filteredInvoker == null) return invoker; return AdapterMethodHandle.makeRetypeOnly(Access.TOKEN, invoker.type(), filteredInvoker); @@ -209,9 +228,9 @@ if (convert == null) convert = computeReturnConversion(type, rawEntryType, true); // retype erased reference arguments (the cast makes it safe to do this) - MethodType tepType = type.insertParameterType(0, adapter.getClass()); + MethodType tepType = type.insertParameterTypes(0, adapter.getClass()); MethodHandle typedEntryPoint = - AdapterMethodHandle.makeRawRetypeOnly(Access.TOKEN, tepType, entryPoint); + AdapterMethodHandle.makeRetypeRaw(Access.TOKEN, tepType, entryPoint); return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget); } @@ -225,7 +244,7 @@ public static MethodHandle make(MethodType type, MethodHandle genericTarget) { MethodType gtype = genericTarget.type(); if (type.generic() != gtype) - throw new IllegalArgumentException(); + throw newIllegalArgumentException("type must be generic"); if (type == gtype) return genericTarget; return ToGeneric.of(type).makeInstance(type, genericTarget); } @@ -283,7 +302,10 @@ try { return ctor.newInstance(entryPoint); } catch (IllegalArgumentException ex) { - } catch (InvocationTargetException ex) { + } catch (InvocationTargetException wex) { + Throwable ex = wex.getTargetException(); + if (ex instanceof Error) throw (Error)ex; + if (ex instanceof RuntimeException) throw (RuntimeException)ex; } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } @@ -317,6 +339,11 @@ protected final MethodHandle target; // Object... -> Object protected final MethodHandle convert; // Object -> R + @Override + public String toString() { + return target.toString(); + } + protected boolean isPrototype() { return target == null; } /* Prototype constructor. */ protected Adapter(MethodHandle entryPoint) { @@ -344,33 +371,33 @@ // { return new ThisType(entryPoint, convert, target); } // Code to run when the arguments (<= 4) have all been boxed. - protected Object target() { return invoker.invoke(target); } - protected Object target(Object a0) { return invoker.invoke(target, a0); } + protected Object target() throws Throwable { return invoker.invoke(target); } + protected Object target(Object a0) throws Throwable { return invoker.invoke(target, a0); } protected Object target(Object a0, Object a1) - { return invoker.invoke(target, a0, a1); } + throws Throwable { return invoker.invoke(target, a0, a1); } protected Object target(Object a0, Object a1, Object a2) - { return invoker.invoke(target, a0, a1, a2); } + throws Throwable { return invoker.invoke(target, a0, a1, a2); } protected Object target(Object a0, Object a1, Object a2, Object a3) - { return invoker.invoke(target, a0, a1, a2, a3); } + throws Throwable { return invoker.invoke(target, a0, a1, a2, a3); } /* - protected Object target_0(Object... av) { return invoker.invoke(target, av); } + protected Object target_0(Object... av) throws Throwable { return invoker.invoke(target, av); } protected Object target_1(Object a0, Object... av) - { return invoker.invoke(target, a0, (Object)av); } + throws Throwable { return invoker.invoke(target, a0, (Object)av); } protected Object target_2(Object a0, Object a1, Object... av) - { return invoker.invoke(target, a0, a1, (Object)av); } + throws Throwable { return invoker.invoke(target, a0, a1, (Object)av); } protected Object target_3(Object a0, Object a1, Object a2, Object... av) - { return invoker.invoke(target, a0, a1, a2, (Object)av); } + throws Throwable { return invoker.invoke(target, a0, a1, a2, (Object)av); } protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av) - { return invoker.invoke(target, a0, a1, a2, a3, (Object)av); } + throws Throwable { return invoker.invoke(target, a0, a1, a2, a3, (Object)av); } // */ // (For more than 4 arguments, generate the code in the adapter itself.) // Code to run when the generic target has finished and produced a value. - protected Object return_L(Object res) { return convert.invoke(res); } - protected int return_I(Object res) { return convert.invoke(res); } - protected long return_J(Object res) { return convert.invoke(res); } - protected float return_F(Object res) { return convert.invoke(res); } - protected double return_D(Object res) { return convert.invoke(res); } + protected Object return_L(Object res) throws Throwable { return convert.invoke(res); } + protected int return_I(Object res) throws Throwable { return convert.invoke(res); } + protected long return_J(Object res) throws Throwable { return convert.invoke(res); } + protected float return_F(Object res) throws Throwable { return convert.invoke(res); } + protected double return_D(Object res) throws Throwable { return convert.invoke(res); } static private final String CLASS_PREFIX; // "sun.dyn.ToGeneric$" static { @@ -397,25 +424,25 @@ protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } - protected Object target(Object a0) { return invoker.invoke(target, a0); } - protected Object targetA1(Object a0) { return target(a0); } - protected Object targetA1(int a0) { return target(a0); } - protected Object targetA1(long a0) { return target(a0); } - protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); } - protected int invoke_I(Object a0) { return return_I(targetA1(a0)); } - protected long invoke_J(Object a0) { return return_J(targetA1(a0)); } - protected float invoke_F(Object a0) { return return_F(targetA1(a0)); } - protected double invoke_D(Object a0) { return return_D(targetA1(a0)); } - protected Object invoke_L(int a0) { return return_L(targetA1(a0)); } - protected int invoke_I(int a0) { return return_I(targetA1(a0)); } - protected long invoke_J(int a0) { return return_J(targetA1(a0)); } - protected float invoke_F(int a0) { return return_F(targetA1(a0)); } - protected double invoke_D(int a0) { return return_D(targetA1(a0)); } - protected Object invoke_L(long a0) { return return_L(targetA1(a0)); } - protected int invoke_I(long a0) { return return_I(targetA1(a0)); } - protected long invoke_J(long a0) { return return_J(targetA1(a0)); } - protected float invoke_F(long a0) { return return_F(targetA1(a0)); } - protected double invoke_D(long a0) { return return_D(targetA1(a0)); } + protected Object target(Object a0) throws Throwable { return invoker.invoke(target, a0); } + protected Object targetA1(Object a0) throws Throwable { return target(a0); } + protected Object targetA1(int a0) throws Throwable { return target(a0); } + protected Object targetA1(long a0) throws Throwable { return target(a0); } + protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); } + protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); } + protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); } + protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); } + protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); } + protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); } + protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); } + protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); } + protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); } + protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); } + protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); } + protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); } + protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); } + protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); } + protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); } } // */ @@ -435,13 +462,13 @@ " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype", " protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }", " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }", - " protected Object target(@Ovav@) { return invoker.invoke(target, @av@); }", + " protected Object target(@Ovav@) throws Throwable { return invoker.invoke(target, @av@); }", " //@each-Tv@", - " protected Object target@cat@(@Tvav@) { return target(@av@); }", + " protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }", " //@end-Tv@", " //@each-Tv@", " //@each-R@", - " protected @R@ invoke_@Rc@(@Tvav@) { return return_@Rc@(target@cat@(@av@)); }", + " protected @R@ invoke_@Rc@(@Tvav@) throws Throwable { return return_@Rc@(target@cat@(@av@)); }", " //@end-R@", " //@end-Tv@", " }", @@ -595,424 +622,424 @@ protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); } - protected Object target() { return invoker.invoke(target); } - protected Object targetA0() { return target(); } - protected Object invoke_L() { return return_L(targetA0()); } - protected int invoke_I() { return return_I(targetA0()); } - protected long invoke_J() { return return_J(targetA0()); } - protected float invoke_F() { return return_F(targetA0()); } - protected double invoke_D() { return return_D(targetA0()); } + protected Object target() throws Throwable { return invoker.invoke(target); } + protected Object targetA0() throws Throwable { return target(); } + protected Object invoke_L() throws Throwable { return return_L(targetA0()); } + protected int invoke_I() throws Throwable { return return_I(targetA0()); } + protected long invoke_J() throws Throwable { return return_J(targetA0()); } + protected float invoke_F() throws Throwable { return return_F(targetA0()); } + protected double invoke_D() throws Throwable { return return_D(targetA0()); } } static class A1 extends Adapter { protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); } - protected Object target(Object a0) { return invoker.invoke(target, a0); } - protected Object targetA1(Object a0) { return target(a0); } - protected Object targetA1(int a0) { return target(a0); } - protected Object targetA1(long a0) { return target(a0); } - protected Object invoke_L(Object a0) { return return_L(targetA1(a0)); } - protected int invoke_I(Object a0) { return return_I(targetA1(a0)); } - protected long invoke_J(Object a0) { return return_J(targetA1(a0)); } - protected float invoke_F(Object a0) { return return_F(targetA1(a0)); } - protected double invoke_D(Object a0) { return return_D(targetA1(a0)); } - protected Object invoke_L(int a0) { return return_L(targetA1(a0)); } - protected int invoke_I(int a0) { return return_I(targetA1(a0)); } - protected long invoke_J(int a0) { return return_J(targetA1(a0)); } - protected float invoke_F(int a0) { return return_F(targetA1(a0)); } - protected double invoke_D(int a0) { return return_D(targetA1(a0)); } - protected Object invoke_L(long a0) { return return_L(targetA1(a0)); } - protected int invoke_I(long a0) { return return_I(targetA1(a0)); } - protected long invoke_J(long a0) { return return_J(targetA1(a0)); } - protected float invoke_F(long a0) { return return_F(targetA1(a0)); } - protected double invoke_D(long a0) { return return_D(targetA1(a0)); } + protected Object target(Object a0) throws Throwable { return invoker.invoke(target, a0); } + protected Object targetA1(Object a0) throws Throwable { return target(a0); } + protected Object targetA1(int a0) throws Throwable { return target(a0); } + protected Object targetA1(long a0) throws Throwable { return target(a0); } + protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); } + protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); } + protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); } + protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); } + protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); } + protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); } + protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); } + protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); } + protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); } + protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); } + protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); } + protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); } + protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); } + protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); } + protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); } } static class A2 extends Adapter { protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); } - protected Object target(Object a0, Object a1) { return invoker.invoke(target, a0, a1); } - protected Object targetA2(Object a0, Object a1) { return target(a0, a1); } - protected Object targetA2(Object a0, int a1) { return target(a0, a1); } - protected Object targetA2(int a0, int a1) { return target(a0, a1); } - protected Object targetA2(Object a0, long a1) { return target(a0, a1); } - protected Object targetA2(long a0, long a1) { return target(a0, a1); } - protected Object invoke_L(Object a0, Object a1) { return return_L(targetA2(a0, a1)); } - protected int invoke_I(Object a0, Object a1) { return return_I(targetA2(a0, a1)); } - protected long invoke_J(Object a0, Object a1) { return return_J(targetA2(a0, a1)); } - protected float invoke_F(Object a0, Object a1) { return return_F(targetA2(a0, a1)); } - protected double invoke_D(Object a0, Object a1) { return return_D(targetA2(a0, a1)); } - protected Object invoke_L(Object a0, int a1) { return return_L(targetA2(a0, a1)); } - protected int invoke_I(Object a0, int a1) { return return_I(targetA2(a0, a1)); } - protected long invoke_J(Object a0, int a1) { return return_J(targetA2(a0, a1)); } - protected float invoke_F(Object a0, int a1) { return return_F(targetA2(a0, a1)); } - protected double invoke_D(Object a0, int a1) { return return_D(targetA2(a0, a1)); } - protected Object invoke_L(int a0, int a1) { return return_L(targetA2(a0, a1)); } - protected int invoke_I(int a0, int a1) { return return_I(targetA2(a0, a1)); } - protected long invoke_J(int a0, int a1) { return return_J(targetA2(a0, a1)); } - protected float invoke_F(int a0, int a1) { return return_F(targetA2(a0, a1)); } - protected double invoke_D(int a0, int a1) { return return_D(targetA2(a0, a1)); } - protected Object invoke_L(Object a0, long a1) { return return_L(targetA2(a0, a1)); } - protected int invoke_I(Object a0, long a1) { return return_I(targetA2(a0, a1)); } - protected long invoke_J(Object a0, long a1) { return return_J(targetA2(a0, a1)); } - protected float invoke_F(Object a0, long a1) { return return_F(targetA2(a0, a1)); } - protected double invoke_D(Object a0, long a1) { return return_D(targetA2(a0, a1)); } - protected Object invoke_L(long a0, long a1) { return return_L(targetA2(a0, a1)); } - protected int invoke_I(long a0, long a1) { return return_I(targetA2(a0, a1)); } - protected long invoke_J(long a0, long a1) { return return_J(targetA2(a0, a1)); } - protected float invoke_F(long a0, long a1) { return return_F(targetA2(a0, a1)); } - protected double invoke_D(long a0, long a1) { return return_D(targetA2(a0, a1)); } + protected Object target(Object a0, Object a1) throws Throwable { return invoker.invoke(target, a0, a1); } + protected Object targetA2(Object a0, Object a1) throws Throwable { return target(a0, a1); } + protected Object targetA2(Object a0, int a1) throws Throwable { return target(a0, a1); } + protected Object targetA2(int a0, int a1) throws Throwable { return target(a0, a1); } + protected Object targetA2(Object a0, long a1) throws Throwable { return target(a0, a1); } + protected Object targetA2(long a0, long a1) throws Throwable { return target(a0, a1); } + protected Object invoke_L(Object a0, Object a1) throws Throwable { return return_L(targetA2(a0, a1)); } + protected int invoke_I(Object a0, Object a1) throws Throwable { return return_I(targetA2(a0, a1)); } + protected long invoke_J(Object a0, Object a1) throws Throwable { return return_J(targetA2(a0, a1)); } + protected float invoke_F(Object a0, Object a1) throws Throwable { return return_F(targetA2(a0, a1)); } + protected double invoke_D(Object a0, Object a1) throws Throwable { return return_D(targetA2(a0, a1)); } + protected Object invoke_L(Object a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); } + protected int invoke_I(Object a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); } + protected long invoke_J(Object a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); } + protected float invoke_F(Object a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); } + protected double invoke_D(Object a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); } + protected Object invoke_L(int a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); } + protected int invoke_I(int a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); } + protected long invoke_J(int a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); } + protected float invoke_F(int a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); } + protected double invoke_D(int a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); } + protected Object invoke_L(Object a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); } + protected int invoke_I(Object a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); } + protected long invoke_J(Object a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); } + protected float invoke_F(Object a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); } + protected double invoke_D(Object a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); } + protected Object invoke_L(long a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); } + protected int invoke_I(long a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); } + protected long invoke_J(long a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); } + protected float invoke_F(long a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); } + protected double invoke_D(long a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); } } static class A3 extends Adapter { protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2) { return invoker.invoke(target, a0, a1, a2); } - protected Object targetA3(Object a0, Object a1, Object a2) { return target(a0, a1, a2); } - protected Object targetA3(Object a0, Object a1, int a2) { return target(a0, a1, a2); } - protected Object targetA3(Object a0, int a1, int a2) { return target(a0, a1, a2); } - protected Object targetA3(int a0, int a1, int a2) { return target(a0, a1, a2); } - protected Object targetA3(Object a0, Object a1, long a2) { return target(a0, a1, a2); } - protected Object targetA3(Object a0, long a1, long a2) { return target(a0, a1, a2); } - protected Object targetA3(long a0, long a1, long a2) { return target(a0, a1, a2); } - protected Object invoke_L(Object a0, Object a1, Object a2) { return return_L(targetA3(a0, a1, a2)); } - protected int invoke_I(Object a0, Object a1, Object a2) { return return_I(targetA3(a0, a1, a2)); } - protected long invoke_J(Object a0, Object a1, Object a2) { return return_J(targetA3(a0, a1, a2)); } - protected float invoke_F(Object a0, Object a1, Object a2) { return return_F(targetA3(a0, a1, a2)); } - protected double invoke_D(Object a0, Object a1, Object a2) { return return_D(targetA3(a0, a1, a2)); } - protected Object invoke_L(Object a0, Object a1, int a2) { return return_L(targetA3(a0, a1, a2)); } - protected int invoke_I(Object a0, Object a1, int a2) { return return_I(targetA3(a0, a1, a2)); } - protected long invoke_J(Object a0, Object a1, int a2) { return return_J(targetA3(a0, a1, a2)); } - protected float invoke_F(Object a0, Object a1, int a2) { return return_F(targetA3(a0, a1, a2)); } - protected double invoke_D(Object a0, Object a1, int a2) { return return_D(targetA3(a0, a1, a2)); } - protected Object invoke_L(Object a0, int a1, int a2) { return return_L(targetA3(a0, a1, a2)); } - protected int invoke_I(Object a0, int a1, int a2) { return return_I(targetA3(a0, a1, a2)); } - protected long invoke_J(Object a0, int a1, int a2) { return return_J(targetA3(a0, a1, a2)); } - protected float invoke_F(Object a0, int a1, int a2) { return return_F(targetA3(a0, a1, a2)); } - protected double invoke_D(Object a0, int a1, int a2) { return return_D(targetA3(a0, a1, a2)); } - protected Object invoke_L(int a0, int a1, int a2) { return return_L(targetA3(a0, a1, a2)); } - protected int invoke_I(int a0, int a1, int a2) { return return_I(targetA3(a0, a1, a2)); } - protected long invoke_J(int a0, int a1, int a2) { return return_J(targetA3(a0, a1, a2)); } - protected float invoke_F(int a0, int a1, int a2) { return return_F(targetA3(a0, a1, a2)); } - protected double invoke_D(int a0, int a1, int a2) { return return_D(targetA3(a0, a1, a2)); } - protected Object invoke_L(Object a0, Object a1, long a2) { return return_L(targetA3(a0, a1, a2)); } - protected int invoke_I(Object a0, Object a1, long a2) { return return_I(targetA3(a0, a1, a2)); } - protected long invoke_J(Object a0, Object a1, long a2) { return return_J(targetA3(a0, a1, a2)); } - protected float invoke_F(Object a0, Object a1, long a2) { return return_F(targetA3(a0, a1, a2)); } - protected double invoke_D(Object a0, Object a1, long a2) { return return_D(targetA3(a0, a1, a2)); } - protected Object invoke_L(Object a0, long a1, long a2) { return return_L(targetA3(a0, a1, a2)); } - protected int invoke_I(Object a0, long a1, long a2) { return return_I(targetA3(a0, a1, a2)); } - protected long invoke_J(Object a0, long a1, long a2) { return return_J(targetA3(a0, a1, a2)); } - protected float invoke_F(Object a0, long a1, long a2) { return return_F(targetA3(a0, a1, a2)); } - protected double invoke_D(Object a0, long a1, long a2) { return return_D(targetA3(a0, a1, a2)); } - protected Object invoke_L(long a0, long a1, long a2) { return return_L(targetA3(a0, a1, a2)); } - protected int invoke_I(long a0, long a1, long a2) { return return_I(targetA3(a0, a1, a2)); } - protected long invoke_J(long a0, long a1, long a2) { return return_J(targetA3(a0, a1, a2)); } - protected float invoke_F(long a0, long a1, long a2) { return return_F(targetA3(a0, a1, a2)); } - protected double invoke_D(long a0, long a1, long a2) { return return_D(targetA3(a0, a1, a2)); } + protected Object target(Object a0, Object a1, Object a2) throws Throwable { return invoker.invoke(target, a0, a1, a2); } + protected Object targetA3(Object a0, Object a1, Object a2) throws Throwable { return target(a0, a1, a2); } + protected Object targetA3(Object a0, Object a1, int a2) throws Throwable { return target(a0, a1, a2); } + protected Object targetA3(Object a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); } + protected Object targetA3(int a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); } + protected Object targetA3(Object a0, Object a1, long a2) throws Throwable { return target(a0, a1, a2); } + protected Object targetA3(Object a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); } + protected Object targetA3(long a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); } + protected Object invoke_L(Object a0, Object a1, Object a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); } + protected int invoke_I(Object a0, Object a1, Object a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); } + protected long invoke_J(Object a0, Object a1, Object a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); } + protected float invoke_F(Object a0, Object a1, Object a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); } + protected double invoke_D(Object a0, Object a1, Object a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); } + protected Object invoke_L(Object a0, Object a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); } + protected int invoke_I(Object a0, Object a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); } + protected long invoke_J(Object a0, Object a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); } + protected float invoke_F(Object a0, Object a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); } + protected double invoke_D(Object a0, Object a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); } + protected Object invoke_L(Object a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); } + protected int invoke_I(Object a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); } + protected long invoke_J(Object a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); } + protected float invoke_F(Object a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); } + protected double invoke_D(Object a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); } + protected Object invoke_L(int a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); } + protected int invoke_I(int a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); } + protected long invoke_J(int a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); } + protected float invoke_F(int a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); } + protected double invoke_D(int a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); } + protected Object invoke_L(Object a0, Object a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); } + protected int invoke_I(Object a0, Object a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); } + protected long invoke_J(Object a0, Object a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); } + protected float invoke_F(Object a0, Object a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); } + protected double invoke_D(Object a0, Object a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); } + protected Object invoke_L(Object a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); } + protected int invoke_I(Object a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); } + protected long invoke_J(Object a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); } + protected float invoke_F(Object a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); } + protected double invoke_D(Object a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); } + protected Object invoke_L(long a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); } + protected int invoke_I(long a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); } + protected long invoke_J(long a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); } + protected float invoke_F(long a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); } + protected double invoke_D(long a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); } } //params=[4, 5, 2, 99, 99, 99] static class A4 extends Adapter { protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3) { return invoker.invoke(target, a0, a1, a2, a3); } - protected Object targetA4(Object a0, Object a1, Object a2, Object a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(Object a0, Object a1, Object a2, int a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(Object a0, Object a1, int a2, int a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(Object a0, int a1, int a2, int a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(int a0, int a1, int a2, int a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(Object a0, Object a1, Object a2, long a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(Object a0, Object a1, long a2, long a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(Object a0, long a1, long a2, long a3) { return target(a0, a1, a2, a3); } - protected Object targetA4(long a0, long a1, long a2, long a3) { return target(a0, a1, a2, a3); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(Object a0, Object a1, Object a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(Object a0, Object a1, Object a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(Object a0, Object a1, Object a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(Object a0, Object a1, int a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(Object a0, Object a1, int a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(Object a0, Object a1, int a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(Object a0, int a1, int a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(Object a0, int a1, int a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(Object a0, int a1, int a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(int a0, int a1, int a2, int a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(int a0, int a1, int a2, int a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(int a0, int a1, int a2, int a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(Object a0, Object a1, Object a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(Object a0, Object a1, Object a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(Object a0, Object a1, Object a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(Object a0, Object a1, long a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(Object a0, Object a1, long a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(Object a0, Object a1, long a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(Object a0, long a1, long a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(Object a0, long a1, long a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(Object a0, long a1, long a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } - protected Object invoke_L(long a0, long a1, long a2, long a3) { return return_L(targetA4(a0, a1, a2, a3)); } - protected int invoke_I(long a0, long a1, long a2, long a3) { return return_I(targetA4(a0, a1, a2, a3)); } - protected long invoke_J(long a0, long a1, long a2, long a3) { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object target(Object a0, Object a1, Object a2, Object a3) throws Throwable { return invoker.invoke(target, a0, a1, a2, a3); } + protected Object targetA4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(Object a0, Object a1, Object a2, int a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(Object a0, Object a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(Object a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(int a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(Object a0, Object a1, Object a2, long a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(Object a0, Object a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(Object a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object targetA4(long a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(Object a0, Object a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(Object a0, Object a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(Object a0, Object a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(Object a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(Object a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(Object a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(int a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(int a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(int a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(Object a0, Object a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(Object a0, Object a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(Object a0, Object a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(Object a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(Object a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(Object a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } + protected Object invoke_L(long a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); } + protected int invoke_I(long a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); } + protected long invoke_J(long a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); } } static class A5 extends Adapter { protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) { return invoker.invoke(target, a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, Object a1, Object a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, Object a1, int a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, int a1, int a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(int a0, int a1, int a2, int a3, int a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, Object a1, Object a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, Object a1, long a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(Object a0, long a1, long a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } - protected Object targetA5(long a0, long a1, long a2, long a3, long a4) { return target(a0, a1, a2, a3, a4); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, Object a1, Object a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, Object a1, Object a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, Object a1, Object a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, Object a1, int a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, Object a1, int a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, Object a1, int a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, int a1, int a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, int a1, int a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, int a1, int a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(int a0, int a1, int a2, int a3, int a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(int a0, int a1, int a2, int a3, int a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(int a0, int a1, int a2, int a3, int a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(Object a0, long a1, long a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(Object a0, long a1, long a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } - protected Object invoke_L(long a0, long a1, long a2, long a3, long a4) { return return_L(targetA5(a0, a1, a2, a3, a4)); } - protected int invoke_I(long a0, long a1, long a2, long a3, long a4) { return return_I(targetA5(a0, a1, a2, a3, a4)); } - protected long invoke_J(long a0, long a1, long a2, long a3, long a4) { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return invoker.invoke(target, a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(int a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object targetA5(long a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } + protected Object invoke_L(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); } + protected int invoke_I(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); } + protected long invoke_J(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); } } //params=[6, 10, 2, 99, 0, 99] static class A6 extends Adapter { protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return invoker.invoke(target, a0, a1, a2, a3, a4, a5); } - protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return target(a0, a1, a2, a3, a4, a5); } - protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } - protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } - protected Object targetA6(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } - protected Object targetA6(Object a0, Object a1, long a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } - protected Object targetA6(Object a0, long a1, long a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } - protected Object targetA6(long a0, long a1, long a2, long a3, long a4, long a5) { return target(a0, a1, a2, a3, a4, a5); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } - protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } - protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } - protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } - protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } - protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } - protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } - protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } - protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } - protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } - protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5) { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } - protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5) { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } - protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5) { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return invoker.invoke(target, a0, a1, a2, a3, a4, a5); } + protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } + protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } + protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } + protected Object targetA6(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } + protected Object targetA6(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } + protected Object targetA6(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } + protected Object targetA6(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } + protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } + protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } + protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } + protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } + protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } + protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } + protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); } + protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); } + protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); } } static class A7 extends Adapter { protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object targetA7(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return target(a0, a1, a2, a3, a4, a5, a6); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } - protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object targetA7(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); } + protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); } } static class A8 extends Adapter { protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object targetA8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return target(a0, a1, a2, a3, a4, a5, a6, a7); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } - protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object targetA8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } + protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); } } static class A9 extends Adapter { protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object targetA9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } - protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object targetA9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } + protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); } } static class A10 extends Adapter { protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); } protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); } - protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object targetA10(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } - protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return invoker.invoke(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object targetA10(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } + protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); } } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/empty/Empty.java --- a/jdk/src/share/classes/sun/dyn/empty/Empty.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/empty/Empty.java Wed Jul 05 17:05:01 2017 +0200 @@ -29,6 +29,10 @@ * An empty class in an empty package. * Used as a proxy for unprivileged code, since making access checks * against it will only succeed against public methods in public types. + *

    + * This class also stands (internally to sun.dyn) for the type of a + * value that cannot be produced, because the expression of this type + * always returns abnormally. (Cf. Nothing in the closures proposal.) * @author jrose */ public class Empty { diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,137 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.dyn.util; + +import java.dyn.MethodType; +import java.util.ArrayList; +import java.util.List; + +/** + * Utility routines for dealing with bytecode-level signatures. + * @author jrose + */ +public class BytecodeDescriptor { + + private BytecodeDescriptor() { } // cannot instantiate + + public static List> parseMethod(String bytecodeSignature, ClassLoader loader) { + return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader); + } + + static List> parseMethod(String bytecodeSignature, + int start, int end, ClassLoader loader) { + if (loader == null) + loader = ClassLoader.getSystemClassLoader(); + String str = bytecodeSignature; + int[] i = {start}; + ArrayList> ptypes = new ArrayList>(); + if (i[0] < end && str.charAt(i[0]) == '(') { + ++i[0]; // skip '(' + while (i[0] < end && str.charAt(i[0]) != ')') { + Class pt = parseSig(str, i, end, loader); + if (pt == null || pt == void.class) + parseError(str, "bad argument type"); + ptypes.add(pt); + } + ++i[0]; // skip ')' + } else { + parseError(str, "not a method type"); + } + Class rtype = parseSig(str, i, end, loader); + if (rtype == null || i[0] != end) + parseError(str, "bad return type"); + ptypes.add(rtype); + return ptypes; + } + + static private void parseError(String str, String msg) { + throw new IllegalArgumentException("bad signature: "+str+": "+msg); + } + + static private Class parseSig(String str, int[] i, int end, ClassLoader loader) { + if (i[0] == end) return null; + char c = str.charAt(i[0]++); + if (c == 'L') { + int begc = i[0], endc = str.indexOf(';', begc); + if (endc < 0) return null; + i[0] = endc+1; + String name = str.substring(begc, endc).replace('/', '.'); + try { + return loader.loadClass(name); + } catch (ClassNotFoundException ex) { + throw new TypeNotPresentException(name, ex); + } + } else if (c == '[') { + Class t = parseSig(str, i, end, loader); + if (t != null) + t = java.lang.reflect.Array.newInstance(t, 0).getClass(); + return t; + } else { + return Wrapper.forBasicType(c).primitiveType(); + } + } + + public static String unparse(Class type) { + StringBuilder sb = new StringBuilder(); + unparseSig(type, sb); + return sb.toString(); + } + + public static String unparse(MethodType type) { + return unparseMethod(type.returnType(), type.parameterList()); + } + + public static String unparse(Object type) { + if (type instanceof Class) + return unparse((Class) type); + if (type instanceof MethodType) + return unparse((MethodType) type); + return (String) type; + } + + public static String unparseMethod(Class rtype, List> ptypes) { + StringBuilder sb = new StringBuilder(); + sb.append('('); + for (Class pt : ptypes) + unparseSig(pt, sb); + sb.append(')'); + unparseSig(rtype, sb); + return sb.toString(); + } + + static private void unparseSig(Class t, StringBuilder sb) { + char c = Wrapper.forBasicType(t).basicTypeChar(); + if (c != 'L') { + sb.append(c); + } else { + boolean lsemi = (!t.isArray()); + if (lsemi) sb.append('L'); + sb.append(t.getName().replace('.', '/')); + if (lsemi) sb.append(';'); + } + } + +} diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/util/BytecodeName.java --- a/jdk/src/share/classes/sun/dyn/util/BytecodeName.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/util/BytecodeName.java Wed Jul 05 17:05:01 2017 +0200 @@ -298,6 +298,8 @@ * The name {@code <init>} will be parsed into { '<', "init", '>'}} * The name {@code foo/bar$:baz} will be parsed into * {@code {"foo", '/', "bar", '$', ':', "baz"}}. + * The name {@code ::\=:foo:\=bar\!baz} will be parsed into + * {@code {':', ':', "", ':', "foo", ':', "bar:baz"}}. */ public static Object[] parseBytecodeName(String s) { int slen = s.length(); @@ -315,7 +317,7 @@ if (lasti < i) { // normal component if (pass != 0) - res[fillp] = s.substring(lasti, i); + res[fillp] = toSourceName(s.substring(lasti, i)); fillp++; lasti = i+1; } @@ -323,13 +325,14 @@ if (pass != 0) res[fillp] = DANGEROUS_CHARS_CA[whichDC]; fillp++; + lasti = i+1; } } if (pass != 0) break; // between passes, build the result array - res = new String[fillp]; - if (fillp <= 1) { - if (fillp != 0) res[0] = s; + res = new Object[fillp]; + if (fillp <= 1 && lasti == 0) { + if (fillp != 0) res[0] = toSourceName(s); break; } } @@ -348,9 +351,19 @@ * @throws NullPointerException if any component is null */ public static String unparseBytecodeName(Object[] components) { - for (Object c : components) { - if (c instanceof String) - checkSafeBytecodeName((String) c); // may fail + Object[] components0 = components; + for (int i = 0; i < components.length; i++) { + Object c = components[i]; + if (c instanceof String) { + String mc = toBytecodeName((String) c); + if (i == 0 && components.length == 1) + return mc; // usual case + if ((Object)mc != c) { + if (components == components0) + components = components.clone(); + components[i] = c = mc; + } + } } return appendAll(components); } @@ -381,6 +394,14 @@ * If the bytecode name contains dangerous characters, * assume that they are being used as punctuation, * and pass them through unchanged. + * Non-empty runs of non-dangerous characters are demangled + * if necessary, and the resulting names are quoted if + * they are not already valid Java identifiers, or if + * they contain a dangerous character (i.e., dollar sign "$"). + * Single quotes are used when quoting. + * Within quoted names, embedded single quotes and backslashes + * are further escaped by prepended backslashes. + * * @param s the original bytecode name (which may be qualified) * @return a human-readable presentation */ @@ -389,10 +410,10 @@ for (int i = 0; i < components.length; i++) { if (!(components[i] instanceof String)) continue; - String c = (String) components[i]; - // pretty up the name by demangling it - String sn = toSourceName(c); - if ((Object)sn != c || !isJavaIdent(sn)) { + String sn = (String) components[i]; + // note that the name is already demangled! + //sn = toSourceName(sn); + if (!isJavaIdent(sn) || sn.indexOf('$') >=0 ) { components[i] = quoteDisplay(sn); } } @@ -401,10 +422,10 @@ private static boolean isJavaIdent(String s) { int slen = s.length(); if (slen == 0) return false; - if (!Character.isUnicodeIdentifierStart(s.charAt(0))) + if (!Character.isJavaIdentifierStart(s.charAt(0))) return false; for (int i = 1; i < slen; i++) { - if (!Character.isUnicodeIdentifierPart(s.charAt(0))) + if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; } return true; @@ -602,110 +623,5 @@ return -1; } - // test driver - static void main(String[] av) { - // If verbose is enabled, quietly check everything. - // Otherwise, print the output for the user to check. - boolean verbose = false; - int maxlen = 0; - - while (av.length > 0 && av[0].startsWith("-")) { - String flag = av[0].intern(); - av = java.util.Arrays.copyOfRange(av, 1, av.length); // Java 1.6 or later - if (flag == "-" || flag == "--") break; - else if (flag == "-q") - verbose = false; - else if (flag == "-v") - verbose = true; - else if (flag.startsWith("-l")) - maxlen = Integer.valueOf(flag.substring(2)); - else - throw new Error("Illegal flag argument: "+flag); - } - - if (maxlen == 0) - maxlen = (verbose ? 2 : 4); - if (verbose) System.out.println("Note: maxlen = "+maxlen); - - switch (av.length) { - case 0: av = new String[] { - DANGEROUS_CHARS.substring(0) + - REPLACEMENT_CHARS.substring(0, 1) + - NULL_ESCAPE + "x" - }; // and fall through: - case 1: - char[] cv = av[0].toCharArray(); - av = new String[cv.length]; - int avp = 0; - for (char c : cv) { - String s = String.valueOf(c); - if (c == 'x') s = "foo"; // tradition... - av[avp++] = s; - } - } - if (verbose) - System.out.println("Note: Verbose output mode enabled. Use '-q' to suppress."); - Tester t = new Tester(); - t.maxlen = maxlen; - t.verbose = verbose; - t.tokens = av; - t.test("", 0); - } - - static class Tester { - boolean verbose; - int maxlen; - java.util.Map map = new java.util.HashMap(); - String[] tokens; - - void test(String stringSoFar, int tokensSoFar) { - test(stringSoFar); - if (tokensSoFar <= maxlen) { - for (String token : tokens) { - if (token.length() == 0) continue; // skip empty tokens - if (stringSoFar.indexOf(token) != stringSoFar.lastIndexOf(token)) - continue; // there are already two occs. of this token - if (token.charAt(0) == ESCAPE_C && token.length() == 1 && maxlen < 4) - test(stringSoFar+token, tokensSoFar); // want lots of \'s - else if (tokensSoFar < maxlen) - test(stringSoFar+token, tokensSoFar+1); - } - } - } - - void test(String s) { - // for small batches, do not test the null string - if (s.length() == 0 && maxlen >=1 && maxlen <= 2) return; - String bn = testSourceName(s); - if (bn == null) return; - if (bn == s) { - //if (verbose) System.out.println(s+" == id"); - } else { - if (verbose) System.out.println(s+" => "+bn+" "+toDisplayName(bn)); - String bnbn = testSourceName(bn); - if (bnbn == null) return; - if (verbose) System.out.println(bn+" => "+bnbn+" "+toDisplayName(bnbn)); - /* - String bn3 = testSourceName(bnbn); - if (bn3 == null) return; - if (verbose) System.out.println(bnbn+" => "+bn3); - */ - } - } - - String testSourceName(String s) { - if (map.containsKey(s)) return null; - String bn = toBytecodeName(s); - map.put(s, bn); - String sn = toSourceName(bn); - if (!sn.equals(s)) { - String bad = (s+" => "+bn+" != "+sn); - if (!verbose) throw new Error("Bad mangling: "+bad); - System.out.println("*** "+bad); - return null; - } - return bn; - } - } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/util/BytecodeSignature.java --- a/jdk/src/share/classes/sun/dyn/util/BytecodeSignature.java Thu Dec 17 14:10:29 2009 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -/* - * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package sun.dyn.util; - -import java.dyn.MethodType; -import java.util.ArrayList; -import java.util.List; - -/** - * Utility routines for dealing with bytecode-level signatures. - * @author jrose - */ -public class BytecodeSignature { - - private BytecodeSignature() { } // cannot instantiate - - public static List> parseMethod(String bytecodeSignature, ClassLoader loader) { - return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader); - } - - static List> parseMethod(String bytecodeSignature, - int start, int end, ClassLoader loader) { - if (loader == null) - loader = ClassLoader.getSystemClassLoader(); - String str = bytecodeSignature; - int[] i = {start}; - ArrayList> ptypes = new ArrayList>(); - if (i[0] < end && str.charAt(i[0]) == '(') { - ++i[0]; // skip '(' - while (i[0] < end && str.charAt(i[0]) != ')') { - Class pt = parseSig(str, i, end, loader); - if (pt == null || pt == void.class) - parseError(str, "bad argument type"); - ptypes.add(pt); - } - ++i[0]; // skip ')' - } else { - parseError(str, "not a method type"); - } - Class rtype = parseSig(str, i, end, loader); - if (rtype == null || i[0] != end) - parseError(str, "bad return type"); - ptypes.add(rtype); - return ptypes; - } - - static private void parseError(String str, String msg) { - throw new IllegalArgumentException("bad signature: "+str+": "+msg); - } - - static private Class parseSig(String str, int[] i, int end, ClassLoader loader) { - if (i[0] == end) return null; - char c = str.charAt(i[0]++); - if (c == 'L') { - int begc = i[0], endc = str.indexOf(';', begc); - if (endc < 0) return null; - i[0] = endc+1; - String name = str.substring(begc, endc).replace('/', '.'); - try { - return loader.loadClass(name); - } catch (ClassNotFoundException ex) { - throw new TypeNotPresentException(name, ex); - } - } else if (c == '[') { - Class t = parseSig(str, i, end, loader); - if (t != null) - t = java.lang.reflect.Array.newInstance(t, 0).getClass(); - return t; - } else { - return Wrapper.forBasicType(c).primitiveType(); - } - } - - public static String unparse(Class type) { - StringBuilder sb = new StringBuilder(); - unparseSig(type, sb); - return sb.toString(); - } - - public static String unparse(MethodType type) { - return unparseMethod(type.returnType(), type.parameterList()); - } - - public static String unparse(Object type) { - if (type instanceof Class) - return unparse((Class) type); - if (type instanceof MethodType) - return unparse((MethodType) type); - return (String) type; - } - - public static String unparseMethod(Class rtype, List> ptypes) { - StringBuilder sb = new StringBuilder(); - sb.append('('); - for (Class pt : ptypes) - unparseSig(pt, sb); - sb.append(')'); - unparseSig(rtype, sb); - return sb.toString(); - } - - static private void unparseSig(Class t, StringBuilder sb) { - char c = Wrapper.forBasicType(t).basicTypeChar(); - if (c != 'L') { - sb.append(c); - } else { - boolean lsemi = (!t.isArray()); - if (lsemi) sb.append('L'); - sb.append(t.getName().replace('.', '/')); - if (lsemi) sb.append(';'); - } - } - -} diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/util/ValueConversions.java --- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/util/ValueConversions.java Wed Jul 05 17:05:01 2017 +0200 @@ -27,7 +27,10 @@ import java.dyn.*; import java.dyn.MethodHandles.Lookup; +import java.util.ArrayList; +import java.util.Arrays; import java.util.EnumMap; +import java.util.List; import sun.dyn.Access; import sun.dyn.AdapterMethodHandle; import sun.dyn.MethodHandleImpl; @@ -37,6 +40,7 @@ private static final Lookup IMPL_LOOKUP = MethodHandleImpl.getLookup(IMPL_TOKEN); private static EnumMap[] newWrapperCaches(int n) { + @SuppressWarnings("unchecked") EnumMap[] caches = (EnumMap[]) new EnumMap[n]; // unchecked warning expected here for (int i = 0; i < n; i++) @@ -114,7 +118,7 @@ } private static MethodType unboxType(Wrapper wrap, boolean raw) { - return MethodType.make(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType()); + return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType()); } private static final EnumMap[] @@ -240,7 +244,7 @@ private static MethodType boxType(Wrapper wrap, boolean raw) { // be exact, since return casts are hard to compose Class boxType = wrap.wrapperType(); - return MethodType.make(boxType, rawWrapper(wrap, raw).primitiveType()); + return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType()); } private static Wrapper rawWrapper(Wrapper wrap, boolean raw) { @@ -305,29 +309,47 @@ /// Kludges for when raw values get accidentally boxed. + static int unboxRawInteger(Object x) { + if (x instanceof Integer) + return unboxInteger(x); + else + return (int) unboxLong(x); + } + + static Integer reboxRawInteger(Object x) { + if (x instanceof Integer) + return (Integer) x; + else + return (int) unboxLong(x); + } + static Byte reboxRawByte(Object x) { if (x instanceof Byte) return (Byte) x; - return boxByteRaw(unboxInteger(x)); + return boxByteRaw(unboxRawInteger(x)); } static Short reboxRawShort(Object x) { if (x instanceof Short) return (Short) x; - return boxShortRaw(unboxInteger(x)); + return boxShortRaw(unboxRawInteger(x)); } static Boolean reboxRawBoolean(Object x) { if (x instanceof Boolean) return (Boolean) x; - return boxBooleanRaw(unboxInteger(x)); + return boxBooleanRaw(unboxRawInteger(x)); } static Character reboxRawCharacter(Object x) { if (x instanceof Character) return (Character) x; - return boxCharacterRaw(unboxInteger(x)); + return boxCharacterRaw(unboxRawInteger(x)); } static Float reboxRawFloat(Object x) { if (x instanceof Float) return (Float) x; - return boxFloatRaw(unboxInteger(x)); + return boxFloatRaw(unboxRawInteger(x)); + } + + static Long reboxRawLong(Object x) { + return (Long) x; //never a rebox } static Double reboxRawDouble(Object x) { @@ -337,12 +359,21 @@ private static MethodType reboxType(Wrapper wrap) { Class boxType = wrap.wrapperType(); - return MethodType.make(boxType, Object.class); + return MethodType.methodType(boxType, Object.class); } private static final EnumMap[] REBOX_CONVERSIONS = newWrapperCaches(2); + /** + * Becase we normalize primitive types to reduce the number of signatures, + * primitives are sometimes manipulated under an "erased" type, + * either int (for types other than long/double) or long (for all types). + * When the erased primitive value is then boxed into an Integer or Long, + * the final boxed primitive is sometimes required. This transformation + * is called a "rebox". It takes an Integer or Long and produces some + * other boxed value. + */ public static MethodHandle rebox(Wrapper wrap, boolean exact) { EnumMap cache = REBOX_CONVERSIONS[exact?1:0]; MethodHandle mh = cache.get(wrap); @@ -355,9 +386,6 @@ mh = IDENTITY; break; case VOID: throw new IllegalArgumentException("cannot rebox a void"); - case INT: case LONG: - mh = cast(wrap.wrapperType(), exact); - break; } if (mh != null) { cache.put(wrap, mh); @@ -384,13 +412,21 @@ /// Width-changing conversions between int and long. static long widenInt(int x) { - return x; + return (long) x; + } + + static Long widenBoxedInt(Integer x) { + return (long)(int)x; } static int narrowLong(long x) { return (int) x; } + static Integer narrowBoxedLong(Long x) { + return (int)(long) x; + } + /// Constant functions static void ignore(Object x) { @@ -432,7 +468,7 @@ return mh; } // slow path - MethodType type = MethodType.make(wrap.primitiveType()); + MethodType type = MethodType.methodType(wrap.primitiveType()); switch (wrap) { case VOID: mh = EMPTY; @@ -500,11 +536,11 @@ private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY; static { try { - MethodType idType = MethodType.makeGeneric(1); - MethodType castType = idType.insertParameterType(0, Class.class); + MethodType idType = MethodType.genericMethodType(1); + MethodType castType = idType.insertParameterTypes(0, Class.class); MethodType alwaysZeroType = idType.changeReturnType(int.class); MethodType ignoreType = idType.changeReturnType(void.class); - MethodType zeroObjectType = MethodType.makeGeneric(0); + MethodType zeroObjectType = MethodType.genericMethodType(0); IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType); //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType); @@ -512,7 +548,7 @@ ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType); ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType); IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType); - EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterType(0)); + EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1)); } catch (RuntimeException ex) { throw ex; } @@ -543,10 +579,10 @@ else if (VerifyType.isNullType(type)) mh = ALWAYS_NULL; else - mh = MethodHandles.insertArgument(CAST_REFERENCE, 0, type); + mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); if (exact) { - MethodType xmt = MethodType.make(type, Object.class); - mh = AdapterMethodHandle.makeRawRetypeOnly(IMPL_TOKEN, xmt, mh); + MethodType xmt = MethodType.methodType(type, Object.class); + mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh); } if (cache != null) cache.put(wrap, mh); @@ -560,4 +596,127 @@ private static MethodHandle retype(MethodType type, MethodHandle mh) { return AdapterMethodHandle.makeRetypeOnly(IMPL_TOKEN, type, mh); } + + private static final Object[] NO_ARGS_ARRAY = {}; + private static Object[] makeArray(Object... args) { return args; } + private static Object[] array() { return NO_ARGS_ARRAY; } + private static Object[] array(Object a0) + { return makeArray(a0); } + private static Object[] array(Object a0, Object a1) + { return makeArray(a0, a1); } + private static Object[] array(Object a0, Object a1, Object a2) + { return makeArray(a0, a1, a2); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3) + { return makeArray(a0, a1, a2, a3); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4) + { return makeArray(a0, a1, a2, a3, a4); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) + { return makeArray(a0, a1, a2, a3, a4, a5); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) + { return makeArray(a0, a1, a2, a3, a4, a5, a6); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + static MethodHandle[] makeArrays() { + ArrayList arrays = new ArrayList(); + MethodHandles.Lookup lookup = IMPL_LOOKUP; + for (;;) { + int nargs = arrays.size(); + MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class); + String name = "array"; + MethodHandle array = null; + try { + array = lookup.findStatic(ValueConversions.class, name, type); + } catch (NoAccessException ex) { + } + if (array == null) break; + arrays.add(array); + } + assert(arrays.size() == 11); // current number of methods + return arrays.toArray(new MethodHandle[0]); + } + static final MethodHandle[] ARRAYS = makeArrays(); + + /** Return a method handle that takes the indicated number of Object + * arguments and returns an Object array of them, as if for varargs. + */ + public static MethodHandle varargsArray(int nargs) { + if (nargs < ARRAYS.length) + return ARRAYS[nargs]; + // else need to spin bytecode or do something else fancy + throw new UnsupportedOperationException("NYI"); + } + + private static final List NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); + private static List makeList(Object... args) { return Arrays.asList(args); } + private static List list() { return NO_ARGS_LIST; } + private static List list(Object a0) + { return makeList(a0); } + private static List list(Object a0, Object a1) + { return makeList(a0, a1); } + private static List list(Object a0, Object a1, Object a2) + { return makeList(a0, a1, a2); } + private static List list(Object a0, Object a1, Object a2, Object a3) + { return makeList(a0, a1, a2, a3); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4) + { return makeList(a0, a1, a2, a3, a4); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) + { return makeList(a0, a1, a2, a3, a4, a5); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) + { return makeList(a0, a1, a2, a3, a4, a5, a6); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) + { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) + { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) + { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + static MethodHandle[] makeLists() { + ArrayList arrays = new ArrayList(); + MethodHandles.Lookup lookup = IMPL_LOOKUP; + for (;;) { + int nargs = arrays.size(); + MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class); + String name = "list"; + MethodHandle array = null; + try { + array = lookup.findStatic(ValueConversions.class, name, type); + } catch (NoAccessException ex) { + } + if (array == null) break; + arrays.add(array); + } + assert(arrays.size() == 11); // current number of methods + return arrays.toArray(new MethodHandle[0]); + } + static final MethodHandle[] LISTS = makeLists(); + + /** Return a method handle that takes the indicated number of Object + * arguments and returns List. + */ + public static MethodHandle varargsList(int nargs) { + if (nargs < LISTS.length) + return LISTS[nargs]; + // else need to spin bytecode or do something else fancy + throw new UnsupportedOperationException("NYI"); + } } + diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/util/VerifyAccess.java --- a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java Wed Jul 05 17:05:01 2017 +0200 @@ -26,8 +26,12 @@ package sun.dyn.util; import java.dyn.LinkagePermission; +import java.dyn.MethodHandles.Lookup; +import java.dyn.NoAccessException; import java.lang.reflect.Modifier; -import sun.dyn.Access; +import sun.dyn.MemberName; +import sun.dyn.MethodHandleImpl; +import sun.dyn.empty.Empty; /** * This class centralizes information about the JVM's linkage access control. @@ -45,21 +49,21 @@ *

    * Some circumstances require an additional check on the * leading parameter (the receiver) of the method, if it is non-static. - * In the case of {@code invokespecial} ({@code doDispatch} is false), + * In the case of {@code invokespecial} ({@code isSpecialInvoke} is true), * the leading parameter must be the accessing class or a subclass. * In the case of a call to a {@code protected} method outside the same * package, the same constraint applies. * @param m the proposed callee - * @param doDispatch if false, a non-static m will be invoked as if by {@code invokespecial} + * @param isSpecialInvoke if true, a non-static method m is checked as if for {@code invokespecial} * @param lookupClass the class for which the access check is being made * @return null if the method is not accessible, else a receiver type constraint, else {@code Object.class} */ public static Class isAccessible(Class defc, int mods, - boolean doDispatch, Class lookupClass) { + Class lookupClass, boolean isSpecialInvoke) { if (!isAccessible(defc, lookupClass)) return null; Class constraint = Object.class; - if (!doDispatch && !Modifier.isStatic(mods)) { + if (isSpecialInvoke && !Modifier.isStatic(mods)) { constraint = lookupClass; } if (Modifier.isPublic(mods)) @@ -166,4 +170,38 @@ if (isSamePackage(requestingClass, subjectClass)) return; security.checkPermission(new LinkagePermission(permissionName, requestingClass)); } + + private static RuntimeException checkNameFailed(MemberName self, Lookup lookup, String comment) { + return new NoAccessException("cannot access from "+lookup+": "+self.toString()+": "+comment); + } + public static void checkName(MemberName self, Lookup lookup) { + Class lc = lookup.lookupClass(); + if (lc == null) return; // lookup is privileged + Class dc = self.getDeclaringClass(); + int samepkg = 0; + // First check the containing class. Must be public or local. + if (!Modifier.isPublic(dc.getModifiers())) { + if (lc != Empty.class) + samepkg = (isSamePackage(dc, lc) ? 1 : -1); + if (samepkg <= 0) + throw checkNameFailed(self, lookup, "class is not public"); + } + // At this point dc is known to be accessible. + if (self.isPublic()) { + return; + } else if (lc == Empty.class) { + throw checkNameFailed(self, lookup, "member is not public"); + } else if (self.isProtected()) { + if (dc.isAssignableFrom(lc)) return; + } else if (self.isPrivate()) { + if (isSamePackageMember(dc, lc)) return; + throw checkNameFailed(self, lookup, "member is private"); + } + // Fall-through handles the package-private and protected cases. + if (samepkg == 0) + samepkg = (isSamePackage(dc, lc) ? 1 : -1); + if (samepkg > 0) return; + throw checkNameFailed(self, lookup, + self.isProtected() ? "member is protected" : "member is private to package"); + } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/util/VerifyType.java --- a/jdk/src/share/classes/sun/dyn/util/VerifyType.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/util/VerifyType.java Wed Jul 05 17:05:01 2017 +0200 @@ -26,6 +26,7 @@ package sun.dyn.util; import java.dyn.MethodType; +import sun.dyn.empty.Empty; /** * This class centralizes information about the JVM verifier @@ -73,29 +74,28 @@ } /** - * Is the given type either java.lang.Void or java.lang.Null? - * These types serve as markers for bare nulls and therefore - * may be promoted to any type. This is secure, since + * Is the given type java.lang.Null or an equivalent null-only type? */ public static boolean isNullType(Class type) { if (type == null) return false; - return type == NULL_CLASS_1 || type == NULL_CLASS_2; + return type == NULL_CLASS + // This one may also be used as a null type. + // TO DO: Decide if we really want to legitimize it here. + // Probably we do, unless java.lang.Null really makes it into Java 7 + //|| type == Void.class + // Locally known null-only class: + || type == Empty.class + ; } - private static final Class NULL_CLASS_1, NULL_CLASS_2; + private static final Class NULL_CLASS; static { - Class nullClass1 = null, nullClass2 = null; + Class nullClass = null; try { - nullClass1 = Class.forName("java.lang.Null"); + nullClass = Class.forName("java.lang.Null"); } catch (ClassNotFoundException ex) { // OK, we'll cope } - NULL_CLASS_1 = nullClass1; - - // This one may also be used as a null type. - // TO DO: Decide if we really want to legitimize it here. - // Probably we do, unless java.lang.Null really makes it into Java 7 - nullClass2 = Void.class; - NULL_CLASS_2 = nullClass2; + NULL_CLASS = nullClass; } /** @@ -191,6 +191,11 @@ // to be captured as a garbage int. // Caller promises that the actual value will be disregarded. return dst == int.class ? 1 : 0; + if (isNullType(src)) + // Special permission for raw conversions: allow a null + // to be reinterpreted as anything. For objects, it is safe, + // and for primitives you get a garbage value (probably zero). + return 1; if (!src.isPrimitive()) return 0; Wrapper sw = Wrapper.forPrimitiveType(src); diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/dyn/util/Wrapper.java --- a/jdk/src/share/classes/sun/dyn/util/Wrapper.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/dyn/util/Wrapper.java Wed Jul 05 17:05:01 2017 +0200 @@ -141,13 +141,19 @@ * @throws IllegalArgumentException for unexpected types */ public static Wrapper forPrimitiveType(Class type) { + Wrapper w = findPrimitiveType(type); + if (w != null) return w; + if (type.isPrimitive()) + throw new InternalError(); // redo hash function + throw newIllegalArgumentException("not primitive: "+type); + } + + static Wrapper findPrimitiveType(Class type) { Wrapper w = FROM_PRIM[hashPrim(type)]; if (w != null && w.primitiveType == type) { return w; } - if (type.isPrimitive()) - throw new InternalError(); // redo hash function - throw newIllegalArgumentException("not primitive: "+type); + return null; } /** Return the wrapper that wraps values into the given wrapper type. @@ -160,7 +166,7 @@ Wrapper w = findWrapperType(type); if (w != null) return w; for (Wrapper x : values()) - if (w.wrapperType == type) + if (x.wrapperType == type) throw new InternalError(); // redo hash function throw newIllegalArgumentException("not wrapper: "+type); } @@ -244,8 +250,10 @@ public Class wrapperType() { return wrapperType; } /** What is the wrapper type for this wrapper? - * The example type must be the wrapper type, + * Otherwise, the example type must be the wrapper type, * or the corresponding primitive type. + * (For {@code OBJECT}, the example type can be any non-primitive, + * and is normalized to {@code Object.class}.) * The resulting class type has the same type parameter. */ public Class wrapperType(Class exampleType) { @@ -290,6 +298,16 @@ return type.isPrimitive(); } + /** What is the bytecode signature character for this type? + * All non-primitives, including array types, report as 'L', the signature character for references. + */ + public static char basicTypeChar(Class type) { + if (!type.isPrimitive()) + return 'L'; + else + return forPrimitiveType(type).basicTypeChar(); + } + /** What is the bytecode signature character for this wrapper's * primitive type? */ @@ -309,7 +327,7 @@ /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type. * Performs standard primitive conversions, including truncation and float conversions. * The given type must be compatible with this wrapper. That is, it must either - * be the wrapper type (or a subtype, in the case of {@code OBJECT} or else + * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else * it must be the wrapper's primitive type. * @throws ClassCastException if the given type is not compatible with this wrapper */ @@ -326,9 +344,17 @@ * If the target type is a primitive, change it to a wrapper. */ static Class forceType(Class type, Class exampleType) { + boolean z = (type == exampleType || + type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) || + exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) || + type == Object.class && !exampleType.isPrimitive()); + if (!z) + System.out.println(type+" <= "+exampleType); assert(type == exampleType || - type == asWrapperType(exampleType) || - type == Object.class && exampleType.isInterface()); + type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) || + exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) || + type == Object.class && !exampleType.isPrimitive()); + @SuppressWarnings("unchecked") Class result = (Class) type; // unchecked warning is expected here return result; } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java --- a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,6 +89,11 @@ Oid[] retVal = new Oid[mechs.length]; int pos = 0; + // Compatibility with RFC 2853 old NT_HOSTBASED_SERVICE value. + if (nameType.equals(GSSNameImpl.oldHostbasedServiceName)) { + nameType = GSSName.NT_HOSTBASED_SERVICE; + } + // Iterate thru all mechs in GSS for (int i = 0; i < mechs.length; i++) { // what nametypes does this mech support? diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java --- a/jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/jgss/GSSNameImpl.java Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,6 +81,29 @@ public class GSSNameImpl implements GSSName { + /** + * The old Oid used in RFC 2853. Now supported as + * input parameters in: + * + * 1. The four overloaded GSSManager.createName(*) methods + * 2. GSSManager.getMechsForName(Oid) + * + * Note that even if a GSSName is created with this old Oid, + * its internal name type and getStringNameType() output are + * always the new value. + */ + final static Oid oldHostbasedServiceName; + + static { + Oid tmp = null; + try { + tmp = new Oid("1.3.6.1.5.6.2"); + } catch (Exception e) { + // should never happen + } + oldHostbasedServiceName = tmp; + } + private GSSManagerImpl gssManager = null; /* @@ -134,6 +157,9 @@ Oid mech) throws GSSException { + if (oldHostbasedServiceName.equals(appNameType)) { + appNameType = GSSName.NT_HOSTBASED_SERVICE; + } if (appName == null) throw new GSSExceptionImpl(GSSException.BAD_NAME, "Cannot import null name"); diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/jgss/GSSUtil.java --- a/jdk/src/share/classes/sun/security/jgss/GSSUtil.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/jgss/GSSUtil.java Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,9 +66,6 @@ public static final Oid NT_GSS_KRB5_PRINCIPAL = GSSUtil.createOid("1.2.840.113554.1.2.2.1"); - public static final Oid NT_HOSTBASED_SERVICE2 = - GSSUtil.createOid("1.2.840.113554.1.2.1.4"); - private static final String DEFAULT_HANDLER = "auth.login.defaultCallbackHandler"; diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java --- a/jdk/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/jgss/wrapper/GSSNameElement.java Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,8 +55,7 @@ static final GSSNameElement DEF_ACCEPTOR = new GSSNameElement(); private static Oid getNativeNameType(Oid nameType, GSSLibStub stub) { - if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType) || - GSSName.NT_HOSTBASED_SERVICE.equals(nameType)) { + if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) { Oid[] supportedNTs = null; try { supportedNTs = stub.inquireNamesForMech(); @@ -83,15 +82,9 @@ if (supportedNTs[i].equals(nameType)) return nameType; } // Special handling the specified name type - if (GSSUtil.NT_GSS_KRB5_PRINCIPAL.equals(nameType)) { - SunNativeProvider.debug("Override " + nameType + - " with mechanism default(null)"); - return null; // Use mechanism specific default - } else { - SunNativeProvider.debug("Override " + nameType + - " with " + GSSUtil.NT_HOSTBASED_SERVICE2); - return GSSUtil.NT_HOSTBASED_SERVICE2; - } + SunNativeProvider.debug("Override " + nameType + + " with mechanism default(null)"); + return null; // Use mechanism specific default } } return nameType; diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/krb5/Config.java --- a/jdk/src/share/classes/sun/security/krb5/Config.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/krb5/Config.java Wed Jul 05 17:05:01 2017 +0200 @@ -109,6 +109,7 @@ public static synchronized void refresh() throws KrbException { singleton = new Config(); KeyTab.refresh(); + KrbKdcReq.KdcAccessibility.reset(); } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/krb5/EncryptionKey.java --- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java Wed Jul 05 17:05:01 2017 +0200 @@ -512,6 +512,23 @@ } /** + * Determines if a kvno matches another kvno. Used in the method + * findKey(type, kvno, keys). Always returns true if either input + * is null or zero, in case any side does not have kvno info available. + * + * Note: zero is included because N/A is not a legal value for kvno + * in javax.security.auth.kerberos.KerberosKey. Therefore, the info + * that the kvno is N/A might be lost when converting between this + * class and KerberosKey. + */ + private static boolean versionMatches(Integer v1, Integer v2) { + if (v1 == null || v1 == 0 || v2 == null || v2 == 0) { + return true; + } + return v1.equals(v2); + } + + /** * Find a key with given etype and kvno * @param kvno if null, return any (first?) key */ @@ -525,15 +542,20 @@ } int ktype; + boolean etypeFound = false; for (int i = 0; i < keys.length; i++) { ktype = keys[i].getEType(); if (EType.isSupported(ktype)) { Integer kv = keys[i].getKeyVersionNumber(); - if (etype == ktype && (kvno == null || kvno.equals(kv))) { - return keys[i]; + if (etype == ktype) { + etypeFound = true; + if (versionMatches(kvno, kv)) { + return keys[i]; + } } } } + // Key not found. // allow DES key to be used for the DES etypes if ((etype == EncryptedData.ETYPE_DES_CBC_CRC || @@ -543,12 +565,16 @@ if (ktype == EncryptedData.ETYPE_DES_CBC_CRC || ktype == EncryptedData.ETYPE_DES_CBC_MD5) { Integer kv = keys[i].getKeyVersionNumber(); - if (kvno == null || kvno.equals(kv)) { + etypeFound = true; + if (versionMatches(kvno, kv)) { return new EncryptionKey(etype, keys[i].getBytes()); } } } } + if (etypeFound) { + throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER); + } return null; } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java --- a/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java Wed Jul 05 17:05:01 2017 +0200 @@ -31,25 +31,26 @@ package sun.security.krb5; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.Security; +import java.util.Locale; import sun.security.krb5.internal.Krb5; import sun.security.krb5.internal.UDPClient; import sun.security.krb5.internal.TCPClient; import java.io.IOException; -import java.io.InterruptedIOException; import java.net.SocketTimeoutException; -import java.net.UnknownHostException; import java.util.StringTokenizer; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.HashSet; public abstract class KrbKdcReq { - /** - * Default port for a KDC. - */ - private static final int DEFAULT_KDC_PORT = Krb5.KDC_INET_DEFAULT_PORT; - // Currently there is no option to specify retries // in the kerberos configuration file @@ -66,7 +67,48 @@ private static int udpPrefLimit = -1; + private static final String BAD_POLICY_KEY = "krb5.kdc.bad.policy"; + + /** + * What to do when a KDC is unavailable, specified in the + * java.security file with key krb5.kdc.bad.policy. + * Possible values can be TRY_LAST or TRY_LESS + */ + private enum BpType { + NONE, TRY_LAST, TRY_LESS + } + private static int tryLessMaxRetries = 1; + private static int tryLessTimeout = 5000; + + private static final BpType badPolicy; + static { + String value = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return Security.getProperty(BAD_POLICY_KEY); + } + }); + if (value != null) { + value = value.toLowerCase(Locale.ENGLISH); + String[] ss = value.split(":"); + if ("tryless".equals(ss[0])) { + if (ss.length > 1) { + String[] params = ss[1].split(","); + tryLessMaxRetries = Integer.parseInt(params[0]); + if (params.length > 1) { + tryLessTimeout = Integer.parseInt(params[1]); + } + } + badPolicy = BpType.TRY_LESS; + } else if ("trylast".equals(ss[0])) { + badPolicy = BpType.TRY_LAST; + } else { + badPolicy = BpType.NONE; + } + } else { + badPolicy = BpType.NONE; + } /* * Get default timeout. @@ -131,22 +173,16 @@ } } - /* - * Get timeout. - */ - - int timeout = getKdcTimeout(realm); - String kdcList = cfg.getKDCList(realm); if (kdcList == null) { throw new KrbException("Cannot get kdc for realm " + realm); } String tempKdc = null; // may include the port number also - StringTokenizer st = new StringTokenizer(kdcList); - while (st.hasMoreTokens()) { - tempKdc = st.nextToken(); + for (String tmp: KdcAccessibility.list(kdcList)) { + tempKdc = tmp; try { send(realm,tempKdc,useTCP); + KdcAccessibility.removeBad(tempKdc); break; } catch (Exception e) { if (DEBUG) { @@ -154,6 +190,7 @@ tempKdc); e.printStackTrace(System.out); } + KdcAccessibility.addBad(tempKdc); savedException = e; } } @@ -174,16 +211,21 @@ if (obuf == null) return; - PrivilegedActionException savedException = null; + int port = Krb5.KDC_INET_DEFAULT_PORT; + int retries = DEFAULT_KDC_RETRY_LIMIT; + int timeout = getKdcTimeout(realm); - /* - * Get timeout. - */ - int timeout = getKdcTimeout(realm); - /* - * Get port number for this KDC. - */ + if (badPolicy == BpType.TRY_LESS && + KdcAccessibility.isBad(tempKdc)) { + if (retries > tryLessMaxRetries) { + retries = tryLessMaxRetries; // less retries + } + if (timeout > tryLessTimeout) { + timeout = tryLessTimeout; // less time + } + } + String kdc = null; String portStr = null; @@ -225,12 +267,12 @@ + port + ", timeout=" + timeout + ", number of retries =" - + DEFAULT_KDC_RETRY_LIMIT + + retries + ", #bytes=" + obuf.length); } KdcCommunication kdcCommunication = - new KdcCommunication(kdc, port, useTCP, timeout, obuf); + new KdcCommunication(kdc, port, useTCP, timeout, retries, obuf); try { ibuf = AccessController.doPrivileged(kdcCommunication); if (DEBUG) { @@ -258,14 +300,16 @@ private int port; private boolean useTCP; private int timeout; + private int retries; private byte[] obuf; public KdcCommunication(String kdc, int port, boolean useTCP, - int timeout, byte[] obuf) { + int timeout, int retries, byte[] obuf) { this.kdc = kdc; this.port = port; this.useTCP = useTCP; this.timeout = timeout; + this.retries = retries; this.obuf = obuf; } @@ -294,7 +338,7 @@ } else { // For each KDC we try DEFAULT_KDC_RETRY_LIMIT (3) times to // get the response - for (int i=1; i <= DEFAULT_KDC_RETRY_LIMIT; i++) { + for (int i=1; i <= retries; i++) { UDPClient kdcClient = new UDPClient(kdc, port, timeout); if (DEBUG) { @@ -310,7 +354,7 @@ * Send the data to the kdc. */ - kdcClient.send(obuf); + kdcClient.send(obuf); /* * And get a response. @@ -323,7 +367,7 @@ System.out.println ("SocketTimeOutException with " + "attempt: " + i); } - if (i == DEFAULT_KDC_RETRY_LIMIT) { + if (i == retries) { ibuf = null; throw se; } @@ -385,4 +429,67 @@ return -1; } + + /** + * Maintains a KDC accessible list. Unavailable KDCs are put into a + * blacklist, when a KDC in the blacklist is available, it's removed + * from there. No insertion order in the blacklist. + * + * There are two methods to deal with KDCs in the blacklist. 1. Only try + * them when there's no KDC not on the blacklist. 2. Still try them, but + * with lesser number of retries and smaller timeout value. + */ + static class KdcAccessibility { + // Known bad KDCs + private static Set bads = new HashSet(); + + private static synchronized void addBad(String kdc) { + if (DEBUG) { + System.out.println(">>> KdcAccessibility: add " + kdc); + } + bads.add(kdc); + } + + private static synchronized void removeBad(String kdc) { + if (DEBUG) { + System.out.println(">>> KdcAccessibility: remove " + kdc); + } + bads.remove(kdc); + } + + private static synchronized boolean isBad(String kdc) { + return bads.contains(kdc); + } + + public static synchronized void reset() { + if (DEBUG) { + System.out.println(">>> KdcAccessibility: reset"); + } + bads.clear(); + } + + // Returns a preferred KDC list by putting the bad ones at the end + private static synchronized String[] list(String kdcList) { + StringTokenizer st = new StringTokenizer(kdcList); + List list = new ArrayList(); + if (badPolicy == BpType.TRY_LAST) { + List badkdcs = new ArrayList(); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + if (bads.contains(t)) badkdcs.add(t); + else list.add(t); + } + // Bad KDCs are put at last + list.addAll(badkdcs); + } else { + // All KDCs are returned in their original order, + // This include TRY_LESS and NONE + while (st.hasMoreTokens()) { + list.add(st.nextToken()); + } + } + return list.toArray(new String[list.size()]); + } + } } + diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java --- a/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,11 +50,12 @@ import sun.security.krb5.internal.crypto.KeyUsage; import sun.security.jgss.krb5.Krb5Util; +import sun.security.krb5.KrbException; +import sun.security.krb5.internal.Krb5; import sun.security.ssl.Debug; import sun.security.ssl.HandshakeInStream; import sun.security.ssl.HandshakeOutStream; -import sun.security.ssl.KerberosClientKeyExchange; import sun.security.ssl.ProtocolVersion; /** @@ -188,7 +189,14 @@ // See if we have the right key to decrypt the ticket to get // the session key. int encPartKeyType = encPart.getEType(); - KerberosKey dkey = findKey(encPartKeyType, serverKeys); + Integer encPartKeyVersion = encPart.getKeyVersionNumber(); + KerberosKey dkey = null; + try { + dkey = findKey(encPartKeyType, encPartKeyVersion, serverKeys); + } catch (KrbException ke) { // a kvno mismatch + throw new IOException( + "Cannot find key matching version number", ke); + } if (dkey == null) { // %%% Should print string repr of etype throw new IOException( @@ -355,12 +363,34 @@ return localPrincipal; } - private static KerberosKey findKey(int etype, KerberosKey[] keys) { + /** + * Determines if a kvno matches another kvno. Used in the method + * findKey(etype, version, keys). Always returns true if either input + * is null or zero, in case any side does not have kvno info available. + * + * Note: zero is included because N/A is not a legal value for kvno + * in javax.security.auth.kerberos.KerberosKey. Therefore, the info + * that the kvno is N/A might be lost when converting between + * EncryptionKey and KerberosKey. + */ + private static boolean versionMatches(Integer v1, int v2) { + if (v1 == null || v1 == 0 || v2 == 0) { + return true; + } + return v1.equals(v2); + } + + private static KerberosKey findKey(int etype, Integer version, + KerberosKey[] keys) throws KrbException { int ktype; + boolean etypeFound = false; for (int i = 0; i < keys.length; i++) { ktype = keys[i].getKeyType(); if (etype == ktype) { - return keys[i]; + etypeFound = true; + if (versionMatches(version, keys[i].getVersionNumber())) { + return keys[i]; + } } } // Key not found. @@ -370,14 +400,20 @@ for (int i = 0; i < keys.length; i++) { ktype = keys[i].getKeyType(); if (ktype == EncryptedData.ETYPE_DES_CBC_CRC || - ktype == EncryptedData.ETYPE_DES_CBC_MD5) { - return new KerberosKey(keys[i].getPrincipal(), - keys[i].getEncoded(), - etype, - keys[i].getVersionNumber()); + ktype == EncryptedData.ETYPE_DES_CBC_MD5) { + etypeFound = true; + if (versionMatches(version, keys[i].getVersionNumber())) { + return new KerberosKey(keys[i].getPrincipal(), + keys[i].getEncoded(), + etype, + keys[i].getVersionNumber()); + } } } } + if (etypeFound) { + throw new KrbException(Krb5.KRB_AP_ERR_BADKEYVER); + } return null; } } diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/lib/security/java.security --- a/jdk/src/share/lib/security/java.security Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/lib/security/java.security Wed Jul 05 17:05:01 2017 +0200 @@ -55,10 +55,10 @@ # # Select the source of seed data for SecureRandom. By default an -# attempt is made to use the entropy gathering device specified by +# attempt is made to use the entropy gathering device specified by # the securerandom.source property. If an exception occurs when -# accessing the URL then the traditional system/thread activity -# algorithm is used. +# accessing the URL then the traditional system/thread activity +# algorithm is used. # # On Solaris and Linux systems, if file:/dev/urandom is specified and it # exists, a special SecureRandom implementation is activated by default. @@ -72,7 +72,7 @@ # The entropy gathering device is described as a URL and can also # be specified with the system property "java.security.egd". For example, # -Djava.security.egd=file:/dev/urandom -# Specifying this system property will override the securerandom.source +# Specifying this system property will override the securerandom.source # setting. # @@ -149,7 +149,7 @@ security.overridePropertiesFile=true # -# Determines the default key and trust manager factory algorithms for +# Determines the default key and trust manager factory algorithms for # the javax.net.ssl package. # ssl.KeyManagerFactory.algorithm=SunX509 @@ -168,10 +168,10 @@ # is to cache for 30 seconds. # # NOTE: setting this to anything other than the default value can have -# serious security implications. Do not set it unless +# serious security implications. Do not set it unless # you are sure you are not exposed to DNS spoofing attack. # -#networkaddress.cache.ttl=-1 +#networkaddress.cache.ttl=-1 # The Java-level namelookup cache policy for failed lookups: # @@ -183,7 +183,7 @@ # the WINS name service in addition to DNS, name service lookups # that fail may take a noticeably long time to return (approx. 5 seconds). # For this reason the default caching policy is to maintain these -# results for 10 seconds. +# results for 10 seconds. # # networkaddress.cache.negative.ttl=10 @@ -192,7 +192,7 @@ # Properties to configure OCSP for certificate revocation checking # -# Enable OCSP +# Enable OCSP # # By default, OCSP is not used for certificate revocation checking. # This property enables the use of OCSP when set to the value "true". @@ -201,7 +201,7 @@ # # Example, # ocsp.enable=true - + # # Location of the OCSP responder # @@ -213,15 +213,15 @@ # # Example, # ocsp.responderURL=http://ocsp.example.net:80 - + # # Subject name of the OCSP responder's certificate # # By default, the certificate of the OCSP responder is that of the issuer # of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. In cases where +# of the OCSP responder when the default does not apply. Its value is a string +# distinguished name (defined in RFC 2253) which identifies a certificate in +# the set of certificates supplied during cert path validation. In cases where # the subject name alone is not sufficient to uniquely identify the certificate # then both the "ocsp.responderCertIssuerName" and # "ocsp.responderCertSerialNumber" properties must be used instead. When this @@ -237,14 +237,14 @@ # of the certificate being validated. This property identifies the certificate # of the OCSP responder when the default does not apply. Its value is a string # distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. When this -# property is set then the "ocsp.responderCertSerialNumber" property must also -# be set. When the "ocsp.responderCertSubjectName" property is set then this +# the set of certificates supplied during cert path validation. When this +# property is set then the "ocsp.responderCertSerialNumber" property must also +# be set. When the "ocsp.responderCertSubjectName" property is set then this # property is ignored. # # Example, # ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" - + # # Serial number of the OCSP responder's certificate # @@ -259,4 +259,31 @@ # # Example, # ocsp.responderCertSerialNumber=2A:FF:00 - + +# +# Policy for failed Kerberos KDC lookups: +# +# When a KDC is unavailable (network error, service failure, etc), it is +# put inside a blacklist and accessed less often for future requests. The +# value (case-insensitive) for this policy can be: +# +# tryLast +# KDCs in the blacklist are always tried after those not on the list. +# +# tryLess[:max_retries,timeout] +# KDCs in the blacklist are still tried by their order in the configuration, +# but with smaller max_retries and timeout values. max_retries and timeout +# are optional numerical parameters (default 1 and 5000, which means once +# and 5 seconds). Please notes that if any of the values defined here is +# more than what is defined in krb5.conf, it will be ignored. +# +# Whenever a KDC is detected as available, it is removed from the blacklist. +# The blacklist is reset when krb5.conf is reloaded. You can add +# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is +# reloaded whenever a JAAS authentication is attempted. +# +# Example, +# krb5.kdc.bad.policy = tryLast +# krb5.kdc.bad.policy = tryLess:2,2000 +krb5.kdc.bad.policy = tryLast + diff -r 4b85cf247673 -r df0a816d95ef jdk/src/share/native/java/lang/StrictMath.c --- a/jdk/src/share/native/java/lang/StrictMath.c Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/share/native/java/lang/StrictMath.c Wed Jul 05 17:05:01 2017 +0200 @@ -95,18 +95,6 @@ } JNIEXPORT jdouble JNICALL -Java_java_lang_StrictMath_ceil(JNIEnv *env, jclass unused, jdouble d) -{ - return (jdouble) jceil((double)d); -} - -JNIEXPORT jdouble JNICALL -Java_java_lang_StrictMath_floor(JNIEnv *env, jclass unused, jdouble d) -{ - return (jdouble) jfloor((double)d); -} - -JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2) { return (jdouble) jatan2((double)d1, (double)d2); diff -r 4b85cf247673 -r df0a816d95ef jdk/src/windows/native/java/net/SocketInputStream.c --- a/jdk/src/windows/native/java/net/SocketInputStream.c Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/src/windows/native/java/net/SocketInputStream.c Wed Jul 05 17:05:01 2017 +0200 @@ -121,6 +121,9 @@ newfd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); if (newfd == -1) { NET_ThrowSocketException(env, "Socket Closed"); + if (bufP != BUF) { + free(bufP); + } return -1; } } diff -r 4b85cf247673 -r df0a816d95ef jdk/test/Makefile --- a/jdk/test/Makefile Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/Makefile Wed Jul 05 17:05:01 2017 +0200 @@ -291,7 +291,7 @@ fi ; \ testExitCode=`$(CAT) $(EXITCODE)`; \ $(ECHO) "EXIT CODE: $${testExitCode}"; \ - exit ${testExitCode} + exit $${testExitCode} BUNDLE_UP_AND_EXIT = \ ( \ @@ -300,7 +300,7 @@ $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \ $(ECHO) "$${jtregExitCode}" > $(EXITCODE); \ if [ -r "$${_summary}" ] ; then \ - $(ECHO) "Summary: $${_summary}" > $(STATS_TXT); \ + $(ECHO) "Summary: $(UNIQUE_DIR)" > $(STATS_TXT); \ $(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \ $(EGREP) ' Passed\.' $(RUNLIST) \ | $(EGREP) -v ' Error\.' \ @@ -370,7 +370,8 @@ endif # With samevm, you cannot use -javaoptions? ifeq ($(USE_JTREG_SAMEVM),true) - EXTRA_JTREG_OPTIONS += -samevm $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%) + JTREG_SAMEVM_OPTION = -samevm + EXTRA_JTREG_OPTIONS += $(JTREG_SAMEVM_OPTION) $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%) JTREG_TEST_OPTIONS = $(JAVA_VM_ARGS:%=-vmoption:%) else JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%) @@ -418,8 +419,9 @@ $(MAKE) TESTDIRS="$(call TestDirs, $?)" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests endef define SummaryInfo -$(ECHO) "Summary for: $?" +$(ECHO) "########################################################" $(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME)) +$(ECHO) "########################################################" endef # ------------------------------------------------------------------ @@ -446,10 +448,14 @@ jdk_beans2: java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \ java/beans/PropertyEditor $(call RunOthervmBatch) + +# Stable othervm testruns (minus items from PROBLEM_LIST) +# Using samevm has serious problems with these tests JDK_ALL_TARGETS += jdk_beans3 jdk_beans3: java/beans/XMLEncoder $(call RunOthervmBatch) +# All beans tests jdk_beans: jdk_beans1 jdk_beans2 jdk_beans3 @$(SummaryInfo) @@ -475,6 +481,7 @@ jdk_management2: com/sun/jmx com/sun/management sun/management $(call RunOthervmBatch) +# All management tests jdk_management: jdk_management1 jdk_management2 @$(SummaryInfo) @@ -506,10 +513,14 @@ jdk_nio2: java/nio/Buffer java/nio/ByteOrder \ java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer $(call RunOthervmBatch) + +# Stable othervm testruns (minus items from PROBLEM_LIST) +# Using samevm has serious problems with these tests JDK_ALL_TARGETS += jdk_nio3 jdk_nio3: com/sun/nio sun/nio $(call RunOthervmBatch) +# All nio tests jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3 @$(SummaryInfo) @@ -529,10 +540,14 @@ JDK_ALL_TARGETS += jdk_security2 jdk_security2: javax/crypto com/sun/crypto $(call RunOthervmBatch) + +# Stable othervm testruns (minus items from PROBLEM_LIST) +# Using samevm has serious problems with these tests JDK_ALL_TARGETS += jdk_security3 jdk_security3: com/sun/security lib/security javax/security sun/security $(call RunOthervmBatch) +# All security tests jdk_security: jdk_security1 jdk_security2 jdk_security3 @$(SummaryInfo) @@ -547,15 +562,18 @@ jdk_text: java/text sun/text $(call RunSamevmBatch) -# Stable othervm testruns (minus items from PROBLEM_LIST) -# Using samevm has serious problems with these tests +# Stable samevm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_tools1 jdk_tools1: com/sun/jdi $(call RunSamevmBatch) + +# Stable othervm testruns (minus items from PROBLEM_LIST) +# Using samevm has serious problems with these tests JDK_ALL_TARGETS += jdk_tools2 jdk_tools2: com/sun/tools sun/jvmstat sun/tools tools vm com/sun/servicetag com/sun/tracing $(call RunOthervmBatch) +# All tools tests jdk_tools: jdk_tools1 jdk_tools2 @$(SummaryInfo) @@ -567,7 +585,9 @@ # ------------------------------------------------------------------ # Run all tests -jdk_all: $(filter-out jdk_awt jdk_rmi jdk_swing, $(JDK_ALL_TARGETS)) +FILTER_OUT_LIST=jdk_awt jdk_rmi jdk_swing +JDK_ALL_STABLE_TARGETS := $(filter-out $(FILTER_OUT_LIST), $(JDK_ALL_TARGETS)) +jdk_all: $(JDK_ALL_STABLE_TARGETS) @$(SummaryInfo) # These are all phony targets @@ -581,16 +601,22 @@ JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) # Only run automatic tests JTREG_BASIC_OPTIONS += -a +# Always turn on assertions +JTREG_ASSERT_OPTION = -ea -esa +JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION) # Report details on all failed or error tests, times too JTREG_BASIC_OPTIONS += -v:fail,error,time # Retain all files for failing tests JTREG_BASIC_OPTIONS += -retain:fail,error # Ignore tests are not run and completely silent about it -JTREG_BASIC_OPTIONS += -ignore:quiet -# Multiple by 2 the timeout numbers -JTREG_BASIC_OPTIONS += -timeoutFactor:2 +JTREG_IGNORE_OPTION = -ignore:quiet +JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION) +# Multiple by 4 the timeout numbers +JTREG_TIMEOUT_OPTION = -timeoutFactor:4 +JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION) # Boost the max memory for jtreg to avoid gc thrashing -JTREG_BASIC_OPTIONS += -J-Xmx512m +JTREG_MEMORY_OPTION = -J-Xmx512m +JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION) # Make sure jtreg exists $(JTREG): $(JT_HOME) diff -r 4b85cf247673 -r df0a816d95ef jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/ProblemList.txt Wed Jul 05 17:05:01 2017 +0200 @@ -431,6 +431,11 @@ # jdk_management +# Fails on Windows 2000, Test failed for iiop java.lang.NullPointerException +# at org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke(Unknown Source) +# at com.sun.corba.se.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:653) +javax/management/remote/mandatory/connection/ReconnectTest.java generic-all + # Solaris 10 sparc, NPE from org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke javax/management/remote/mandatory/threads/ExecutorTest.java generic-all @@ -494,10 +499,6 @@ # Problems with rounding add failures on solaris-sparcv9 and -server java/math/BigDecimal/AddTests.java solaris-sparcv9 -# Problems on windows with samevm, missing inputstream close()? -# Also times out on solaris-sparcv9 -server -java/math/BigInteger/BigIntegerTest.java generic-all - # Should be samevm? But seems problematic with samevm on windows java/math/BigInteger/ModPow65537.java generic-all @@ -581,6 +582,14 @@ # Suspect many of these tests auffer from using fixed ports, no concrete # evidence. +# Dies on Solaris 10 sparc and sparcv9, Linux -ea -esa with +# Interrupted or IO exception, maybe writing to non-unique named file? +com/sun/net/httpserver/bugs/B6373555.java generic-all + +# Dies on pretty much all platforms when run with -ea -esa, Assertion error +java/net/CookieHandler/TestHttpCookie.java generic-all +java/net/URLClassLoader/closetest/CloseTest.java generic-all + # Fails on OpenSolaris, BindException unexpected java/net/BindException/Test.java generic-all @@ -717,6 +726,9 @@ # Connection refused, windows samevm sun/net/www/protocol/http/DigestTest.java generic-all +# Fails on Fedora 9 32bit & 64bit & Solaris 10, wrong proxy for http://localhost/index.html +java/net/ProxySelector/B6737819.java generic-all + ############################################################################ # jdk_nio @@ -724,6 +736,33 @@ # Suspect many of these tests auffer from using fixed ports, no concrete # evidence. +# Fails with -ea -esa, Assertion error, but only on Solaris 10 machines? +com/sun/nio/sctp/SctpChannel/Send.java generic-all +com/sun/nio/sctp/SctpChannel/Shutdown.java generic-all + +# Fails on Windows 2000, Can't delete test directory .\x.SetLastModified.dir +# at SetLastModified.main(SetLastModified.java:107) +java/io/File/SetLastModified.java generic-all + +# Fails on Solaris 10 x64, address already in use +java/nio/channels/DatagramChannel/SRTest.java generic-all + +# Fails on Solaris 10 x86, times out +java/nio/channels/DatagramChannel/Sender.java generic-all + +# Fails on Fedora 9 x86, address in use +java/nio/channels/Selector/SelectWrite.java generic-all + +# Fails on Fedora 9 32bit times out +java/nio/channels/DatagramChannel/EmptyBuffer.java generic-all + +# Fails on Windows 2000, ExceptionInInitializerError +# in WindowsAsynchronousServerSocketChannelImpl.java:316 +java/nio/channels/AsynchronousChannelGroup/Unbounded.java generic-all + +# Fails on Windows 2000, times out +java/nio/channels/FileChannel/Transfer.java generic-all + # Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses # from a channel that is bound to the wildcard address com/sun/nio/sctp/SctpChannel/Bind.java generic-all @@ -893,6 +932,48 @@ # jdk_security +# Fails with -ea -esa, but only on Solaris sparc? Suspect it is timing out +sun/security/tools/keytool/standard.sh generic-all + +# Fails on Solaris 10 X64, address already in use +sun/security/krb5/auto/HttpNegotiateServer.java generic-all + +# Fails on almost all platforms +# java.lang.UnsupportedClassVersionError: SerialTest : +# Unsupported major.minor version 51.0 +# at java.lang.ClassLoader.defineClass1(Native Method) +sun/security/util/Oid/S11N.sh generic-all + +# Fails on Fedora 9 32bit +# GSSException: Failure unspecified at GSS-API level (Mechanism level: +# Invalid argument (400) - Cannot find key of appropriate type to decrypt +# AP REP - DES CBC mode with MD5) +# at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:778) +sun/security/krb5/auto/NonMutualSpnego.java generic-all + +# Fails on Solaris 10 sparc, GSSException: Failure unspecified at GSS-API level +# Also fails on Windows 2000 similar way +sun/security/krb5/auto/ok-as-delegate.sh generic-all + +# Fails on Windows 2000, GSSException: Failure unspecified at GSS-API level +# (Mechanism level: Request is a replay (34)) +sun/security/krb5/auto/ok-as-delegate-xrealm.sh generic-all + +# Fails on Windows 2000, ExceptionInInitializerError +sun/security/mscapi/AccessKeyStore.sh generic-all + +# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied +sun/security/pkcs11/KeyAgreement/TestDH.java generic-all + +# Fails on Windows 2000, UnsatisfiedLinkError: libnspr4.dll: Access is denied +sun/security/pkcs11/fips/ClientJSSEServerJSSE.java generic-all + +# Fails on Solaris 10, KrbException: Additional pre-authentication required (25) +sun/security/krb5/auto/basic.sh generic-all + +# Fails on Fedora 9 64bit, PKCS11Exception: CKR_DEVICE_ERROR +sun/security/pkcs11/KeyAgreement/TestDH.java generic-all + # Run too slow on Solaris 10 sparc sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java solaris-sparc sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java solaris-sparc @@ -1088,6 +1169,16 @@ # So most if not all tools tests are now being run with "othervm" mode. # Some of these tools tests have a tendency to use fixed ports, bad idea. +# Fails with -ea -esa on Solaris, Assertion error (Solaris specific test) +com/sun/tracing/BasicFunctionality.java generic-all + +# Fails on Fedora 9 32bit, jps output differs problem +sun/tools/jstatd/jstatdDefaults.sh generic-all + +# Fails on Linux Fedora 9 32bit, Could not read data for remote JVM 16133 +# jstat output differs from expected output +sun/tools/jstatd/jstatdExternalRegistry.sh generic-all + # Output of jps differs from expected output. # Invalid argument count on solaris-sparc and x64 sun/tools/jstatd/jstatdPort.sh generic-all @@ -1099,6 +1190,11 @@ sun/tools/jps/jps-Vvml_2.sh generic-all sun/tools/jps/jps-m_2.sh generic-all +# Fails on Solaris 10 sparcv9, shell exits with 1 +# Turning off use of shared archive because of choice of garbage collector or large pages +# Could not synchronize with target +sun/tools/jps/jps-v_1.sh generic-all + # Fails on OpenSolaris "Could not synchronize with target" sun/tools/jps/jps-Defaults.sh generic-all sun/tools/jps/jps-V_2.sh generic-all @@ -1160,6 +1256,12 @@ # jdk_util +# Fails with -ea -esa on all platforms with Assertion error +java/util/ResourceBundle/Test4300693.java generic-all + +# Failing on all -client 32bit platforms starting with b77? See 6908348. +java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all + # Assert error, failures, on Linux Fedora 9 -server # Windows samevm failure, assert error "Passed = 134, failed = 2" java/util/Arrays/ArrayObjectMethods.java generic-all diff -r 4b85cf247673 -r df0a816d95ef jdk/test/com/sun/jdi/NoLaunchOptionTest.java --- a/jdk/test/com/sun/jdi/NoLaunchOptionTest.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/com/sun/jdi/NoLaunchOptionTest.java Wed Jul 05 17:05:01 2017 +0200 @@ -31,6 +31,9 @@ * @build VMConnection * @run main/othervm NoLaunchOptionTest */ + +import java.net.ServerSocket; + public class NoLaunchOptionTest extends Object { private Process subprocess; private int subprocessStatus; @@ -121,12 +124,19 @@ } public static void main(String[] args) throws Exception { + // find a free port + ServerSocket ss = new ServerSocket(0); + int port = ss.getLocalPort(); + ss.close(); + String address = String.valueOf(port); + String javaExe = System.getProperty("java.home") + java.io.File.separator + "bin" + java.io.File.separator + "java"; String targetClass = "NotAClass"; String cmds [] = {javaExe, - "-agentlib:jdwp=transport=dt_socket,address=8000," + + "-agentlib:jdwp=transport=dt_socket,address=" + + address + "," + "onthrow=java.lang.ClassNotFoundException,suspend=n", targetClass}; NoLaunchOptionTest myTest = new NoLaunchOptionTest(); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/com/sun/jdi/OptionTest.java --- a/jdk/test/com/sun/jdi/OptionTest.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/com/sun/jdi/OptionTest.java Wed Jul 05 17:05:01 2017 +0200 @@ -32,6 +32,9 @@ * @run compile -g VMConnection.java * @run main/othervm OptionTest */ + +import java.net.ServerSocket; + public class OptionTest extends Object { private Process subprocess; private int subprocessStatus; @@ -122,12 +125,18 @@ } public static void main(String[] args) throws Exception { + // find a free port + ServerSocket ss = new ServerSocket(0); + int port = ss.getLocalPort(); + ss.close(); + String address = String.valueOf(port); + String javaExe = System.getProperty("java.home") + java.io.File.separator + "bin" + java.io.File.separator + "java"; String targetClass = "HelloWorld"; String baseOptions = "transport=dt_socket" + - ",address=8000" + + ",address=" + address + ",server=y" + ",suspend=n"; diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/dyn/MethodHandlesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/dyn/MethodHandlesTest.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,1839 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @summary unit tests for java.dyn.MethodHandles + * @compile -XDinvokedynamic MethodHandlesTest.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic jdk.java.dyn.MethodHandlesTest + */ + +package jdk.java.dyn; + +import java.dyn.*; +import java.dyn.MethodHandles.Lookup; +import java.lang.reflect.*; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.*; +import static org.junit.Assert.*; + + +/** + * + * @author jrose + */ +public class MethodHandlesTest { + // How much output? + static int verbosity = 1; + + // Set this true during development if you want to fast-forward to + // a particular new, non-working test. Tests which are known to + // work (or have recently worked) test this flag and return on true. + static boolean CAN_SKIP_WORKING = false; + //static { CAN_SKIP_WORKING = true; } + + // Set true to test more calls. If false, some tests are just + // lookups, without exercising the actual method handle. + static boolean DO_MORE_CALLS = false; + + + @Test + public void testFirst() throws Throwable { + verbosity += 9; try { + // left blank for debugging + } finally { verbosity -= 9; } + } + + // current failures + @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric") + public void testFail_1() throws Throwable { + testSpreadArguments(int.class, 0, 6); + } + @Test @Ignore("failure in JVM when expanding the stack") + public void testFail_2() throws Throwable { + // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes: + testSpreadArguments(Object.class, 0, 2); + } + @Test @Ignore("IllArgEx failure in call to ToGeneric.make") + public void testFail_3() throws Throwable { + testSpreadArguments(int.class, 1, 2); + } + @Test @Ignore("IllArgEx failure in call to ToGeneric.make") + public void testFail_4() throws Throwable { + testCollectArguments(int.class, 1, 2); + } + @Test @Ignore("cannot collect leading primitive types") + public void testFail_5() throws Throwable { + testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class)); + } + @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit") + public void testFail_6() throws Throwable { + testInsertArguments(0, 0, MAX_ARG_INCREASE+1); + } + static final int MAX_ARG_INCREASE = 3; + + public MethodHandlesTest() { + } + + String testName; + int posTests, negTests; + @After + public void printCounts() { + if (verbosity >= 1 && (posTests | negTests) != 0) { + System.out.println(); + if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run"); + if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run"); + } + } + void countTest(boolean positive) { + if (positive) ++posTests; + else ++negTests; + } + void countTest() { countTest(true); } + void startTest(String name) { + if (testName != null) printCounts(); + if (verbosity >= 0) + System.out.println(name); + posTests = negTests = 0; + testName = name; + } + + @BeforeClass + public static void setUpClass() throws Exception { + calledLog.clear(); + calledLog.add(null); + nextArg = 1000000; + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + static List calledLog = new ArrayList(); + static Object logEntry(String name, Object... args) { + return Arrays.asList(name, Arrays.asList(args)); + } + static Object called(String name, Object... args) { + Object entry = logEntry(name, args); + calledLog.add(entry); + return entry; + } + static void assertCalled(String name, Object... args) { + Object expected = logEntry(name, args); + Object actual = calledLog.get(calledLog.size() - 1); + if (expected.equals(actual)) return; + System.out.println("assertCalled "+name+":"); + System.out.println("expected: "+expected); + System.out.println("actual: "+actual); + System.out.println("ex. types: "+getClasses(expected)); + System.out.println("act. types: "+getClasses(actual)); + assertEquals("previous method call types", expected, actual); + assertEquals("previous method call", expected, actual); + } + static void printCalled(MethodHandle target, String name, Object... args) { + if (verbosity >= 2) + System.out.println("calling "+logEntry(name, args)+" on "+target); + } + + static Object castToWrapper(Object value, Class dst) { + Object wrap = null; + if (value instanceof Number) + wrap = castToWrapperOrNull(((Number)value).longValue(), dst); + if (value instanceof Character) + wrap = castToWrapperOrNull((char)(Character)value, dst); + if (wrap != null) return wrap; + return dst.cast(value); + } + + static Object castToWrapperOrNull(long value, Class dst) { + if (dst == int.class || dst == Integer.class) + return (int)(value); + if (dst == long.class || dst == Long.class) + return (long)(value); + if (dst == char.class || dst == Character.class) + return (char)(value); + if (dst == short.class || dst == Short.class) + return (short)(value); + if (dst == float.class || dst == Float.class) + return (float)(value); + if (dst == double.class || dst == Double.class) + return (double)(value); + if (dst == byte.class || dst == Byte.class) + return (byte)(value); + if (dst == boolean.class || dst == boolean.class) + return ((value % 29) & 1) == 0; + return null; + } + + static int nextArg; + static Object randomArg(Class param) { + Object wrap = castToWrapperOrNull(nextArg, param); + if (wrap != null) { + nextArg++; + return wrap; + } +// import sun.dyn.util.Wrapper; +// Wrapper wrap = Wrapper.forBasicType(dst); +// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst)) +// wrap = Wrapper.forWrapperType(dst); +// if (wrap != Wrapper.OBJECT) +// return wrap.wrap(nextArg++); + if (param.isInterface() || param.isAssignableFrom(String.class)) + return "#"+(nextArg++); + else + try { + return param.newInstance(); + } catch (InstantiationException ex) { + } catch (IllegalAccessException ex) { + } + return null; // random class not Object, String, Integer, etc. + } + static Object[] randomArgs(Class... params) { + Object[] args = new Object[params.length]; + for (int i = 0; i < args.length; i++) + args[i] = randomArg(params[i]); + return args; + } + static Object[] randomArgs(int nargs, Class param) { + Object[] args = new Object[nargs]; + for (int i = 0; i < args.length; i++) + args[i] = randomArg(param); + return args; + } + + static T[] array(Class atype, E... a) { + return Arrays.copyOf(a, a.length, atype); + } + static T[] cat(T[] a, T... b) { + int alen = a.length, blen = b.length; + if (blen == 0) return a; + T[] c = Arrays.copyOf(a, alen + blen); + System.arraycopy(b, 0, c, alen, blen); + return c; + } + static Integer[] boxAll(int... vx) { + Integer[] res = new Integer[vx.length]; + for (int i = 0; i < res.length; i++) { + res[i] = vx[i]; + } + return res; + } + static Object getClasses(Object x) { + if (x == null) return x; + if (x instanceof String) return x; // keep the name + if (x instanceof List) { + // recursively report classes of the list elements + Object[] xa = ((List)x).toArray(); + for (int i = 0; i < xa.length; i++) + xa[i] = getClasses(xa[i]); + return Arrays.asList(xa); + } + return x.getClass().getSimpleName(); + } + + static MethodHandle changeArgTypes(MethodHandle target, Class argType) { + return changeArgTypes(target, 0, 999, argType); + } + static MethodHandle changeArgTypes(MethodHandle target, + int beg, int end, Class argType) { + MethodType targetType = target.type(); + end = Math.min(end, targetType.parameterCount()); + ArrayList> argTypes = new ArrayList>(targetType.parameterList()); + Collections.fill(argTypes.subList(beg, end), argType); + MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); + return MethodHandles.convertArguments(target, ttype2); + } + + // This lookup is good for all members in and under MethodHandlesTest. + static final Lookup PRIVATE = MethodHandles.lookup(); + // This lookup is good for package-private members but not private ones. + static final Lookup PACKAGE = PackageSibling.lookup(); + // This lookup is good only for public members. + static final Lookup PUBLIC = MethodHandles.publicLookup(); + + // Subject methods... + static class Example implements IntExample { + final String name; + public Example() { name = "Example#"+(nextArg++); } + protected Example(String name) { this.name = name; } + protected Example(int x) { this(); called("protected ", this, x); } + @Override public String toString() { return name; } + + public void v0() { called("v0", this); } + void pkg_v0() { called("pkg_v0", this); } + private void pri_v0() { called("pri_v0", this); } + public static void s0() { called("s0"); } + static void pkg_s0() { called("pkg_s0"); } + private static void pri_s0() { called("pri_s0"); } + + public Object v1(Object x) { return called("v1", this, x); } + public Object v2(Object x, Object y) { return called("v2", this, x, y); } + public Object v2(Object x, int y) { return called("v2", this, x, y); } + public Object v2(int x, Object y) { return called("v2", this, x, y); } + public Object v2(int x, int y) { return called("v2", this, x, y); } + public static Object s1(Object x) { return called("s1", x); } + public static Object s2(int x) { return called("s2", x); } + public static Object s3(long x) { return called("s3", x); } + public static Object s4(int x, int y) { return called("s4", x, y); } + public static Object s5(long x, int y) { return called("s5", x, y); } + public static Object s6(int x, long y) { return called("s6", x, y); } + public static Object s7(float x, double y) { return called("s7", x, y); } + } + public static class PubExample extends Example { + } + static class SubExample extends Example { + @Override public void v0() { called("Sub/v0", this); } + @Override void pkg_v0() { called("Sub/pkg_v0", this); } + private SubExample(int x) { called("", this, x); } + public SubExample() { super("SubExample#"+(nextArg++)); } + } + public static interface IntExample { + public void v0(); + static class Impl implements IntExample { + public void v0() { called("Int/v0", this); } + final String name; + public Impl() { name = "Example#"+(nextArg++); } + } + } + + static final Object[][][] ACCESS_CASES = { + { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE } }, + { { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE } }, + { { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE } }, + { { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE } }, + }; + + static Object[][] accessCases(Class defc, String name) { + if (name.contains("pri_")) { + return ACCESS_CASES[1]; // PRIVATE only + } else if (name.contains("pkg_")) { + return ACCESS_CASES[2]; // not PUBLIC + } else { + assertTrue(name.indexOf('_') < 0); + boolean pubc = Modifier.isPublic(defc.getModifiers()); + if (pubc) + return ACCESS_CASES[3]; // all access levels + return ACCESS_CASES[2]; // PACKAGE but not PUBLIC + } + } + + @Test + public void testFindStatic() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findStatic"); + testFindStatic(PubExample.class, void.class, "s0"); + testFindStatic(Example.class, void.class, "s0"); + testFindStatic(Example.class, void.class, "pkg_s0"); + testFindStatic(Example.class, void.class, "pri_s0"); + + testFindStatic(Example.class, Object.class, "s1", Object.class); + testFindStatic(Example.class, Object.class, "s2", int.class); + testFindStatic(Example.class, Object.class, "s3", long.class); + testFindStatic(Example.class, Object.class, "s4", int.class, int.class); + testFindStatic(Example.class, Object.class, "s5", long.class, int.class); + testFindStatic(Example.class, Object.class, "s6", int.class, long.class); + testFindStatic(Example.class, Object.class, "s7", float.class, double.class); + + testFindStatic(false, PRIVATE, Example.class, void.class, "bogus"); + } + + void testFindStatic(Class defc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); + } + } + void testFindStatic(Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + testFindStatic(true, lookup, defc, ret, name, params); + } + void testFindStatic(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + MethodType type = MethodType.methodType(ret, params); + MethodHandle target = null; + RuntimeException noAccess = null; + try { + target = lookup.findStatic(defc, name, type); + } catch (NoAccessException ex) { + noAccess = ex; + } + if (verbosity >= 2) + System.out.println("findStatic "+lookup+": "+defc+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(type, target.type()); + assertTrue(target.toString().contains(name)); // rough check + if (!DO_MORE_CALLS && lookup != PRIVATE) return; + Object[] args = randomArgs(params); + printCalled(target, name, args); + target.invokeVarargs(args); + assertCalled(name, args); + System.out.print(':'); + } + + @Test + public void testFindVirtual() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findVirtual"); + testFindVirtual(Example.class, void.class, "v0"); + testFindVirtual(Example.class, void.class, "pkg_v0"); + testFindVirtual(Example.class, void.class, "pri_v0"); + testFindVirtual(Example.class, Object.class, "v1", Object.class); + testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class); + testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class); + testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class); + testFindVirtual(Example.class, Object.class, "v2", int.class, int.class); + testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus"); + // test dispatch + testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/v0"); + testFindVirtual(SubExample.class, Example.class, void.class, "Sub/v0"); + testFindVirtual(SubExample.class, IntExample.class, void.class, "Sub/v0"); + testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/pkg_v0"); + testFindVirtual(SubExample.class, Example.class, void.class, "Sub/pkg_v0"); + testFindVirtual(Example.class, IntExample.class, void.class, "v0"); + testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0"); + } + + void testFindVirtual(Class defc, Class ret, String name, Class... params) throws Throwable { + Class rcvc = defc; + testFindVirtual(rcvc, defc, ret, name, params); + } + void testFindVirtual(Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params); + } + } + void testFindVirtual(Lookup lookup, Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { + testFindVirtual(true, lookup, rcvc, defc, ret, name, params); + } + void testFindVirtual(boolean positive, Lookup lookup, Class rcvc, Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo + MethodType type = MethodType.methodType(ret, params); + MethodHandle target = null; + RuntimeException noAccess = null; + try { + target = lookup.findVirtual(defc, methodName, type); + } catch (NoAccessException ex) { + noAccess = ex; + } + if (verbosity >= 2) + System.out.println("findVirtual "+lookup+": "+defc+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + Class[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); + MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); + MethodType ttype = target.type(); + ttype = ttype.changeParameterType(0, defc); // FIXME: test this + assertEquals(typeWithSelf, ttype); + assertTrue(target.toString().contains(methodName)); // rough check + if (!DO_MORE_CALLS && lookup != PRIVATE) return; + Object[] argsWithSelf = randomArgs(paramsWithSelf); + if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); + printCalled(target, name, argsWithSelf); + target.invokeVarargs(argsWithSelf); + assertCalled(name, argsWithSelf); + System.out.print(':'); + } + + @Test + public void testFindSpecial() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("findSpecial"); + testFindSpecial(Example.class, void.class, "v0"); + testFindSpecial(Example.class, void.class, "pkg_v0"); + testFindSpecial(false, PRIVATE, Example.class, void.class, "", int.class); + testFindSpecial(false, PRIVATE, Example.class, void.class, "bogus"); + } + + void testFindSpecial(Class defc, Class ret, String name, Class... params) throws Throwable { + testFindSpecial(true, PRIVATE, defc, ret, name, params); + testFindSpecial(false, PACKAGE, defc, ret, name, params); + testFindSpecial(false, PUBLIC, defc, ret, name, params); + } + void testFindSpecial(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + MethodType type = MethodType.methodType(ret, params); + MethodHandle target = null; + RuntimeException noAccess = null; + try { + target = lookup.findSpecial(defc, name, type, defc); + } catch (NoAccessException ex) { + noAccess = ex; + } + if (verbosity >= 2) + System.out.println("findSpecial "+defc+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + Class[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); + MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); + MethodType ttype = target.type(); + ttype = ttype.changeParameterType(0, defc); // FIXME: test this + assertEquals(typeWithSelf, ttype); + assertTrue(target.toString().contains(name)); // rough check + if (!DO_MORE_CALLS && lookup != PRIVATE) return; + Object[] args = randomArgs(paramsWithSelf); + printCalled(target, name, args); + target.invokeVarargs(args); + assertCalled(name, args); + System.out.print(':'); + } + + @Test + public void testBind() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("bind"); + testBind(Example.class, void.class, "v0"); + testBind(Example.class, void.class, "pkg_v0"); + testBind(Example.class, void.class, "pri_v0"); + testBind(Example.class, Object.class, "v1", Object.class); + testBind(Example.class, Object.class, "v2", Object.class, Object.class); + testBind(Example.class, Object.class, "v2", Object.class, int.class); + testBind(Example.class, Object.class, "v2", int.class, Object.class); + testBind(Example.class, Object.class, "v2", int.class, int.class); + testBind(false, PRIVATE, Example.class, void.class, "bogus"); + testBind(SubExample.class, void.class, "Sub/v0"); + testBind(SubExample.class, void.class, "Sub/pkg_v0"); + testBind(IntExample.Impl.class, void.class, "Int/v0"); + } + + void testBind(Class defc, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params); + } + } + + void testBind(boolean positive, Lookup lookup, Class defc, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo + MethodType type = MethodType.methodType(ret, params); + Object receiver = randomArg(defc); + MethodHandle target = null; + RuntimeException noAccess = null; + try { + target = lookup.bind(receiver, methodName, type); + } catch (NoAccessException ex) { + noAccess = ex; + } + if (verbosity >= 2) + System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(type, target.type()); + Object[] args = randomArgs(params); + printCalled(target, name, args); + target.invokeVarargs(args); + Object[] argsWithReceiver = cat(array(Object[].class, receiver), args); + assertCalled(name, argsWithReceiver); + System.out.print(':'); + } + + @Test + public void testUnreflect() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("unreflect"); + testUnreflect(Example.class, true, void.class, "s0"); + testUnreflect(Example.class, true, void.class, "pkg_s0"); + testUnreflect(Example.class, true, void.class, "pri_s0"); + + testUnreflect(Example.class, true, Object.class, "s1", Object.class); + testUnreflect(Example.class, true, Object.class, "s2", int.class); + //testUnreflect(Example.class, true, Object.class, "s3", long.class); + //testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class); + //testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class); + //testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class); + + testUnreflect(Example.class, false, void.class, "v0"); + testUnreflect(Example.class, false, void.class, "pkg_v0"); + testUnreflect(Example.class, false, void.class, "pri_v0"); + testUnreflect(Example.class, false, Object.class, "v1", Object.class); + testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class); + testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class); + testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class); + testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class); + } + + void testUnreflect(Class defc, boolean isStatic, Class ret, String name, Class... params) throws Throwable { + for (Object[] ac : accessCases(defc, name)) { + testUnreflect((Boolean)ac[0], (Lookup)ac[1], defc, isStatic, ret, name, params); + } + } + void testUnreflect(boolean positive, Lookup lookup, Class defc, boolean isStatic, Class ret, String name, Class... params) throws Throwable { + countTest(positive); + MethodType type = MethodType.methodType(ret, params); + Method rmethod = null; + MethodHandle target = null; + RuntimeException noAccess = null; + try { + rmethod = defc.getDeclaredMethod(name, params); + } catch (NoSuchMethodException ex) { + throw new NoAccessException(ex); + } + assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers())); + try { + target = lookup.unreflect(rmethod); + } catch (NoAccessException ex) { + noAccess = ex; + } + if (verbosity >= 2) + System.out.println("unreflect "+defc+"."+name+"/"+type+" => "+target + +(noAccess == null ? "" : " !! "+noAccess)); + if (positive && noAccess != null) throw noAccess; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + Class[] paramsMaybeWithSelf = params; + if (!isStatic) { + paramsMaybeWithSelf = cat(array(Class[].class, (Class)defc), params); + } + MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf); + MethodType ttype = target.type(); + if (!isStatic) + ttype = ttype.changeParameterType(0, defc); // FIXME: test this + assertEquals(typeMaybeWithSelf, ttype); + Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf); + printCalled(target, name, argsMaybeWithSelf); + target.invokeVarargs(argsMaybeWithSelf); + assertCalled(name, argsMaybeWithSelf); + System.out.print(':'); + } + + @Test @Ignore("unimplemented") + public void testUnreflectSpecial() throws Throwable { + Lookup lookup = PRIVATE; // FIXME: test more lookups than this one + startTest("unreflectSpecial"); + Method m = null; + MethodHandle expResult = null; + MethodHandle result = lookup.unreflectSpecial(m, Example.class); + assertEquals(expResult, result); + fail("The test case is a prototype."); + } + + public static class HasFields { + boolean fZ = false; + byte fB = (byte)'B'; + short fS = (short)'S'; + char fC = 'C'; + int fI = 'I'; + long fJ = 'J'; + float fF = 'F'; + double fD = 'D'; + static boolean sZ = true; + static byte sB = 1+(byte)'B'; + static short sS = 1+(short)'S'; + static char sC = 1+'C'; + static int sI = 1+'I'; + static long sJ = 1+'J'; + static float sF = 1+'F'; + static double sD = 1+'D'; + + Object fL = 'L'; + String fR = "R"; + static Object sL = 'M'; + static String sR = "S"; + + static final Object[][] CASES; + static { + ArrayList cases = new ArrayList(); + Object types[][] = { + {'L',Object.class}, {'R',String.class}, + {'I',int.class}, {'J',long.class}, + {'F',float.class}, {'D',double.class}, + {'Z',boolean.class}, {'B',byte.class}, + {'S',short.class}, {'C',char.class}, + }; + HasFields fields = new HasFields(); + for (Object[] t : types) { + for (int kind = 0; kind <= 1; kind++) { + boolean isStatic = (kind != 0); + char btc = (Character)t[0]; + String name = (isStatic ? "s" : "f") + btc; + Class type = (Class) t[1]; + Object value; + Field field; + try { + field = HasFields.class.getDeclaredField(name); + } catch (Exception ex) { + throw new InternalError("no field HasFields."+name); + } + try { + value = field.get(fields); + } catch (Exception ex) { + throw new InternalError("cannot fetch field HasFields."+name); + } + if (type == float.class) { + float v = 'F'; + if (isStatic) v++; + assert(value.equals(v)); + } + assert(name.equals(field.getName())); + assert(type.equals(field.getType())); + assert(isStatic == (Modifier.isStatic(field.getModifiers()))); + cases.add(new Object[]{ field, value }); + } + } + CASES = cases.toArray(new Object[0][]); + } + } + + @Test + public void testUnreflectGetter() throws Throwable { + Lookup lookup = PRIVATE; // FIXME: test more lookups than this one + startTest("unreflectGetter"); + for (Object[] c : HasFields.CASES) { + Field f = (Field)c[0]; + Object value = c[1]; + Class type = f.getType(); + if (type.isPrimitive() && type != int.class) + continue; //FIXME + testUnreflectGetter(lookup, f, type, value); + } + } + public void testUnreflectGetter(MethodHandles.Lookup lookup, + Field f, Class type, Object value) throws Throwable { + countTest(true); + boolean isStatic = Modifier.isStatic(f.getModifiers()); + MethodType expType = MethodType.methodType(type, HasFields.class); + if (isStatic) expType = expType.dropParameterTypes(0, 1); + MethodHandle mh = lookup.unreflectGetter(f); + assertSame(mh.type(), expType); + assertEquals(mh.toString(), f.getName()); + HasFields fields = new HasFields(); + Object sawValue; + Class rtype = type; + if (type != int.class) rtype = Object.class; + mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(rtype)); + Object expValue = value; + for (int i = 0; i <= 1; i++) { + if (isStatic) { + if (type == int.class) + sawValue = mh.invoke(); // do these exactly + else + sawValue = mh.invoke(); + } else { + if (type == int.class) + sawValue = mh.invoke((Object) fields); + else + sawValue = mh.invoke((Object) fields); + } + assertEquals(sawValue, expValue); + Object random = randomArg(type); + f.set(fields, random); + expValue = random; + } + f.set(fields, value); // put it back + } + + + @Test + public void testUnreflectSetter() throws Throwable { + Lookup lookup = PRIVATE; // FIXME: test more lookups than this one + startTest("unreflectSetter"); + for (Object[] c : HasFields.CASES) { + Field f = (Field)c[0]; + Object value = c[1]; + Class type = f.getType(); + if (type.isPrimitive() && type != int.class) + continue; //FIXME + testUnreflectSetter(lookup, f, type, value); + } + } + public void testUnreflectSetter(MethodHandles.Lookup lookup, + Field f, Class type, Object value) throws Throwable { + countTest(true); + boolean isStatic = Modifier.isStatic(f.getModifiers()); + MethodType expType = MethodType.methodType(void.class, HasFields.class, type); + if (isStatic) expType = expType.dropParameterTypes(0, 1); + MethodHandle mh = lookup.unreflectSetter(f); + assertSame(mh.type(), expType); + assertEquals(mh.toString(), f.getName()); + HasFields fields = new HasFields(); + Object sawValue; + Class vtype = type; + if (type != int.class) vtype = Object.class; + int last = mh.type().parameterCount() - 1; + mh = MethodHandles.convertArguments(mh, mh.type().generic().changeReturnType(void.class).changeParameterType(last, vtype)); + assertEquals(f.get(fields), value); // clean to start with + for (int i = 0; i <= 1; i++) { + Object putValue = randomArg(type); + if (isStatic) { + if (type == int.class) + mh.invoke((int)(Integer)putValue); // do these exactly + else + mh.invoke(putValue); + } else { + if (type == int.class) + mh.invoke((Object) fields, (int)(Integer)putValue); + else + mh.invoke((Object) fields, putValue); + } + assertEquals(f.get(fields), putValue); + } + f.set(fields, value); // put it back + } + + @Test + public void testArrayElementGetter() throws Throwable { + startTest("arrayElementGetter"); + testArrayElementGetterSetter(new Object[10], false); + testArrayElementGetterSetter(new String[10], false); + testArrayElementGetterSetter(new int[10], false); + // FIXME: Do the other primitive types. + //testArrayElementGetterSetter(new float[10], false); + } + + @Test + public void testArrayElementSetter() throws Throwable { + startTest("arrayElementSetter"); + testArrayElementGetterSetter(new Object[10], true); + testArrayElementGetterSetter(new String[10], true); + testArrayElementGetterSetter(new int[10], true); + // FIXME: Do the other primitive types. + //testArrayElementGetterSetter(new float[10], true); + } + + public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { + countTest(true); + Class arrayType = array.getClass(); + Class elemType = arrayType.getComponentType(); + MethodType expType = !testSetter + ? MethodType.methodType(elemType, arrayType, int.class) + : MethodType.methodType(void.class, arrayType, int.class, elemType); + MethodHandle mh = !testSetter + ? MethodHandles.arrayElementGetter(arrayType) + : MethodHandles.arrayElementSetter(arrayType); + assertSame(mh.type(), expType); + //assertEquals(mh.toString(), f.getName()); + Object sawValue, expValue; + List model = array2list(array); + int length = Array.getLength(array); + for (int i = 0; i < length; i++) { + // update array element + Object random = randomArg(elemType); + model.set(i, random); + if (testSetter) { + if (elemType == int.class) + mh.invoke((int[]) array, i, (int)(Integer)random); + else + mh.invokeGeneric(array, i, random); + assertEquals(model, array2list(array)); + } else { + Array.set(array, i, random); + + } + // observe array element + sawValue = Array.get(array, i); + if (!testSetter) { + expValue = sawValue; + if (elemType == int.class) + sawValue = mh.invoke((int[]) array, i); + else + sawValue = mh.invokeGeneric(array, i); + assertEquals(sawValue, expValue); + assertEquals(model, array2list(array)); + } + } + } + + List array2list(Object array) { + int length = Array.getLength(array); + ArrayList model = new ArrayList(length); + for (int i = 0; i < length; i++) + model.add(Array.get(array, i)); + return model; + } + + static class Callee { + static Object id() { return called("id"); } + static Object id(Object x) { return called("id", x); } + static Object id(Object x, Object y) { return called("id", x, y); } + static Object id(Object x, Object y, Object z) { return called("id", x, y, z); } + static Object id(Object... vx) { return called("id", vx); } + static MethodHandle ofType(int n) { + return ofType(Object.class, n); + } + static MethodHandle ofType(Class rtype, int n) { + if (n == -1) + return ofType(MethodType.methodType(rtype, Object[].class)); + return ofType(MethodType.genericMethodType(n).changeReturnType(rtype)); + } + static MethodHandle ofType(Class rtype, Class... ptypes) { + return ofType(MethodType.methodType(rtype, ptypes)); + } + static MethodHandle ofType(MethodType type) { + Class rtype = type.returnType(); + String pfx = ""; + if (rtype != Object.class) + pfx = rtype.getSimpleName().substring(0, 1).toLowerCase(); + String name = pfx+"id"; + return PRIVATE.findStatic(Callee.class, name, type); + } + } + + @Test + public void testConvertArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("convertArguments"); + testConvert(Callee.ofType(1), null, "id", int.class); + testConvert(Callee.ofType(1), null, "id", String.class); + testConvert(Callee.ofType(1), null, "id", Integer.class); + testConvert(Callee.ofType(1), null, "id", short.class); + } + + void testConvert(MethodHandle id, Class rtype, String name, Class... params) throws Throwable { + testConvert(true, id, rtype, name, params); + } + + void testConvert(boolean positive, MethodHandle id, Class rtype, String name, Class... params) throws Throwable { + countTest(positive); + MethodType idType = id.type(); + if (rtype == null) rtype = idType.returnType(); + for (int i = 0; i < params.length; i++) { + if (params[i] == null) params[i] = idType.parameterType(i); + } + // simulate the pairwise conversion + MethodType newType = MethodType.methodType(rtype, params); + Object[] args = randomArgs(newType.parameterArray()); + Object[] convArgs = args.clone(); + for (int i = 0; i < args.length; i++) { + Class src = newType.parameterType(i); + Class dst = idType.parameterType(i); + if (src != dst) + convArgs[i] = castToWrapper(convArgs[i], dst); + } + Object convResult = id.invokeVarargs(convArgs); + { + Class dst = newType.returnType(); + Class src = idType.returnType(); + if (src != dst) + convResult = castToWrapper(convResult, dst); + } + MethodHandle target = null; + RuntimeException error = null; + try { + target = MethodHandles.convertArguments(id, newType); + } catch (RuntimeException ex) { + error = ex; + } + if (verbosity >= 2) + System.out.println("convert "+id+ " to "+newType+" => "+target + +(error == null ? "" : " !! "+error)); + if (positive && error != null) throw error; + assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null); + if (!positive) return; // negative test failed as expected + assertEquals(newType, target.type()); + printCalled(target, id.toString(), args); + Object result = target.invokeVarargs(args); + assertCalled(name, convArgs); + assertEquals(convResult, result); + System.out.print(':'); + } + + @Test + public void testPermuteArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("permuteArguments"); + testPermuteArguments(4, Integer.class, 2, String.class, 0); + //testPermuteArguments(6, Integer.class, 0, null, 30); + //testPermuteArguments(4, Integer.class, 1, int.class, 6); + } + public void testPermuteArguments(int max, Class type1, int t2c, Class type2, int dilution) throws Throwable { + if (verbosity >= 1) + System.out.println("permuteArguments "+max+"*"+type1.getName() + +(t2c==0?"":"/"+t2c+"*"+type2.getName()) + +(dilution > 0 ? " with dilution "+dilution : "")); + int t2pos = t2c == 0 ? 0 : 1; + for (int inargs = t2pos+1; inargs <= max; inargs++) { + Class[] types = new Class[inargs]; + Arrays.fill(types, type1); + if (t2c != 0) { + // Fill in a middle range with type2: + Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2); + } + Object[] args = randomArgs(types); + int numcases = 1; + for (int outargs = 0; outargs <= max; outargs++) { + if (outargs - inargs >= MAX_ARG_INCREASE) continue; + int[] reorder = new int[outargs]; + int casStep = dilution + 1; + // Avoid some common factors: + while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) || + (casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0)) + casStep++; + for (int cas = 0; cas < numcases; cas += casStep) { + for (int i = 0, c = cas; i < outargs; i++) { + reorder[i] = c % inargs; + c /= inargs; + } + testPermuteArguments(args, types, reorder); + } + numcases *= inargs; + if (dilution > 10 && outargs >= 4) { + // Do some special patterns, which we probably missed. + // Replication of a single argument or argument pair. + for (int i = 0; i < inargs; i++) { + Arrays.fill(reorder, i); + testPermuteArguments(args, types, reorder); + for (int d = 1; d <= 2; d++) { + if (i + d >= inargs) continue; + for (int j = 1; j < outargs; j += 2) + reorder[j] += 1; + testPermuteArguments(args, types, reorder); + testPermuteArguments(args, types, reverse(reorder)); + } + } + // Repetition of a sequence of 3 or more arguments. + for (int i = 1; i < inargs; i++) { + for (int len = 3; len <= inargs; len++) { + for (int j = 0; j < outargs; j++) + reorder[j] = (i + (j % len)) % inargs; + testPermuteArguments(args, types, reorder); + testPermuteArguments(args, types, reverse(reorder)); + } + } + } + } + } + } + + static int[] reverse(int[] reorder) { + reorder = reorder.clone(); + for (int i = 0, imax = reorder.length / 2; i < imax; i++) { + int j = reorder.length - 1 - i; + int tem = reorder[i]; + reorder[i] = reorder[j]; + reorder[j] = tem; + } + return reorder; + } + + void testPermuteArguments(Object[] args, Class[] types, int[] reorder) throws Throwable { + countTest(); + if (args == null && types == null) { + int max = 0; + for (int j : reorder) { + if (max < j) max = j; + } + args = randomArgs(max+1, Integer.class); + } + if (args == null) { + args = randomArgs(types); + } + if (types == null) { + types = new Class[args.length]; + for (int i = 0; i < args.length; i++) + types[i] = args[i].getClass(); + } + int inargs = args.length, outargs = reorder.length; + assert(inargs == types.length); + if (verbosity >= 2) + System.out.println("permuteArguments "+Arrays.toString(reorder)); + Object[] permArgs = new Object[outargs]; + Class[] permTypes = new Class[outargs]; + for (int i = 0; i < outargs; i++) { + permArgs[i] = args[reorder[i]]; + permTypes[i] = types[reorder[i]]; + } + if (verbosity >= 3) { + System.out.println("in args: "+Arrays.asList(args)); + System.out.println("out args: "+Arrays.asList(permArgs)); + System.out.println("in types: "+Arrays.asList(types)); + System.out.println("out types: "+Arrays.asList(permTypes)); + } + MethodType inType = MethodType.methodType(Object.class, types); + MethodType outType = MethodType.methodType(Object.class, permTypes); + MethodHandle target = MethodHandles.convertArguments(ValueConversions.varargsList(outargs), outType); + MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder); + Object result = newTarget.invokeVarargs(args); + Object expected = Arrays.asList(permArgs); + assertEquals(expected, result); + } + + + @Test + public void testSpreadArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("spreadArguments"); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + if (verbosity >= 2) + System.out.println("spreadArguments "+argType); + for (int nargs = 0; nargs < 10; nargs++) { + if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 + for (int pos = 0; pos < nargs; pos++) { + if (argType == int.class && pos > 0) continue; // FIXME Fail_3 + testSpreadArguments(argType, pos, nargs); + } + } + } + } + public void testSpreadArguments(Class argType, int pos, int nargs) throws Throwable { + countTest(); + MethodHandle target = ValueConversions.varargsArray(nargs); + MethodHandle target2 = changeArgTypes(target, argType); + if (verbosity >= 2) + System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]"); + Object[] args = randomArgs(target2.type().parameterArray()); + // make sure the target does what we think it does: + if (pos == 0 && nargs < 5) { + Object[] check = (Object[]) target.invokeVarargs(args); + assertArrayEquals(args, check); + switch (nargs) { + case 0: + check = target.invoke(); + assertArrayEquals(args, check); + break; + case 1: + check = target.invoke(args[0]); + assertArrayEquals(args, check); + break; + case 2: + check = target.invoke(args[0], args[1]); + assertArrayEquals(args, check); + break; + } + } + List> newParams = new ArrayList>(target2.type().parameterList()); + { // modify newParams in place + List> spreadParams = newParams.subList(pos, nargs); + spreadParams.clear(); spreadParams.add(Object[].class); + } + MethodType newType = MethodType.methodType(Object.class, newParams); + MethodHandle result = MethodHandles.spreadArguments(target2, newType); + Object[] returnValue; + if (pos == 0) { + returnValue = (Object[]) result.invoke(args); + } else { + Object[] args1 = Arrays.copyOfRange(args, 0, pos+1); + args1[pos] = Arrays.copyOfRange(args, pos, args.length); + returnValue = (Object[]) result.invokeVarargs(args1); + } + assertArrayEquals(args, returnValue); + } + + @Test + public void testCollectArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("collectArguments"); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + if (verbosity >= 2) + System.out.println("collectArguments "+argType); + for (int nargs = 0; nargs < 10; nargs++) { + for (int pos = 0; pos < nargs; pos++) { + if (argType == int.class) continue; // FIXME Fail_4 + testCollectArguments(argType, pos, nargs); + } + } + } + } + public void testCollectArguments(Class argType, int pos, int nargs) throws Throwable { + countTest(); + // fake up a MH with the same type as the desired adapter: + MethodHandle fake = ValueConversions.varargsArray(nargs); + fake = changeArgTypes(fake, argType); + MethodType newType = fake.type(); + Object[] args = randomArgs(newType.parameterArray()); + // here is what should happen: + Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1); + collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length); + // here is the MH which will witness the collected argument tail: + MethodHandle target = ValueConversions.varargsArray(pos+1); + target = changeArgTypes(target, 0, pos, argType); + target = changeArgTypes(target, pos, pos+1, Object[].class); + if (verbosity >= 2) + System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]"); + MethodHandle result = MethodHandles.collectArguments(target, newType); + Object[] returnValue = (Object[]) result.invokeVarargs(args); +// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]); +// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]); +// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]); + assertArrayEquals(collectedArgs, returnValue); + } + + @Test + public void testInsertArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("insertArguments"); + for (int nargs = 0; nargs <= 4; nargs++) { + for (int ins = 0; ins <= 4; ins++) { + if (ins > MAX_ARG_INCREASE) continue; // FIXME Fail_6 + for (int pos = 0; pos <= nargs; pos++) { + testInsertArguments(nargs, pos, ins); + } + } + } + } + + void testInsertArguments(int nargs, int pos, int ins) throws Throwable { + countTest(); + MethodHandle target = ValueConversions.varargsArray(nargs + ins); + Object[] args = randomArgs(target.type().parameterArray()); + List resList = Arrays.asList(args); + List argsToPass = new ArrayList(resList); + List argsToInsert = argsToPass.subList(pos, pos + ins); + if (verbosity >= 2) + System.out.println("insert: "+argsToInsert+" into "+target); + MethodHandle target2 = MethodHandles.insertArguments(target, pos, + (Object[]) argsToInsert.toArray()); + argsToInsert.clear(); // remove from argsToInsert + Object res2 = target2.invokeVarargs(argsToPass); + Object res2List = Arrays.asList((Object[])res2); + if (verbosity >= 2) + System.out.println("result: "+res2List); + //if (!resList.equals(res2List)) + // System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List); + assertEquals(resList, res2List); + } + + @Test + public void testFilterArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("filterArguments"); + for (int nargs = 1; nargs <= 6; nargs++) { + for (int pos = 0; pos < nargs; pos++) { + testFilterArguments(nargs, pos); + } + } + } + + void testFilterArguments(int nargs, int pos) throws Throwable { + countTest(); + MethodHandle target = ValueConversions.varargsList(nargs); + MethodHandle filter = ValueConversions.varargsList(1); + filter = MethodHandles.convertArguments(filter, filter.type().generic()); + Object[] argsToPass = randomArgs(nargs, Object.class); + if (verbosity >= 2) + System.out.println("filter "+target+" at "+pos+" with "+filter); + MethodHandle[] filters = new MethodHandle[pos*2+1]; + filters[pos] = filter; + MethodHandle target2 = MethodHandles.filterArguments(target, filters); + // Simulate expected effect of filter on arglist: + Object[] filteredArgs = argsToPass.clone(); + filteredArgs[pos] = filter.invoke(filteredArgs[pos]); + List expected = Arrays.asList(filteredArgs); + Object result = target2.invokeVarargs(argsToPass); + if (verbosity >= 2) + System.out.println("result: "+result); + if (!expected.equals(result)) + System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+argsToPass+" => "+result); + assertEquals(expected, result); + } + + @Test + public void testFoldArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("foldArguments"); + for (int nargs = 0; nargs <= 4; nargs++) { + for (int fold = 0; fold <= nargs; fold++) { + for (int pos = 0; pos <= nargs; pos++) { + testFoldArguments(nargs, pos, fold); + } + } + } + } + + void testFoldArguments(int nargs, int pos, int fold) throws Throwable { + if (pos != 0) return; // can fold only at pos=0 for now + countTest(); + MethodHandle target = ValueConversions.varargsList(1 + nargs); + MethodHandle combine = ValueConversions.varargsList(fold); + List argsToPass = Arrays.asList(randomArgs(nargs, Object.class)); + if (verbosity >= 2) + System.out.println("fold "+target+" with "+combine); + MethodHandle target2 = MethodHandles.foldArguments(target, combine); + // Simulate expected effect of combiner on arglist: + List expected = new ArrayList(argsToPass); + List argsToFold = expected.subList(pos, pos + fold); + if (verbosity >= 2) + System.out.println("fold: "+argsToFold+" into "+target2); + Object foldedArgs = combine.invokeVarargs(argsToFold); + argsToFold.add(0, foldedArgs); + Object result = target2.invokeVarargs(argsToPass); + if (verbosity >= 2) + System.out.println("result: "+result); + if (!expected.equals(result)) + System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result); + assertEquals(expected, result); + } + + @Test + public void testDropArguments() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("dropArguments"); + for (int nargs = 0; nargs <= 4; nargs++) { + for (int drop = 1; drop <= 4; drop++) { + for (int pos = 0; pos <= nargs; pos++) { + testDropArguments(nargs, pos, drop); + } + } + } + } + + void testDropArguments(int nargs, int pos, int drop) throws Throwable { + countTest(); + MethodHandle target = ValueConversions.varargsArray(nargs); + Object[] args = randomArgs(target.type().parameterArray()); + MethodHandle target2 = MethodHandles.dropArguments(target, pos, + Collections.nCopies(drop, Object.class).toArray(new Class[0])); + List resList = Arrays.asList(args); + List argsToDrop = new ArrayList(resList); + for (int i = drop; i > 0; i--) { + argsToDrop.add(pos, "blort#"+i); + } + Object res2 = target2.invokeVarargs(argsToDrop); + Object res2List = Arrays.asList((Object[])res2); + //if (!resList.equals(res2List)) + // System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List); + assertEquals(resList, res2List); + } + + @Test + public void testInvokers() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker"); + // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker + Set done = new HashSet(); + for (int i = 0; i <= 6; i++) { + MethodType gtype = MethodType.genericMethodType(i); + for (Class argType : new Class[]{Object.class, Integer.class, int.class}) { + for (int j = -1; j < i; j++) { + MethodType type = gtype; + if (j < 0) + type = type.changeReturnType(argType); + else if (argType == void.class) + continue; + else + type = type.changeParameterType(j, argType); + if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5 + if (done.add(type)) + testInvokers(type); + MethodType vtype = type.changeReturnType(void.class); + if (done.add(vtype)) + testInvokers(vtype); + } + } + } + } + + public void testInvokers(MethodType type) throws Throwable { + if (verbosity >= 2) + System.out.println("test invokers for "+type); + int nargs = type.parameterCount(); + boolean testRetCode = type.returnType() != void.class; + MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee", + MethodType.genericMethodType(0, true)); + target = MethodHandles.collectArguments(target, type); + Object[] args = randomArgs(type.parameterArray()); + List targetPlusArgs = new ArrayList(Arrays.asList(args)); + targetPlusArgs.add(0, target); + int code = (Integer) invokee(args); + Object log = logEntry("invokee", args); + assertEquals(log.hashCode(), code); + assertCalled("invokee", args); + MethodHandle inv; + Object result; + // exact invoker + countTest(); + calledLog.clear(); + inv = MethodHandles.exactInvoker(type); + result = inv.invokeVarargs(targetPlusArgs); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + // generic invoker + countTest(); + inv = MethodHandles.genericInvoker(type); + if (nargs <= 3) { + calledLog.clear(); + switch (nargs) { + case 0: + result = inv.invoke(target); + break; + case 1: + result = inv.invoke(target, args[0]); + break; + case 2: + result = inv.invoke(target, args[0], args[1]); + break; + case 3: + result = inv.invoke(target, args[0], args[1], args[2]); + break; + } + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + calledLog.clear(); + result = inv.invokeVarargs(targetPlusArgs); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + // varargs invoker #0 + calledLog.clear(); + inv = MethodHandles.varargsInvoker(type, 0); + result = inv.invoke(target, args); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + if (nargs >= 1) { + // varargs invoker #1 + calledLog.clear(); + inv = MethodHandles.varargsInvoker(type, 1); + result = inv.invoke(target, args[0], Arrays.copyOfRange(args, 1, nargs)); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + if (nargs >= 2) { + // varargs invoker #2 + calledLog.clear(); + inv = MethodHandles.varargsInvoker(type, 2); + result = inv.invoke(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs)); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + if (nargs >= 3) { + // varargs invoker #3 + calledLog.clear(); + inv = MethodHandles.varargsInvoker(type, 3); + result = inv.invoke(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs)); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + for (int k = 0; k <= nargs; k++) { + // varargs invoker #0..N + countTest(); + calledLog.clear(); + inv = MethodHandles.varargsInvoker(type, k); + List targetPlusVarArgs = new ArrayList(targetPlusArgs); + List tailList = targetPlusVarArgs.subList(1+k, 1+nargs); + Object[] tail = tailList.toArray(); + tailList.clear(); tailList.add(tail); + result = inv.invokeVarargs(targetPlusVarArgs); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + // dynamic invoker + countTest(); + CallSite site = new CallSite(MethodHandlesTest.class, "foo", type); + inv = MethodHandles.dynamicInvoker(site); + site.setTarget(target); + calledLog.clear(); + result = inv.invokeVarargs(args); + if (testRetCode) assertEquals(code, result); + assertCalled("invokee", args); + } + + static Object invokee(Object... args) { + return called("invokee", args).hashCode(); + } + + private static final String MISSING_ARG = "missingArg"; + static Object targetIfEquals() { + return called("targetIfEquals"); + } + static Object fallbackIfNotEquals() { + return called("fallbackIfNotEquals"); + } + static Object targetIfEquals(Object x) { + assertEquals(x, MISSING_ARG); + return called("targetIfEquals", x); + } + static Object fallbackIfNotEquals(Object x) { + assertFalse(x.toString(), x.equals(MISSING_ARG)); + return called("fallbackIfNotEquals", x); + } + static Object targetIfEquals(Object x, Object y) { + assertEquals(x, y); + return called("targetIfEquals", x, y); + } + static Object fallbackIfNotEquals(Object x, Object y) { + assertFalse(x.toString(), x.equals(y)); + return called("fallbackIfNotEquals", x, y); + } + static Object targetIfEquals(Object x, Object y, Object z) { + assertEquals(x, y); + return called("targetIfEquals", x, y, z); + } + static Object fallbackIfNotEquals(Object x, Object y, Object z) { + assertFalse(x.toString(), x.equals(y)); + return called("fallbackIfNotEquals", x, y, z); + } + + @Test + public void testGuardWithTest() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("guardWithTest"); + for (int nargs = 0; nargs <= 3; nargs++) { + if (nargs != 2) continue; // FIXME: test more later + testGuardWithTest(nargs, Object.class); + testGuardWithTest(nargs, String.class); + } + } + void testGuardWithTest(int nargs, Class argClass) throws Throwable { + countTest(); + MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class)); + MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs)); + MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs)); + while (test.type().parameterCount() < nargs) + test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class); + while (test.type().parameterCount() > nargs) + test = MethodHandles.insertArguments(test, 0, MISSING_ARG); + if (argClass != Object.class) { + test = changeArgTypes(test, argClass); + target = changeArgTypes(target, argClass); + fallback = changeArgTypes(fallback, argClass); + } + MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback); + assertEquals(target.type(), mh.type()); + Object[][] argLists = { + { }, + { "foo" }, { MISSING_ARG }, + { "foo", "foo" }, { "foo", "bar" }, + { "foo", "foo", "baz" }, { "foo", "bar", "baz" } + }; + for (Object[] argList : argLists) { + if (argList.length != nargs) continue; + boolean equals; + switch (nargs) { + case 0: equals = true; break; + case 1: equals = MISSING_ARG.equals(argList[0]); break; + default: equals = argList[0].equals(argList[1]); break; + } + String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals"); + if (verbosity >= 2) + System.out.println(logEntry(willCall, argList)); + Object result = mh.invokeVarargs(argList); + assertCalled(willCall, argList); + } + } + + @Test + public void testCatchException() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("catchException"); + for (int nargs = 2; nargs <= 6; nargs++) { + for (int ti = 0; ti <= 1; ti++) { + boolean throwIt = (ti != 0); + testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs); + testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs); + testCatchException(String.class, new LinkageError("testing"), throwIt, nargs); + } + } + } + + private static + Object throwOrReturn(Object normal, T exception) throws T { + if (exception != null) throw exception; + return normal; + } + + void testCatchException(Class returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable { + countTest(); + if (verbosity >= 2) + System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs); + Class exType = thrown.getClass(); + MethodHandle throwOrReturn + = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn", + MethodType.methodType(Object.class, Object.class, Throwable.class)); + MethodHandle thrower = throwOrReturn; + while (thrower.type().parameterCount() < nargs) + thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class); + MethodHandle target = MethodHandles.catchException(thrower, + thrown.getClass(), ValueConversions.varargsList(1+nargs)); + assertEquals(thrower.type(), target.type()); + //System.out.println("catching with "+target+" : "+throwOrReturn); + Object[] args = randomArgs(nargs, Object.class); + args[1] = (throwIt ? thrown : null); + Object returned = target.invokeVarargs(args); + //System.out.println("return from "+target+" : "+returned); + if (!throwIt) { + assertSame(args[0], returned); + } else { + List catchArgs = new ArrayList(Arrays.asList(args)); + catchArgs.add(0, thrown); + assertEquals(catchArgs, returned); + } + } + + @Test + public void testThrowException() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("throwException"); + testThrowException(int.class, new ClassCastException("testing")); + testThrowException(void.class, new java.io.IOException("testing")); + testThrowException(String.class, new LinkageError("testing")); + } + + void testThrowException(Class returnType, Throwable thrown) throws Throwable { + countTest(); + Class exType = thrown.getClass(); + MethodHandle target = MethodHandles.throwException(returnType, exType); + //System.out.println("throwing with "+target+" : "+thrown); + MethodType expectedType = MethodType.methodType(returnType, exType); + assertEquals(expectedType, target.type()); + Throwable caught = null; + try { + Object res = target.invokeGeneric(thrown); + fail("got "+res+" instead of throwing "+thrown); + } catch (Throwable ex) { + if (ex != thrown) { + if (ex instanceof Error) throw (Error)ex; + if (ex instanceof RuntimeException) throw (RuntimeException)ex; + } + caught = ex; + } + assertSame(thrown, caught); + } + + @Test + public void testCastFailure() throws Throwable { + if (CAN_SKIP_WORKING) return; + startTest("testCastFailure"); + testCastFailure("cast/argument", 11000); + testCastFailure("unbox/argument", 11000); + testCastFailure("cast/return", 11000); + testCastFailure("unbox/return", 11000); + } + + static class Surprise extends JavaMethodHandle { + Surprise() { super("value"); } + Object value(Object x) { + trace("value", x); + if (boo != null) return boo; + return x; + } + Object boo; + void boo(Object x) { boo = x; } + + static void trace(String x, Object y) { + if (verbosity > 8) System.out.println(x+"="+y); + } + static Object refIdentity(Object x) { trace("ref.x", x); return x; } + static Integer boxIdentity(Integer x) { trace("box.x", x); return x; } + static int intIdentity(int x) { trace("int.x", x); return x; } + static MethodHandle REF_IDENTITY = PRIVATE.findStatic( + Surprise.class, "refIdentity", + MethodType.methodType(Object.class, Object.class)); + static MethodHandle BOX_IDENTITY = PRIVATE.findStatic( + Surprise.class, "boxIdentity", + MethodType.methodType(Integer.class, Integer.class)); + static MethodHandle INT_IDENTITY = PRIVATE.findStatic( + Surprise.class, "intIdentity", + MethodType.methodType(int.class, int.class)); + } + + void testCastFailure(String mode, int okCount) throws Throwable { + countTest(false); + if (verbosity > 1) System.out.println("mode="+mode); + Surprise boo = new Surprise(); + MethodHandle identity = Surprise.REF_IDENTITY, surprise = boo; + if (mode.endsWith("/return")) { + if (mode.equals("unbox/return")) { + // fail on return to ((Integer)surprise).intValue + surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(int.class, Object.class)); + identity = MethodHandles.convertArguments(identity, MethodType.methodType(int.class, Object.class)); + } else if (mode.equals("cast/return")) { + // fail on return to (Integer)surprise + surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(Integer.class, Object.class)); + identity = MethodHandles.convertArguments(identity, MethodType.methodType(Integer.class, Object.class)); + } + } else if (mode.endsWith("/argument")) { + MethodHandle callee = null; + if (mode.equals("unbox/argument")) { + // fail on handing surprise to int argument + callee = Surprise.INT_IDENTITY; + } else if (mode.equals("cast/argument")) { + // fail on handing surprise to Integer argument + callee = Surprise.BOX_IDENTITY; + } + if (callee != null) { + callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1)); + surprise = MethodHandles.filterArguments(callee, surprise); + identity = MethodHandles.filterArguments(callee, identity); + } + } + assertNotSame(mode, surprise, boo); + identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1)); + surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1)); + Object x = 42; + for (int i = 0; i < okCount; i++) { + Object y = identity.invoke(x); + assertEquals(x, y); + Object z = surprise.invoke(x); + assertEquals(x, z); + } + boo.boo("Boo!"); + Object y = identity.invoke(x); + assertEquals(x, y); + try { + Object z = surprise.invoke(x); + System.out.println("Failed to throw; got z="+z); + assertTrue(false); + } catch (Exception ex) { + if (verbosity > 1) + System.out.println("caught "+ex); + if (verbosity > 2) + ex.printStackTrace(); + assertTrue(ex instanceof ClassCastException + // FIXME: accept only one of the two for any given unit test + || ex instanceof WrongMethodTypeException + ); + } + } + +} +// Local abbreviated copy of sun.dyn.util.ValueConversions +class ValueConversions { + private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); + private static final Object[] NO_ARGS_ARRAY = {}; + private static Object[] makeArray(Object... args) { return args; } + private static Object[] array() { return NO_ARGS_ARRAY; } + private static Object[] array(Object a0) + { return makeArray(a0); } + private static Object[] array(Object a0, Object a1) + { return makeArray(a0, a1); } + private static Object[] array(Object a0, Object a1, Object a2) + { return makeArray(a0, a1, a2); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3) + { return makeArray(a0, a1, a2, a3); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4) + { return makeArray(a0, a1, a2, a3, a4); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) + { return makeArray(a0, a1, a2, a3, a4, a5); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) + { return makeArray(a0, a1, a2, a3, a4, a5, a6); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + private static Object[] array(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) + { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + static MethodHandle[] makeArrays() { + ArrayList arrays = new ArrayList(); + MethodHandles.Lookup lookup = IMPL_LOOKUP; + for (;;) { + int nargs = arrays.size(); + MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class); + String name = "array"; + MethodHandle array = null; + try { + array = lookup.findStatic(ValueConversions.class, name, type); + } catch (NoAccessException ex) { + } + if (array == null) break; + arrays.add(array); + } + assert(arrays.size() == 11); // current number of methods + return arrays.toArray(new MethodHandle[0]); + } + static final MethodHandle[] ARRAYS = makeArrays(); + + /** Return a method handle that takes the indicated number of Object + * arguments and returns an Object array of them, as if for varargs. + */ + public static MethodHandle varargsArray(int nargs) { + if (nargs < ARRAYS.length) + return ARRAYS[nargs]; + // else need to spin bytecode or do something else fancy + throw new UnsupportedOperationException("NYI"); + } + + private static final List NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); + private static List makeList(Object... args) { return Arrays.asList(args); } + private static List list() { return NO_ARGS_LIST; } + private static List list(Object a0) + { return makeList(a0); } + private static List list(Object a0, Object a1) + { return makeList(a0, a1); } + private static List list(Object a0, Object a1, Object a2) + { return makeList(a0, a1, a2); } + private static List list(Object a0, Object a1, Object a2, Object a3) + { return makeList(a0, a1, a2, a3); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4) + { return makeList(a0, a1, a2, a3, a4); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5) + { return makeList(a0, a1, a2, a3, a4, a5); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6) + { return makeList(a0, a1, a2, a3, a4, a5, a6); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7) + { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8) + { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } + private static List list(Object a0, Object a1, Object a2, Object a3, + Object a4, Object a5, Object a6, Object a7, + Object a8, Object a9) + { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + static MethodHandle[] makeLists() { + ArrayList arrays = new ArrayList(); + MethodHandles.Lookup lookup = IMPL_LOOKUP; + for (;;) { + int nargs = arrays.size(); + MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class); + String name = "list"; + MethodHandle array = null; + try { + array = lookup.findStatic(ValueConversions.class, name, type); + } catch (NoAccessException ex) { + } + if (array == null) break; + arrays.add(array); + } + assert(arrays.size() == 11); // current number of methods + return arrays.toArray(new MethodHandle[0]); + } + static final MethodHandle[] LISTS = makeLists(); + + /** Return a method handle that takes the indicated number of Object + * arguments and returns List. + */ + public static MethodHandle varargsList(int nargs) { + if (nargs < LISTS.length) + return LISTS[nargs]; + // else need to spin bytecode or do something else fancy + throw new UnsupportedOperationException("NYI"); + } +} +// This guy tests access from outside the same package member, but inside +// the package itself. +class PackageSibling { + static Lookup lookup() { + return MethodHandles.lookup(); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/lang/Math/CeilAndFloorTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/Math/CeilAndFloorTests.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,201 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6908131 + * @summary Check for correct implementation of Math.ceil and Math.floor + */ + +import sun.misc.FpUtils; +import sun.misc.DoubleConsts; + +public class CeilAndFloorTests { + private static int testCeilCase(double input, double expected) { + int failures = 0; + failures += Tests.test("Math.ceil", input, Math.ceil(input), expected); + failures += Tests.test("StrictMath.ceil", input, StrictMath.ceil(input), expected); + return failures; + } + + private static int testFloorCase(double input, double expected) { + int failures = 0; + failures += Tests.test("Math.floor", input, Math.floor(input), expected); + failures += Tests.test("StrictMath.floor", input, StrictMath.floor(input), expected); + return failures; + } + + private static int nearIntegerTests() { + int failures = 0; + + double [] fixedPoints = { + -0.0, + 0.0, + -1.0, + 1.0, + -0x1.0p52, + 0x1.0p52, + -Double.MAX_VALUE, + Double.MAX_VALUE, + Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, + Double.NaN, + }; + + for(double fixedPoint : fixedPoints) { + failures += testCeilCase(fixedPoint, fixedPoint); + failures += testFloorCase(fixedPoint, fixedPoint); + } + + for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) { + double powerOfTwo = Math.scalb(1.0, i); + double neighborDown = FpUtils.nextDown(powerOfTwo); + double neighborUp = Math.nextUp(powerOfTwo); + + if (i < 0) { + failures += testCeilCase( powerOfTwo, 1.0); + failures += testCeilCase(-powerOfTwo, -0.0); + + failures += testFloorCase( powerOfTwo, 0.0); + failures += testFloorCase(-powerOfTwo, -1.0); + + failures += testCeilCase( neighborDown, 1.0); + failures += testCeilCase(-neighborDown, -0.0); + + failures += testFloorCase( neighborUp, 0.0); + failures += testFloorCase(-neighborUp, -1.0); + } else { + failures += testCeilCase(powerOfTwo, powerOfTwo); + failures += testFloorCase(powerOfTwo, powerOfTwo); + + if (neighborDown==Math.rint(neighborDown)) { + failures += testCeilCase( neighborDown, neighborDown); + failures += testCeilCase(-neighborDown, -neighborDown); + + failures += testFloorCase( neighborDown, neighborDown); + failures += testFloorCase(-neighborDown,-neighborDown); + } else { + failures += testCeilCase( neighborDown, powerOfTwo); + failures += testFloorCase(-neighborDown, -powerOfTwo); + } + + if (neighborUp==Math.rint(neighborUp)) { + failures += testCeilCase(neighborUp, neighborUp); + failures += testCeilCase(-neighborUp, -neighborUp); + + failures += testFloorCase(neighborUp, neighborUp); + failures += testFloorCase(-neighborUp, -neighborUp); + } else { + failures += testFloorCase(neighborUp, powerOfTwo); + failures += testCeilCase(-neighborUp, -powerOfTwo); + } + } + } + + for(int i = -(0x10000); i <= 0x10000; i++) { + double d = (double) i; + double neighborDown = FpUtils.nextDown(d); + double neighborUp = Math.nextUp(d); + + failures += testCeilCase( d, d); + failures += testCeilCase(-d, -d); + + failures += testFloorCase( d, d); + failures += testFloorCase(-d, -d); + + if (Math.abs(d) > 1.0) { + failures += testCeilCase( neighborDown, d); + failures += testCeilCase(-neighborDown, -d+1); + + failures += testFloorCase( neighborUp, d); + failures += testFloorCase(-neighborUp, -d-1); + } + } + + return failures; + } + + public static int roundingTests() { + int failures = 0; + double [][] testCases = { + { Double.MIN_VALUE, 1.0}, + {-Double.MIN_VALUE, -0.0}, + { FpUtils.nextDown(DoubleConsts.MIN_NORMAL), 1.0}, + {-FpUtils.nextDown(DoubleConsts.MIN_NORMAL), -0.0}, + { DoubleConsts.MIN_NORMAL, 1.0}, + {-DoubleConsts.MIN_NORMAL, -0.0}, + + { 0.1, 1.0}, + {-0.1, -0.0}, + + { 0.5, 1.0}, + {-0.5, -0.0}, + + { 1.5, 2.0}, + {-1.5, -1.0}, + + { 2.5, 3.0}, + {-2.5, -2.0}, + + { FpUtils.nextDown(1.0), 1.0}, + { FpUtils.nextDown(-1.0), -1.0}, + + { Math.nextUp(1.0), 2.0}, + { Math.nextUp(-1.0), -0.0}, + + { 0x1.0p51, 0x1.0p51}, + {-0x1.0p51, -0x1.0p51}, + + { FpUtils.nextDown(0x1.0p51), 0x1.0p51}, + {-Math.nextUp(0x1.0p51), -0x1.0p51}, + + { Math.nextUp(0x1.0p51), 0x1.0p51+1}, + {-FpUtils.nextDown(0x1.0p51), -0x1.0p51+1}, + + { FpUtils.nextDown(0x1.0p52), 0x1.0p52}, + {-Math.nextUp(0x1.0p52), -0x1.0p52-1.0}, + + { Math.nextUp(0x1.0p52), 0x1.0p52+1.0}, + {-FpUtils.nextDown(0x1.0p52), -0x1.0p52+1.0}, + }; + + for(double[] testCase : testCases) { + failures += testCeilCase(testCase[0], testCase[1]); + failures += testFloorCase(-testCase[0], -testCase[1]); + } + return failures; + } + + public static void main(String... args) { + int failures = 0; + + failures += nearIntegerTests(); + failures += roundingTests(); + + if (failures > 0) { + System.err.println("Testing {Math, StrictMath}.ceil incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/math/BigInteger/BigIntegerTest.java --- a/jdk/test/java/math/BigInteger/BigIntegerTest.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/math/BigInteger/BigIntegerTest.java Wed Jul 05 17:05:01 2017 +0200 @@ -642,37 +642,71 @@ for(int i = 0; i < bitPatterns.length; i++) { BigInteger b1 = new BigInteger(bitPatterns[i], 16); + BigInteger b2 = null; File f = new File("serialtest"); FileOutputStream fos = new FileOutputStream(f); - ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(b1); - oos.flush(); - oos.close(); - FileInputStream fis = new FileInputStream(f); - ObjectInputStream ois = new ObjectInputStream(fis); - BigInteger b2 = (BigInteger)ois.readObject(); + try { + ObjectOutputStream oos = new ObjectOutputStream(fos); + try { + oos.writeObject(b1); + oos.flush(); + } finally { + oos.close(); + } - if (!b1.equals(b2) || - !b1.equals(b1.or(b2))) { - failCount++; - System.err.println("Serialized failed for hex " + - b1.toString(16)); + FileInputStream fis = new FileInputStream(f); + try { + ObjectInputStream ois = new ObjectInputStream(fis); + try { + b2 = (BigInteger)ois.readObject(); + } finally { + ois.close(); + } + } finally { + fis.close(); + } + + if (!b1.equals(b2) || + !b1.equals(b1.or(b2))) { + failCount++; + System.err.println("Serialized failed for hex " + + b1.toString(16)); + } + } finally { + fos.close(); } f.delete(); } for(int i=0; i<10; i++) { BigInteger b1 = fetchNumber(rnd.nextInt(100)); + BigInteger b2 = null; File f = new File("serialtest"); FileOutputStream fos = new FileOutputStream(f); - ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(b1); - oos.flush(); - oos.close(); - FileInputStream fis = new FileInputStream(f); - ObjectInputStream ois = new ObjectInputStream(fis); - BigInteger b2 = (BigInteger)ois.readObject(); + try { + ObjectOutputStream oos = new ObjectOutputStream(fos); + try { + oos.writeObject(b1); + oos.flush(); + } finally { + oos.close(); + } + + FileInputStream fis = new FileInputStream(f); + try { + ObjectInputStream ois = new ObjectInputStream(fis); + try { + b2 = (BigInteger)ois.readObject(); + } finally { + ois.close(); + } + } finally { + fis.close(); + } + } finally { + fos.close(); + } if (!b1.equals(b2) || !b1.equals(b1.or(b2))) diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/Basic-X.java.template --- a/jdk/test/java/nio/Buffer/Basic-X.java.template Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/Basic-X.java.template Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final $type$[] VALUES = { + $Fulltype$.MIN_VALUE, + ($type$) -1, + ($type$) 0, + ($type$) 1, + $Fulltype$.MAX_VALUE, +#if[float] + $Fulltype$.NEGATIVE_INFINITY, + $Fulltype$.POSITIVE_INFINITY, + $Fulltype$.NaN, + ($type$) -0.0, +#end[float] +#if[double] + $Fulltype$.NEGATIVE_INFINITY, + $Fulltype$.POSITIVE_INFINITY, + $Fulltype$.NaN, + ($type$) -0.0, +#end[double] + }; + private static void relGet($Type$Buffer b) { int n = b.capacity(); $type$ v; @@ -309,6 +329,12 @@ #end[byte] + private static void fail(String problem, + $Type$Buffer xb, $Type$Buffer yb, + $type$ x, $type$ y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for ($type$ x : VALUES) { + $Type$Buffer xb = $Type$Buffer.wrap(new $type$[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for ($type$ y : VALUES) { + $Type$Buffer yb = $Type$Buffer.wrap(new $type$[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != $Fulltype$.compare(x, y)) { +#if[float] + if (x == 0.0 && y == 0.0) continue; +#end[float] +#if[double] + if (x == 0.0 && y == 0.0) continue; +#end[double] + fail("Incorrect results for $Type$Buffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for $Type$Buffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/BasicByte.java --- a/jdk/test/java/nio/Buffer/BasicByte.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/BasicByte.java Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final byte[] VALUES = { + Byte.MIN_VALUE, + (byte) -1, + (byte) 0, + (byte) 1, + Byte.MAX_VALUE, + + + + + + + + + + + + + }; + private static void relGet(ByteBuffer b) { int n = b.capacity(); byte v; @@ -309,6 +329,12 @@ + private static void fail(String problem, + ByteBuffer xb, ByteBuffer yb, + byte x, byte y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for (byte x : VALUES) { + ByteBuffer xb = ByteBuffer.wrap(new byte[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for (byte y : VALUES) { + ByteBuffer yb = ByteBuffer.wrap(new byte[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != Byte.compare(x, y)) { + + + + + + + fail("Incorrect results for ByteBuffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for ByteBuffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/BasicChar.java --- a/jdk/test/java/nio/Buffer/BasicChar.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/BasicChar.java Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final char[] VALUES = { + Character.MIN_VALUE, + (char) -1, + (char) 0, + (char) 1, + Character.MAX_VALUE, + + + + + + + + + + + + + }; + private static void relGet(CharBuffer b) { int n = b.capacity(); char v; @@ -309,6 +329,12 @@ + private static void fail(String problem, + CharBuffer xb, CharBuffer yb, + char x, char y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for (char x : VALUES) { + CharBuffer xb = CharBuffer.wrap(new char[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for (char y : VALUES) { + CharBuffer yb = CharBuffer.wrap(new char[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != Character.compare(x, y)) { + + + + + + + fail("Incorrect results for CharBuffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for CharBuffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/BasicDouble.java --- a/jdk/test/java/nio/Buffer/BasicDouble.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/BasicDouble.java Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final double[] VALUES = { + Double.MIN_VALUE, + (double) -1, + (double) 0, + (double) 1, + Double.MAX_VALUE, + + + + + + + + Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, + Double.NaN, + (double) -0.0, + + }; + private static void relGet(DoubleBuffer b) { int n = b.capacity(); double v; @@ -309,6 +329,12 @@ + private static void fail(String problem, + DoubleBuffer xb, DoubleBuffer yb, + double x, double y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for (double x : VALUES) { + DoubleBuffer xb = DoubleBuffer.wrap(new double[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for (double y : VALUES) { + DoubleBuffer yb = DoubleBuffer.wrap(new double[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != Double.compare(x, y)) { + + + + + if (x == 0.0 && y == 0.0) continue; + + fail("Incorrect results for DoubleBuffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for DoubleBuffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/BasicFloat.java --- a/jdk/test/java/nio/Buffer/BasicFloat.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/BasicFloat.java Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final float[] VALUES = { + Float.MIN_VALUE, + (float) -1, + (float) 0, + (float) 1, + Float.MAX_VALUE, + + Float.NEGATIVE_INFINITY, + Float.POSITIVE_INFINITY, + Float.NaN, + (float) -0.0, + + + + + + + + }; + private static void relGet(FloatBuffer b) { int n = b.capacity(); float v; @@ -309,6 +329,12 @@ + private static void fail(String problem, + FloatBuffer xb, FloatBuffer yb, + float x, float y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for (float x : VALUES) { + FloatBuffer xb = FloatBuffer.wrap(new float[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for (float y : VALUES) { + FloatBuffer yb = FloatBuffer.wrap(new float[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != Float.compare(x, y)) { + + if (x == 0.0 && y == 0.0) continue; + + + + + fail("Incorrect results for FloatBuffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for FloatBuffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/BasicInt.java --- a/jdk/test/java/nio/Buffer/BasicInt.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/BasicInt.java Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final int[] VALUES = { + Integer.MIN_VALUE, + (int) -1, + (int) 0, + (int) 1, + Integer.MAX_VALUE, + + + + + + + + + + + + + }; + private static void relGet(IntBuffer b) { int n = b.capacity(); int v; @@ -309,6 +329,12 @@ + private static void fail(String problem, + IntBuffer xb, IntBuffer yb, + int x, int y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for (int x : VALUES) { + IntBuffer xb = IntBuffer.wrap(new int[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for (int y : VALUES) { + IntBuffer yb = IntBuffer.wrap(new int[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != Integer.compare(x, y)) { + + + + + + + fail("Incorrect results for IntBuffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for IntBuffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/BasicLong.java --- a/jdk/test/java/nio/Buffer/BasicLong.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/BasicLong.java Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final long[] VALUES = { + Long.MIN_VALUE, + (long) -1, + (long) 0, + (long) 1, + Long.MAX_VALUE, + + + + + + + + + + + + + }; + private static void relGet(LongBuffer b) { int n = b.capacity(); long v; @@ -309,6 +329,12 @@ + private static void fail(String problem, + LongBuffer xb, LongBuffer yb, + long x, long y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for (long x : VALUES) { + LongBuffer xb = LongBuffer.wrap(new long[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for (long y : VALUES) { + LongBuffer yb = LongBuffer.wrap(new long[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != Long.compare(x, y)) { + + + + + + + fail("Incorrect results for LongBuffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for LongBuffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/BasicShort.java --- a/jdk/test/java/nio/Buffer/BasicShort.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/BasicShort.java Wed Jul 05 17:05:01 2017 +0200 @@ -38,6 +38,26 @@ extends Basic { + private static final short[] VALUES = { + Short.MIN_VALUE, + (short) -1, + (short) 0, + (short) 1, + Short.MAX_VALUE, + + + + + + + + + + + + + }; + private static void relGet(ShortBuffer b) { int n = b.capacity(); short v; @@ -309,6 +329,12 @@ + private static void fail(String problem, + ShortBuffer xb, ShortBuffer yb, + short x, short y) { + fail(problem + String.format(": x=%s y=%s", x, y), xb, yb); + } + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { boolean caught = false; try { @@ -522,6 +548,42 @@ if (b.compareTo(b2) <= 0) fail("Comparison to lesser buffer <= 0", b, b2); + // Check equals and compareTo with interesting values + for (short x : VALUES) { + ShortBuffer xb = ShortBuffer.wrap(new short[] { x }); + if (xb.compareTo(xb) != 0) { + fail("compareTo not reflexive", xb, xb, x, x); + } + if (! xb.equals(xb)) { + fail("equals not reflexive", xb, xb, x, x); + } + for (short y : VALUES) { + ShortBuffer yb = ShortBuffer.wrap(new short[] { y }); + if (xb.compareTo(yb) != - yb.compareTo(xb)) { + fail("compareTo not anti-symmetric", + xb, yb, x, y); + } + if ((xb.compareTo(yb) == 0) != xb.equals(yb)) { + fail("compareTo inconsistent with equals", + xb, yb, x, y); + } + if (xb.compareTo(yb) != Short.compare(x, y)) { + + + + + + + fail("Incorrect results for ShortBuffer.compareTo", + xb, yb, x, y); + } + if (xb.equals(yb) != ((x == y) || ((x != x) && (y != y)))) { + fail("Incorrect results for ShortBuffer.equals", + xb, yb, x, y); + } + } + } + // Sub, dup relPut(b); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/nio/Buffer/genBasic.sh --- a/jdk/test/java/nio/Buffer/genBasic.sh Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/nio/Buffer/genBasic.sh Wed Jul 05 17:05:01 2017 +0200 @@ -36,5 +36,3 @@ gen long Long Long gen float Float Float gen double Double Double - -rm -rf build diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java --- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Wed Jul 05 17:05:01 2017 +0200 @@ -146,13 +146,13 @@ oneRun(new ArrayBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingDeque(CAPACITY), pairs, iters); + oneRun(new SynchronousQueue(), pairs, iters / 8); + + /* TODO: unbounded queue implementations are prone to OOME + oneRun(new PriorityBlockingQueue(iters / 2 * pairs), pairs, iters / 4); oneRun(new LinkedTransferQueue(), pairs, iters); oneRun(new LTQasSQ(), pairs, iters); oneRun(new HalfSyncLTQ(), pairs, iters); - oneRun(new SynchronousQueue(), pairs, iters / 8); - - /* PriorityBlockingQueue is unbounded - oneRun(new PriorityBlockingQueue(iters / 2 * pairs), pairs, iters / 4); */ } diff -r 4b85cf247673 -r df0a816d95ef jdk/test/java/util/jar/JarFile/TurkCert.java --- a/jdk/test/java/util/jar/JarFile/TurkCert.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/java/util/jar/JarFile/TurkCert.java Wed Jul 05 17:05:01 2017 +0200 @@ -26,6 +26,7 @@ * @bug 4624534 * @summary Make sure jar certificates work for Turkish locale * @author kladko + * @run main/othervm TurkCert */ import java.util.*; diff -r 4b85cf247673 -r df0a816d95ef jdk/test/javax/xml/crypto/dsig/GenerationTests.java --- a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java Wed Jul 05 17:05:01 2017 +0200 @@ -23,7 +23,7 @@ /** * @test - * @bug 4635230 6283345 6303830 6824440 + * @bug 4635230 6283345 6303830 6824440 6867348 * @summary Basic unit tests for generating XML Signatures with JSR 105 * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java * X509KeySelector.java GenerationTests.java @@ -126,13 +126,14 @@ test_create_signature_x509_is(); test_create_signature_x509_ski(); test_create_signature_x509_sn(); -// test_create_signature(); + test_create_signature(); test_create_exc_signature(); test_create_sign_spec(); test_create_signature_enveloping_sha256_dsa(); test_create_signature_enveloping_sha384_rsa_sha256(); test_create_signature_enveloping_sha512_rsa_sha384(); test_create_signature_enveloping_sha512_rsa_sha512(); + test_create_signature_reference_dependency(); } private static void setup() throws Exception { @@ -410,6 +411,55 @@ System.out.println(); } + static void test_create_signature_reference_dependency() throws Exception { + System.out.println("* Generating signature-reference-dependency.xml"); + // create references + List refs = Collections.singletonList + (fac.newReference("#object-1", sha1)); + + // create SignedInfo + SignedInfo si = fac.newSignedInfo(withoutComments, rsaSha1, refs); + + // create objects + List objs = new ArrayList(); + + // Object 1 + List manRefs = Collections.singletonList + (fac.newReference("#object-2", sha1)); + objs.add(fac.newXMLObject(Collections.singletonList + (fac.newManifest(manRefs, "manifest-1")), "object-1", null, null)); + + // Object 2 + Document doc = db.newDocument(); + Element nc = doc.createElementNS(null, "NonCommentandus"); + nc.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", ""); + nc.appendChild(doc.createComment(" Commentandum ")); + objs.add(fac.newXMLObject(Collections.singletonList + (new DOMStructure(nc)), "object-2", null, null)); + + // create XMLSignature + XMLSignature sig = fac.newXMLSignature(si, rsa, objs, "signature", null); + DOMSignContext dsc = new DOMSignContext(getPrivateKey("RSA"), doc); + + sig.sign(dsc); + +// dumpDocument(doc, new PrintWriter(System.out)); + + DOMValidateContext dvc = new DOMValidateContext + (kvks, doc.getDocumentElement()); + XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); + + if (sig.equals(sig2) == false) { + throw new Exception + ("Unmarshalled signature is not equal to generated signature"); + } + if (sig2.validate(dvc) == false) { + throw new Exception("Validation of generated signature failed"); + } + + System.out.println(); + } + static void test_create_signature() throws Exception { System.out.println("* Generating signature.xml"); @@ -645,6 +695,7 @@ envDoc.getElementsByTagName("YoursSincerely").item(0); DOMSignContext dsc = new DOMSignContext(signingKey, ys); + dsc.setURIDereferencer(httpUd); sig.sign(dsc); @@ -660,6 +711,7 @@ DOMValidateContext dvc = new DOMValidateContext (new X509KeySelector(ks), sigElement); + dvc.setURIDereferencer(httpUd); File f = new File( System.getProperty("dir.test.vector.baltimore") + System.getProperty("file.separator") + diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/BadKdc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,113 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.security.krb5.Config; + +public class BadKdc { + + // Matches the krb5 debug output: + // >>> KDCCommunication: kdc=kdc.rabbit.hole UDP:14319, timeout=2000,... + // ^ kdc# ^ timeout + static final Pattern re = Pattern.compile( + ">>> KDCCommunication: kdc=kdc.rabbit.hole UDP:(\\d)...., " + + "timeout=(\\d)000,"); + public static void go(int[]... expected) + throws Exception { + System.setProperty("sun.security.krb5.debug", "true"); + + // Make sure KDCs' ports starts with 1 and 2 and 3, + // useful for checking debug output. + int p1 = 10000 + new java.util.Random().nextInt(10000); + int p2 = 20000 + new java.util.Random().nextInt(10000); + int p3 = 30000 + new java.util.Random().nextInt(10000); + + FileWriter fw = new FileWriter("alternative-krb5.conf"); + + fw.write("[libdefaults]\n" + + "default_realm = " + OneKDC.REALM + "\n" + + "kdc_timeout = 2000\n"); + fw.write("[realms]\n" + OneKDC.REALM + " = {\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p1 + "\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p2 + "\n" + + "kdc = " + OneKDC.KDCHOST + ":" + p3 + "\n" + + "}\n"); + + fw.close(); + System.setProperty("java.security.krb5.conf", "alternative-krb5.conf"); + Config.refresh(); + + // Turn on k3 only + KDC k3 = on(p3); + + test(expected[0]); + test(expected[1]); + Config.refresh(); + test(expected[2]); + + k3.terminate(); // shutdown k3 + on(p2); // k2 is on + test(expected[3]); + on(p1); // k1 and k2 is on + test(expected[4]); + } + + private static KDC on(int p) throws Exception { + KDC k = new KDC(OneKDC.REALM, OneKDC.KDCHOST, p, true); + k.addPrincipal(OneKDC.USER, OneKDC.PASS); + k.addPrincipalRandKey("krbtgt/" + OneKDC.REALM); + return k; + } + + /** + * One round of test for max_retries and timeout. + * @param timeout the expected timeout + * @param expected the expected kdc# timeout kdc# timeout... + */ + private static void test(int... expected) throws Exception { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + PrintStream oldout = System.out; + System.setOut(new PrintStream(bo)); + Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); + System.setOut(oldout); + + String[] lines = new String(bo.toByteArray()).split("\n"); + System.out.println("----------------- TEST -----------------"); + int count = 0; + for (String line: lines) { + Matcher m = re.matcher(line); + if (m.find()) { + System.out.println(line); + if (Integer.parseInt(m.group(1)) != expected[count++] || + Integer.parseInt(m.group(2)) != expected[count++]) { + throw new Exception("Fail here"); + } + } + } + if (count != expected.length) { + throw new Exception("Less rounds"); + } + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/BadKdc1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc1 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc1 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", "tryLess"); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2 + // The above line means try kdc1 for 2 seconds, then kdc1 + // for 2 seconds,..., finally kdc3 for 2 seconds. + new int[]{1,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2 + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,2,2,3,2}, // 1, 2 + // k3 off, k2 on + new int[]{1,2,2,2,1,2,2,2}, // 1 + // k1 on + new int[]{1,2,1,2} // empty + ); + } +} + diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/BadKdc2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc2.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc2 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc2 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", "tryLess:2,1000"); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2 + new int[]{1,1,1,1,2,1,2,1,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2 + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,1,1,1,2,1,2,1,3,2}, // 1, 2 + // k3 off, k2 on + new int[]{1,1,1,1,2,1,1,1,1,1,2,2}, // 1 + // k1 on + new int[]{1,1,1,2} // empty + ); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/BadKdc3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc3.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc3 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc3 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", "tryLast"); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2 + new int[]{3,2,3,2}, // 1, 2 + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,3,2}, // 1, 2 + // k3 off, k2 on + new int[]{3,2,3,2,3,2,1,2,1,2,1,2,2,2,2,2}, // 1, 3 + // k1 on + new int[]{2,2,2,2} // 1, 3 + ); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/BadKdc4.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/BadKdc4.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843127 + * @run main/timeout=300 BadKdc4 + * @summary krb5 should not try to access unavailable kdc too often + */ + +import java.io.*; +import java.security.Security; + +public class BadKdc4 { + + public static void main(String[] args) + throws Exception { + Security.setProperty("krb5.kdc.bad.policy", ""); + BadKdc.go( + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2}, + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2}, + // refresh + new int[]{1,2,1,2,1,2,2,2,2,2,2,2,3,2,1,2,1,2,1,2,2,2,2,2,2,2,3,2}, + // k3 off, k2 on + new int[]{1,2,1,2,1,2,2,2,1,2,1,2,1,2,2,2}, + // k1 on + new int[]{1,2,1,2} + ); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/KDC.java --- a/jdk/test/sun/security/krb5/auto/KDC.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/sun/security/krb5/auto/KDC.java Wed Jul 05 17:05:01 2017 +0200 @@ -141,6 +141,10 @@ // Options private Map options = new HashMap(); + private Thread thread1, thread2, thread3; + DatagramSocket u1 = null; + ServerSocket t1 = null; + /** * Option names, to be expanded forever. */ @@ -480,8 +484,9 @@ Method stringToKey = EncryptionKey.class.getDeclaredMethod("stringToKey", char[].class, String.class, byte[].class, Integer.TYPE); stringToKey.setAccessible(true); Integer kvno = null; - // For service whose password ending with a number, use it as kvno - if (p.toString().indexOf('/') >= 0) { + // For service whose password ending with a number, use it as kvno. + // Kvno must be postive. + if (p.toString().indexOf('/') > 0) { char[] pass = getPassword(p, server); if (Character.isDigit(pass[pass.length-1])) { kvno = pass[pass.length-1] - '0'; @@ -940,8 +945,6 @@ * @throws java.io.IOException for any communication error */ protected void startServer(int port, boolean asDaemon) throws IOException { - DatagramSocket u1 = null; - ServerSocket t1 = null; if (port > 0) { u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1")); t1 = new ServerSocket(port); @@ -966,7 +969,7 @@ this.port = port; // The UDP consumer - Thread thread = new Thread() { + thread1 = new Thread() { public void run() { while (true) { try { @@ -982,11 +985,11 @@ } } }; - thread.setDaemon(asDaemon); - thread.start(); + thread1.setDaemon(asDaemon); + thread1.start(); // The TCP consumer - thread = new Thread() { + thread2 = new Thread() { public void run() { while (true) { try { @@ -1004,11 +1007,11 @@ } } }; - thread.setDaemon(asDaemon); - thread.start(); + thread2.setDaemon(asDaemon); + thread2.start(); // The dispatcher - thread = new Thread() { + thread3 = new Thread() { public void run() { while (true) { try { @@ -1018,10 +1021,21 @@ } } }; - thread.setDaemon(true); - thread.start(); + thread3.setDaemon(true); + thread3.start(); } + public void terminate() { + try { + thread1.stop(); + thread2.stop(); + thread3.stop(); + u1.close(); + t1.close(); + } catch (Exception e) { + // OK + } + } /** * Helper class to encapsulate a job in a KDC. */ diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/MoreKvno.java --- a/jdk/test/sun/security/krb5/auto/MoreKvno.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/sun/security/krb5/auto/MoreKvno.java Wed Jul 05 17:05:01 2017 +0200 @@ -24,15 +24,20 @@ /* * @test * @bug 6893158 + * @bug 6907425 * @summary AP_REQ check should use key version number */ +import org.ietf.jgss.GSSException; import sun.security.jgss.GSSUtil; +import sun.security.krb5.KrbException; import sun.security.krb5.PrincipalName; import sun.security.krb5.internal.ktab.KeyTab; +import sun.security.krb5.internal.Krb5; public class MoreKvno { + static PrincipalName p; public static void main(String[] args) throws Exception { @@ -41,21 +46,40 @@ // Rewrite keytab, 3 set of keys with different kvno KeyTab ktab = KeyTab.create(OneKDC.KTAB); - PrincipalName p = new PrincipalName(OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST); - ktab.addEntry(p, "pass0".toCharArray(), 0); + p = new PrincipalName( + OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST); + ktab.addEntry(p, "pass1".toCharArray(), 1); + ktab.addEntry(p, "pass3".toCharArray(), 3); ktab.addEntry(p, "pass2".toCharArray(), 2); - ktab.addEntry(p, "pass1".toCharArray(), 1); ktab.save(); - kdc.addPrincipal(OneKDC.SERVER, "pass1".toCharArray()); - go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept"); - kdc.addPrincipal(OneKDC.SERVER, "pass2".toCharArray()); + char[] pass = "pass2".toCharArray(); + kdc.addPrincipal(OneKDC.SERVER, pass); + go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass); + + pass = "pass3".toCharArray(); + kdc.addPrincipal(OneKDC.SERVER, pass); // "server" initiate also, check pass2 is used at authentication - go(OneKDC.SERVER, "server"); + go(OneKDC.SERVER, "server", pass); + + try { + pass = "pass4".toCharArray(); + kdc.addPrincipal(OneKDC.SERVER, pass); + go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept", pass); + throw new Exception("This test should fail"); + } catch (GSSException gsse) { + KrbException ke = (KrbException)gsse.getCause(); + if (ke.returnCode() != Krb5.KRB_AP_ERR_BADKEYVER) { + throw new Exception("Not expected failure code: " + + ke.returnCode()); + } + } } - static void go(String server, String entry) throws Exception { + static void go(String server, String entry, char[] pass) throws Exception { Context c, s; + + // Part 1: Test keytab c = Context.fromUserPass("dummy", "bogus".toCharArray(), false); s = Context.fromJAAS(entry); @@ -66,5 +90,17 @@ s.dispose(); c.dispose(); + + // Part 2: Test username/password pair + c = Context.fromUserPass("dummy", "bogus".toCharArray(), false); + s = Context.fromUserPass(p.getNameString(), pass, true); + + c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + + Context.handshake(c, s); + + s.dispose(); + c.dispose(); } } diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/OneKDC.java --- a/jdk/test/sun/security/krb5/auto/OneKDC.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/sun/security/krb5/auto/OneKDC.java Wed Jul 05 17:05:01 2017 +0200 @@ -24,8 +24,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; import java.security.Security; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/SSL.java --- a/jdk/test/sun/security/krb5/auto/SSL.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/sun/security/krb5/auto/SSL.java Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6894643 + * @bug 6894643 6913636 * @summary Test JSSE Kerberos ciphersuite */ import java.io.*; @@ -32,12 +32,13 @@ import java.security.Principal; import java.util.Date; import sun.security.jgss.GSSUtil; +import sun.security.krb5.PrincipalName; +import sun.security.krb5.internal.ktab.KeyTab; public class SSL { private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"; private static final int LOOP_LIMIT = 1; - private static final char[] PASS = "secret".toCharArray(); private static int loopCount = 0; private static volatile String server; private static volatile int port; @@ -54,12 +55,39 @@ kdc.addPrincipal(OneKDC.USER, OneKDC.PASS); kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM); - kdc.addPrincipal("host/" + server, PASS); KDC.saveConfig(OneKDC.KRB5_CONF, kdc); System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF); + // Add 3 versions of keys into keytab + KeyTab ktab = KeyTab.create(OneKDC.KTAB); + PrincipalName service = new PrincipalName( + "host/" + server, PrincipalName.KRB_NT_SRV_HST); + ktab.addEntry(service, "pass1".toCharArray(), 1); + ktab.addEntry(service, "pass2".toCharArray(), 2); + ktab.addEntry(service, "pass3".toCharArray(), 3); + ktab.save(); + + // and use the middle one as the real key + kdc.addPrincipal("host/" + server, "pass2".toCharArray()); + + // JAAS config entry name ssl + System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF); + File f = new File(OneKDC.JAAS_CONF); + FileOutputStream fos = new FileOutputStream(f); + fos.write(( + "ssl {\n" + + " com.sun.security.auth.module.Krb5LoginModule required\n" + + " principal=\"host/" + server + "\"\n" + + " useKeyTab=true\n" + + " keyTab=" + OneKDC.KTAB + "\n" + + " isInitiator=false\n" + + " storeKey=true;\n};\n" + ).getBytes()); + fos.close(); + f.deleteOnExit(); + final Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false); - final Context s = Context.fromUserPass("host/" + server, PASS, true); + final Context s = Context.fromJAAS("ssl"); c.startAsClient("host/" + server, GSSUtil.GSS_KRB5_MECH_OID); s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/krb5/auto/Test5653.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/Test5653.java Wed Jul 05 17:05:01 2017 +0200 @@ -0,0 +1,80 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6895424 + * @summary RFC 5653 + */ + +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSManager; +import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; +import sun.security.jgss.GSSUtil; + +public class Test5653 { + + public static void main(String[] args) + throws Exception { + + Oid oldOid = new Oid("1.3.6.1.5.6.2"); + new OneKDC(null).writeJAASConf(); + + System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); + GSSManager m = GSSManager.getInstance(); + boolean found = false; + + // Test 1: the getMechsForName() method accepts it. + for (Oid tmp: m.getMechsForName(oldOid)) { + if (tmp.equals(GSSUtil.GSS_KRB5_MECH_OID)) { + found = true; + break; + } + } + if (!found) { + throw new Exception("Cannot found krb5 mech for old name type"); + } + + // Test 2: the createName() method accepts it. + GSSName name = m.createName("server@host.rabbit.hole", oldOid); + + // Test 3: its getStringNameType() output is correct + if (!name.getStringNameType().equals(GSSName.NT_HOSTBASED_SERVICE)) { + throw new Exception("GSSName not correct name type"); + } + + // Test 4: everything still works. + GSSContext c1 = m.createContext( + name, + GSSUtil.GSS_KRB5_MECH_OID, + null, + GSSContext.DEFAULT_LIFETIME); + byte[] token = c1.initSecContext(new byte[0], 0, 0); + + Context s; + s = Context.fromJAAS("server"); + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + s.x().acceptSecContext(token, 0, token.length); + } +} diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/security/util/Oid/S11N.sh --- a/jdk/test/sun/security/util/Oid/S11N.sh Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/sun/security/util/Oid/S11N.sh Wed Jul 05 17:05:01 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2004-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -21,8 +21,8 @@ # have any questions. # # @test -# @bug 4811968 -# @summary Serialization compatibility with old versions +# @bug 4811968 6908628 +# @summary Serialization compatibility with old versions (and fix) # @author Weijun Wang # # set a few environment variables so that the shell-script can run stand-alone @@ -99,7 +99,8 @@ # the test code -${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}SerialTest.java || exit 10 +${TESTJAVA}${FS}bin${FS}javac -target 1.4 -source 1.4 \ + -d . ${TESTSRC}${FS}SerialTest.java || exit 10 OLDJAVA=" /java/re/j2se/1.6.0/latest/binaries/${PF} @@ -161,4 +162,10 @@ rm -f tmp.oid.serial.old rm -f SerialTest.class +for oldj in ${OLDJAVA}; do + if [ ! -d ${oldj} ]; then + echo WARNING: ${oldj} is missing. Test incomplete! > /dev/stderr + fi +done + exit 0 diff -r 4b85cf247673 -r df0a816d95ef jdk/test/sun/tools/jhat/HatRun.java --- a/jdk/test/sun/tools/jhat/HatRun.java Thu Dec 17 14:10:29 2009 -0800 +++ b/jdk/test/sun/tools/jhat/HatRun.java Wed Jul 05 17:05:01 2017 +0200 @@ -166,8 +166,10 @@ jre_home ); String cdir = System.getProperty("test.classes", "."); String os_arch = System.getProperty("os.arch"); - boolean d64 = os_arch.equals("sparcv9") || - os_arch.equals("amd64"); + String os_name = System.getProperty("os.name"); + boolean d64 = os_name.equals("SunOS") && ( + os_arch.equals("sparcv9") || + os_arch.equals("amd64")); String isa_dir = d64?(File.separator+os_arch):""; String java = jre_home + File.separator + "bin" + isa_dir