OpenJDK / jdk8u / jdk8u / jdk
changeset 10601:da56587ffb26
Merge
author | asaha |
---|---|
date | Mon, 27 Oct 2014 14:09:55 -0700 |
parents | e4066947e8fe 89f29f60b6c8 |
children | 240ae8272509 |
files | .hgtags src/share/classes/com/sun/jarsigner/package.html src/share/classes/sun/awt/image/MultiResolutionBufferedImage.java src/share/classes/sun/security/jgss/GSSNameImpl.java src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java src/share/classes/sun/security/ssl/Handshaker.java src/solaris/classes/java/lang/UNIXProcess.java.aix src/solaris/classes/java/lang/UNIXProcess.java.bsd src/solaris/classes/java/lang/UNIXProcess.java.linux src/solaris/classes/java/lang/UNIXProcess.java.solaris src/solaris/native/sun/awt/awt_Plugin.c src/solaris/native/sun/awt/awt_Plugin.h src/solaris/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh test/sun/jvmstat/testlibrary/JavaProcess.java test/sun/security/krb5/TimeInCCache.java |
diffstat | 436 files changed, 23821 insertions(+), 12664 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Oct 24 11:49:24 2014 +0000 +++ b/.hgtags Mon Oct 27 14:09:55 2014 -0700 @@ -343,4 +343,16 @@ 649c7ba692012fd93c532fea133cf14785674387 jdk8u31-b03 ab6aa5ee3897ebfe4a04722a594fb2cecd6f3bef jdk8u31-b04 1e79baf89075967bddc64921d2680d8c1123f654 jdk8u31-b05 +e6ed015afbbf3459ba3297e270b4f3170e989c80 jdk8u40-b00 +6e223d48080ef40f4ec11ecbcd19b4a20813b9eb jdk8u40-b01 +4797cd0713b44b009525f1276d571ade7e24f3f5 jdk8u40-b02 +c67acfb24eed87629887128df51007218ddf1f60 jdk8u40-b03 +dde62d949f7847469b2ede2ca4190c95066adc91 jdk8u40-b04 +d587834579dadd18cb8b096e61d92e2dbccc2782 jdk8u40-b05 +25788892a6723c0742a24050cc25ab103d9804de jdk8u40-b06 +07f0e22b5c238dd7b89fedbed35f02ac6b392c96 jdk8u40-b07 +0f0d70abca09b4ddb0981204ad5a427d4ce935e9 jdk8u40-b08 +064adeb65ce82f9ff3cc7898e59d19eb64743c63 jdk8u40-b09 +c3a4729c70fa29d79ad77e0643ad7715ebbc96b5 jdk8u40-b10 +693da296b395139f2fe6d7131eb0b0d85f6015f6 jdk8u40-b11 1ecc234bd38950a2bc047aa253a5e803f0836a4e jdk8u45-b00
--- a/make/CompileDemos.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/CompileDemos.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -456,7 +456,7 @@ ################################################################################################## ifndef OPENJDK - DB_DEMO_ZIPFILE := $(wildcard $(JDK_TOPDIR)/src/closed/share/db/*.zip) + DB_DEMO_ZIPFILE := $(wildcard $(JDK_TOPDIR)/src/closed/share/db/db-derby-*-bin.zip) $(JDK_OUTPUTDIR)/demo/_the.db.unzipped: $(DB_DEMO_ZIPFILE) $(MKDIR) -p $(@D)
--- a/make/CompileJavaClasses.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/CompileJavaClasses.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -52,8 +52,9 @@ endif ifndef OPENJDK - # There exists two versions of this file... + # There exists two versions of these files... EXFILES := $(JDK_TOPDIR)/src/share/classes/javax/crypto/JarVerifier.java + EXFILES += $(JDK_TOPDIR)/src/share/classes/sun/management/ExtendedPlatformComponent.java ifeq ($(OPENJDK_TARGET_OS), windows) # This gets built on unix platforms implicitly in the old build even though
--- a/make/CompileNativeLibraries.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/CompileNativeLibraries.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -87,6 +87,9 @@ include lib/SoundLibraries.gmk +# Include the corresponding custom file, if present. +-include $(CUSTOM_MAKE_DIR)/CompileNativeLibraries.gmk + ########################################################################################## all: $(COPY_FILES) $(BUILD_LIBRARIES)
--- a/make/Images.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/Images.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -562,7 +562,7 @@ $(CAT) $< | $(SED) "s/XXXX/$(shell cat $(JDK_TOPDIR)/src/closed/share/db/COPYRIGHTYEAR)/" > $@ JDK_DB_TARGETS := $(patsubst $(JDK_TOPDIR)/src/closed/share/db/%, $(IMAGES_OUTPUTDIR)/_unzip/%.unzipped, \ - $(wildcard $(JDK_TOPDIR)/src/closed/share/db/*.zip)) \ + $(wildcard $(JDK_TOPDIR)/src/closed/share/db/db-derby-*-bin.zip)) \ $(JDK_IMAGE_DIR)/db/README-JDK.html $(JDK_IMAGE_DIR)/db/3RDPARTY endif
--- a/make/Tools.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/Tools.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -80,6 +80,7 @@ build.tools.generatecharacter.CharacterName TOOL_DTDBUILDER = $(JAVA) -Ddtd_home=$(JDK_TOPDIR)/make/data/dtdbuilder \ + -Djava.awt.headless=true \ -cp $(JDK_OUTPUTDIR)/btclasses build.tools.dtdbuilder.DTDBuilder TOOL_GENERATEBREAKITERATORDATA = $(JAVA) \
--- a/make/data/jdwp/jdwp.spec Fri Oct 24 11:49:24 2014 +0000 +++ b/make/data/jdwp/jdwp.spec Mon Oct 27 14:09:55 2014 -0700 @@ -1147,7 +1147,8 @@ (ErrorSet (Error INVALID_CLASS "clazz is not the ID of a class.") (Error INVALID_OBJECT "clazz is not a known ID.") - (Error INVALID_METHODID "methodID is not the ID of a method.") + (Error INVALID_METHODID "methodID is not the ID of a static method in " + "this class type or one of its superclasses.") (Error INVALID_THREAD) (Error THREAD_NOT_SUSPENDED) (Error VM_DEAD) @@ -1250,6 +1251,83 @@ ) ) (CommandSet InterfaceType=5 + (Command InvokeMethod=1 + "Invokes a static method. " + "The method must not be a static initializer. " + "The method must be a member of the interface type. " + "<p>Since JDWP version 1.8 " + "<p>" + "The method invocation will occur in the specified thread. " + "Method invocation can occur only if the specified thread " + "has been suspended by an event. " + "Method invocation is not supported " + "when the target VM has been suspended by the front-end. " + "<p>" + "The specified method is invoked with the arguments in the specified " + "argument list. " + "The method invocation is synchronous; the reply packet is not " + "sent until the invoked method returns in the target VM. " + "The return value (possibly the void value) is " + "included in the reply packet. " + "If the invoked method throws an exception, the " + "exception object ID is set in the reply packet; otherwise, the " + "exception object ID is null. " + "<p>" + "For primitive arguments, the argument value's type must match the " + "argument's type exactly. For object arguments, there must exist a " + "widening reference conversion from the argument value's type to the " + "argument's type and the argument's type must be loaded. " + "<p>" + "By default, all threads in the target VM are resumed while " + "the method is being invoked if they were previously " + "suspended by an event or by a command. " + "This is done to prevent the deadlocks " + "that will occur if any of the threads own monitors " + "that will be needed by the invoked method. It is possible that " + "breakpoints or other events might occur during the invocation. " + "Note, however, that this implicit resume acts exactly like " + "the ThreadReference resume command, so if the thread's suspend " + "count is greater than 1, it will remain in a suspended state " + "during the invocation. By default, when the invocation completes, " + "all threads in the target VM are suspended, regardless their state " + "before the invocation. " + "<p>" + "The resumption of other threads during the invoke can be prevented " + "by specifying the INVOKE_SINGLE_THREADED " + "bit flag in the <code>options</code> field; however, " + "there is no protection against or recovery from the deadlocks " + "described above, so this option should be used with great caution. " + "Only the specified thread will be resumed (as described for all " + "threads above). Upon completion of a single threaded invoke, the invoking thread " + "will be suspended once again. Note that any threads started during " + "the single threaded invocation will not be suspended when the " + "invocation completes. " + "<p>" + "If the target VM is disconnected during the invoke (for example, through " + "the VirtualMachine dispose command) the method invocation continues. " + (Out + (interfaceType clazz "The interface type ID.") + (threadObject thread "The thread in which to invoke.") + (method methodID "The method to invoke.") + (Repeat arguments + (value arg "The argument value.") + ) + (int options "Invocation <a href=\"#JDWP_InvokeOptions\">options</a>") + ) + (Reply + (value returnValue "The returned value.") + (tagged-object exception "The thrown exception.") + ) + (ErrorSet + (Error INVALID_CLASS "clazz is not the ID of an interface.") + (Error INVALID_OBJECT "clazz is not a known ID.") + (Error INVALID_METHODID "methodID is not the ID of a static method in this " + "interface type or is the ID of a static initializer.") + (Error INVALID_THREAD) + (Error THREAD_NOT_SUSPENDED) + (Error VM_DEAD) + ) + ) ) (CommandSet Method=6 (Command LineTable=1 @@ -1543,7 +1621,7 @@ "<p>" "By default, all threads in the target VM are resumed while " "the method is being invoked if they were previously " - "suspended by an event or by command. " + "suspended by an event or by a command. " "This is done to prevent the deadlocks " "that will occur if any of the threads own monitors " "that will be needed by the invoked method. It is possible that " @@ -1586,7 +1664,9 @@ (Error INVALID_OBJECT) (Error INVALID_CLASS "clazz is not the ID of a reference " "type.") - (Error INVALID_METHODID "methodID is not the ID of a method.") + (Error INVALID_METHODID "methodID is not the ID of an instance method " + "in this object's type or one of its superclasses, " + "superinterfaces, or implemented interfaces.") (Error INVALID_THREAD) (Error THREAD_NOT_SUSPENDED) (Error VM_DEAD)
--- a/make/gensrc/GensrcMisc.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/gensrc/GensrcMisc.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -62,25 +62,6 @@ ########################################################################################## -ifeq ($(OPENJDK_TARGET_OS_API), posix) - UPSUFFIX := $(OPENJDK_TARGET_OS) - ifeq ($(OPENJDK_TARGET_OS), macosx) - UPSUFFIX := bsd - endif - # UNIXProcess.java is different for solaris and linux. We need to copy - # the correct UNIXProcess.java over to $(JDK_OUTPUTDIR)/gensrc/java/lang/. - - $(JDK_OUTPUTDIR)/gensrc/java/lang/UNIXProcess.java: \ - $(JDK_TOPDIR)/src/solaris/classes/java/lang/UNIXProcess.java.$(UPSUFFIX) - $(ECHO) $(LOG_INFO) Copying UNIXProcess.java.$(OPENJDK_TARGET_OS) to java/lang/UNIXProcess.java - $(call install-file) - $(CHMOD) u+rw $@ - - GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/java/lang/UNIXProcess.java -endif - -########################################################################################## - GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/sun/nio/ch/SocketOptionRegistry.java GENSRC_SOR_SRC := $(JDK_TOPDIR)/src/share/native/sun/nio/ch
--- a/make/lib/Awt2dLibraries.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/lib/Awt2dLibraries.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -318,7 +318,7 @@ endif ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBAWT_FILES += awt_LoadLibrary.c img_colors.c + LIBAWT_FILES += awt_LoadLibrary.c LIBAWT_CFLAGS += -F/System/Library/Frameworks/JavaVM.framework/Frameworks endif @@ -611,7 +611,6 @@ debug_mem.c \ debug_trace.c \ debug_util.c \ - awt_Plugin.c \ gnome_interface.c \ gtk2_interface.c \ swing_GTKEngine.c \
--- a/make/lib/CoreLibraries.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/lib/CoreLibraries.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -129,9 +129,9 @@ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/common \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/java/util -ifneq ($(OPENJDK_TARGET_OS), macosx) +ifeq ($(OPENJDK_TARGET_OS), windows) LIBJAVA_SRC_DIRS += $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/util/locale/provider -else +else ifeq ($(OPENJDK_TARGET_OS), macosx) LIBJAVA_SRC_DIRS += $(JDK_TOPDIR)/src/macosx/native/sun/util/locale/provider endif
--- a/make/lib/ServiceabilityLibraries.gmk Fri Oct 24 11:49:24 2014 +0000 +++ b/make/lib/ServiceabilityLibraries.gmk Mon Oct 27 14:09:55 2014 -0700 @@ -23,6 +23,10 @@ # questions. # +# Include custom extensions if available. +-include $(CUSTOM_MAKE_DIR)/lib/ServiceabilityLibraries.gmk + + LIBATTACH_EXCLUDE_FILES := ifneq ($(OPENJDK_TARGET_OS), solaris) LIBATTACH_EXCLUDE_FILES += SolarisVirtualMachine.c @@ -283,12 +287,12 @@ ########################################################################################## -BUILD_LIBMANAGEMENT_SRC := $(JDK_TOPDIR)/src/share/native/sun/management \ +BUILD_LIBMANAGEMENT_SRC += $(JDK_TOPDIR)/src/share/native/sun/management \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/management BUILD_LIBMANAGEMENT_EXCLUDES := -BUILD_LIBMANAGEMENT_CFLAGS := -I$(JDK_TOPDIR)/src/share/native/sun/management +BUILD_LIBMANAGEMENT_CFLAGS += -I$(JDK_TOPDIR)/src/share/native/sun/management ifneq ($(OPENJDK_TARGET_OS), solaris) BUILD_LIBMANAGEMENT_EXCLUDES += SolarisOperatingSystem.c @@ -309,6 +313,9 @@ endif endif +# Make it possible to override this variable +LIBMANAGEMENT_MAPFILE ?= $(JDK_TOPDIR)/make/mapfiles/libmanagement/mapfile-vers + $(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT, \ LIBRARY := management, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ @@ -317,7 +324,7 @@ LANG := C, \ OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \ CFLAGS := $(CFLAGS_JDKLIB) $(BUILD_LIBMANAGEMENT_CFLAGS), \ - MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement/mapfile-vers, \ + MAPFILE := $(LIBMANAGEMENT_MAPFILE), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_solaris := -lkstat, \
--- a/make/mapfiles/libawt/mapfile-mawt-vers Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libawt/mapfile-mawt-vers Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -249,11 +249,6 @@ Java_sun_awt_motif_XsessionWMcommand; Java_sun_awt_motif_XsessionWMcommand_New; - # Java Plugin - getAwtLockFunctions; - getAwtData; - getAwtDisplay; - # libfontmanager entry points AWTIsHeadless; AWTCountFonts;
--- a/make/mapfiles/libawt/mapfile-vers Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libawt/mapfile-vers Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -174,13 +174,6 @@ Java_sun_awt_motif_XsessionWMcommand; Java_sun_awt_motif_XsessionWMcommand_New; - # Java Plugin - # This is in awt_LoadLibrary.c and falls through to libmawt. - # Evidently plugin needs this for backward compatability. - getAwtLockFunctions; - getAwtData; - getAwtDisplay; - # libfontmanager entry points AWTIsHeadless; GrPrim_Sg2dGetCompInfo;
--- a/make/mapfiles/libawt/mapfile-vers-linux Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libawt/mapfile-vers-linux Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -152,13 +152,6 @@ # Evidently CDE needs this for backward compatability. Java_sun_awt_motif_XsessionWMcommand; - # Java Plugin - # This is in awt_LoadLibrary.c and falls through to libmawt. - # Evidently plugin needs this for backward compatability. - getAwtLockFunctions; - getAwtData; - getAwtDisplay; - # libfontmanager entry points AWTIsHeadless; GrPrim_Sg2dGetCompInfo; @@ -283,11 +276,6 @@ # CDE private entry point Java_sun_awt_motif_XsessionWMcommand; - # Java Plugin - getAwtLockFunctions; - getAwtData; - getAwtDisplay; - # libfontmanager entry points AWTIsHeadless; AWTCountFonts;
--- a/make/mapfiles/libawt_xawt/mapfile-vers Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libawt_xawt/mapfile-vers Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -449,12 +449,6 @@ awt_Lock; awt_GetComponent; - # Java Plugin - # This is in awt_LoadLibrary.c and falls through to libmawt. - # Evidently plugin needs this for backward compatability. - getAwtLockFunctions; - getAwtData; - getAwtDisplay; #XAWT entry point for CDE Java_sun_awt_motif_XsessionWMcommand; Java_sun_awt_motif_XsessionWMcommand_New;
--- a/make/mapfiles/libjava/mapfile-vers Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libjava/mapfile-vers Mon Oct 27 14:09:55 2014 -0700 @@ -78,13 +78,13 @@ Java_java_io_FileInputStream_available; Java_java_io_FileInputStream_close0; Java_java_io_FileInputStream_initIDs; - Java_java_io_FileInputStream_open; + Java_java_io_FileInputStream_open0; Java_java_io_FileInputStream_read0; Java_java_io_FileInputStream_readBytes; Java_java_io_FileInputStream_skip; Java_java_io_FileOutputStream_close0; Java_java_io_FileOutputStream_initIDs; - Java_java_io_FileOutputStream_open; + Java_java_io_FileOutputStream_open0; Java_java_io_FileOutputStream_write; Java_java_io_FileOutputStream_writeBytes; Java_java_io_ObjectInputStream_bytesToDoubles; @@ -97,7 +97,7 @@ Java_java_io_RandomAccessFile_getFilePointer; Java_java_io_RandomAccessFile_initIDs; Java_java_io_RandomAccessFile_length; - Java_java_io_RandomAccessFile_open; + Java_java_io_RandomAccessFile_open0; Java_java_io_RandomAccessFile_read0; Java_java_io_RandomAccessFile_readBytes; Java_java_io_RandomAccessFile_seek0; @@ -287,8 +287,6 @@ # Java_sun_misc_VM_unsuspendSomeThreads; threads.c # Java_sun_misc_VM_unsuspendThreads; threads.c - Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPattern; - # Outcalls from libjvm done using dlsym(). VerifyClassCodes;
--- a/make/mapfiles/libjava/reorder-sparc Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libjava/reorder-sparc Mon Oct 27 14:09:55 2014 -0700 @@ -44,7 +44,7 @@ text: .text%Java_java_io_UnixFileSystem_canonicalize; text: .text%JNU_GetStringPlatformChars; text: .text%JNU_ReleaseStringPlatformChars; -text: .text%Java_java_io_FileInputStream_open; +text: .text%Java_java_io_FileInputStream_open0; text: .text%fileOpen; text: .text%Java_java_io_FileInputStream_readBytes; text: .text%readBytes;
--- a/make/mapfiles/libjava/reorder-sparcv9 Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libjava/reorder-sparcv9 Mon Oct 27 14:09:55 2014 -0700 @@ -47,7 +47,7 @@ text: .text%Java_java_io_UnixFileSystem_canonicalize; text: .text%JNU_GetStringPlatformChars; text: .text%JNU_ReleaseStringPlatformChars; -text: .text%Java_java_io_FileInputStream_open; +text: .text%Java_java_io_FileInputStream_open0; text: .text%fileOpen; text: .text%Java_java_io_FileInputStream_readBytes; text: .text%readBytes;
--- a/make/mapfiles/libjava/reorder-x86 Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libjava/reorder-x86 Mon Oct 27 14:09:55 2014 -0700 @@ -57,7 +57,7 @@ text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find; text: .text%Java_java_lang_Float_floatToIntBits; text: .text%Java_java_lang_Double_doubleToLongBits; -text: .text%Java_java_io_FileInputStream_open; +text: .text%Java_java_io_FileInputStream_open0; text: .text%fileOpen; text: .text%Java_java_io_UnixFileSystem_getLength; text: .text%Java_java_io_FileInputStream_readBytes; @@ -90,7 +90,7 @@ text: .text%JNU_CallMethodByName; text: .text%JNU_CallMethodByNameV; text: .text%Java_java_util_logging_FileHandler_lockFile; -text: .text%Java_java_io_FileOutputStream_open; +text: .text%Java_java_io_FileOutputStream_open0; text: .text%Java_java_io_UnixFileSystem_createDirectory; text: .text%Java_java_io_UnixFileSystem_getLastModifiedTime; text: .text%Java_java_util_prefs_FileSystemPreferences_lockFile0;
--- a/make/mapfiles/libjfr/mapfile-vers Fri Oct 24 11:49:24 2014 +0000 +++ b/make/mapfiles/libjfr/mapfile-vers Mon Oct 27 14:09:55 2014 -0700 @@ -10,8 +10,13 @@ Java_oracle_jrockit_jfr_Process_getpid; Java_oracle_jrockit_jfr_Timing_counterTime; Java_oracle_jrockit_jfr_Timing_init; - Java_oracle_jrockit_jfr_NativeLogger_output0; - Java_oracle_jrockit_jfr_VMJFR_isEnabled; + Java_oracle_jrockit_jfr_Logger_output0; + Java_oracle_jrockit_jfr_JFR_isCommercialFeaturesUnlocked; + Java_oracle_jrockit_jfr_JFR_isStarted; + Java_oracle_jrockit_jfr_JFR_isSupportedInVM; + Java_oracle_jrockit_jfr_JFR_startFlightRecorder; + Java_oracle_jrockit_jfr_JFR_isDisabledOnCommandLine; + Java_oracle_jrockit_jfr_JFR_isEnabled; Java_oracle_jrockit_jfr_VMJFR_options; Java_oracle_jrockit_jfr_VMJFR_init; Java_oracle_jrockit_jfr_VMJFR_addConstPool; @@ -33,7 +38,6 @@ Java_oracle_jrockit_jfr_VMJFR_setPeriod; Java_oracle_jrockit_jfr_VMJFR_getPeriod; Java_oracle_jrockit_jfr_VMJFR_descriptors; - Java_oracle_jrockit_jfr_VMJFR_redefineClass0; Java_oracle_jrockit_jfr_VMJFR_retransformClasses0; JNI_OnLoad; local:
--- a/make/profile-rtjar-includes.txt Fri Oct 24 11:49:24 2014 +0000 +++ b/make/profile-rtjar-includes.txt Mon Oct 27 14:09:55 2014 -0700 @@ -117,6 +117,8 @@ com/sun/security/ntlm \ com/sun/security/sasl \ com/sun/tracing \ + jdk/management \ + jdk/internal/cmm \ java/lang/instrument \ java/lang/management \ java/security/acl \
--- a/src/aix/classes/sun/awt/fontconfigs/aix.fontconfig.properties Fri Oct 24 11:49:24 2014 +0000 +++ b/src/aix/classes/sun/awt/fontconfigs/aix.fontconfig.properties Mon Oct 27 14:09:55 2014 -0700 @@ -24,9 +24,14 @@ # questions. # -# Minimal version for AIX using the standard Latin Type1 Fonts from the -# package X11.fnt.iso_T1. These fonts are installed by default into -# "/usr/lpp/X11/lib/X11/fonts/Type1" and sym-linked to "/usr/lib/X11/fonts/Type1" +# +# Portions Copyright (c) 2014 IBM Corporation +# + +# This file references the standard Latin Type1 fonts from the AIX package +# X11.fnt.iso_T1 and the Unicode TrueType fonts from X11.fnt.ucs.ttf. They +# are located by default under "/usr/lpp/X11/lib/X11/fonts/{Type1,TrueType}" +# and sym-linked to "/usr/lib/X11/fonts/". # Version @@ -34,44 +39,381 @@ # Component Font Mappings -dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1 -dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1 +allfonts.iso10646-extB=-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2 -dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1 -sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1 +dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +dialog.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 -serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1 -serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1 +dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +dialog.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 -monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1 +dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1 +dialog.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1 +dialog.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +serif.plain.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.plain.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.plain.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.plain.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.plain.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.plain.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.plain.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.plain.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.plain.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.plain.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +serif.bold.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.bold.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.bold.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.bold.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.bold.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.bold.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.bold.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.bold.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.bold.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.bold.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + + +serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1 +serif.italic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.italic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.italic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.italic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.italic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.italic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.italic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.italic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.italic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.italic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1 +serif.bolditalic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.bolditalic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.bolditalic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.bolditalic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.bolditalic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.bolditalic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.bolditalic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.bolditalic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.bolditalic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.bolditalic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 # Search Sequences sequence.allfonts=latin-1 +sequence.allfonts.UTF-8=latin-1,japanese-iso10646 +# Uk_UA +sequence.allfonts.x-IBM1124=latin-1,ukranian-ibm1124 +# Japanese +sequence.allfonts.x-IBM943C=latin-1,japanese-x0201,japanese-x0208,japanese-udc +sequence.allfonts.x-IBM29626C=latin-1,japanese-x0201,japanese-x0208,japanese-udc +sequence.allfonts.UTF-8.ja=japanese-iso10646,latin-1,iso10646-extB +# Chinese +sequence.allfonts.x-EUC_CN=latin-1,chinese +sequence.allfonts.GB18030=latin-1,chinese-iso10646,iso10646-extB +sequence.allfonts.UTF-8.zh.CN=latin-1,chinese-iso10646,iso10646-extB +# Taiwanese +sequence.allfonts.x-IBM964=latin-1,taiwanese-iso10646 +sequence.allfonts.Big5=latin-1,taiwanese-iso10646 +sequence.allfonts.UTF-8.zh.TW=latin-1,taiwanese-iso10646 +# Korean +sequence.allfonts.x-IBM970=latin-1,korean +sequence.allfonts.UTF-8.ko=latin-1,korean-iso10646 +# Thai +sequence.allfonts.TIS-620=latin-1,thai +sequence.allfonts.UTF-8.th=latin-1,thai +# fallback +sequence.fallback=thai,chinese-iso10646,taiwanese-iso10646,japanese-iso10646,korean-iso10646,iso10646-extB -filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa -filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa -filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa -filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa -filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa -filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa -filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa -filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa -filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa -filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa -filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa -filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa +# Exclusion Ranges +exclusion.japanese-iso10646=0000-00ff + +# Font File Names +filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa +filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa +filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa +filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa +filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa +filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa +filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa +filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa +filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa +filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa +filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa +filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa + + +filename.-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2=/usr/lpp/X11/lib/X11/fonts/TrueType/MTSanXBA.ttf + +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_t.ttf + +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdt.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_t.ttf + +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +filename.-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/courth.ttf +filename.-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/helvth.ttf +filename.-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/timeth.ttf + +filename.-*-*-medium-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-medium-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +filename.-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +# AWT font path +awtfontpath.japanese-x0201=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-x0208=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-udc=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.korean=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.korean-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.chinese=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.chinese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.taiwanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.thai=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.iso10646-extB=/usr/lpp/X11/lib/X11/fonts/TrueType +
--- a/src/macosx/classes/com/apple/laf/AquaImageFactory.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/com/apple/laf/AquaImageFactory.java Mon Oct 27 14:09:55 2014 -0700 @@ -46,10 +46,8 @@ import com.apple.laf.AquaIcon.SystemIcon; import com.apple.laf.AquaUtils.RecyclableObject; import com.apple.laf.AquaUtils.RecyclableSingleton; -import java.util.Arrays; -import java.util.List; -import sun.awt.image.MultiResolutionBufferedImage; import sun.awt.image.MultiResolutionImage; +import sun.awt.image.MultiResolutionCachedImage; public class AquaImageFactory { public static IconUIResource getConfirmImageIcon() { @@ -107,9 +105,9 @@ private static final int kAlertIconSize = 64; static IconUIResource getAppIconCompositedOn(final Image background) { - if (background instanceof MultiResolutionBufferedImage) { + if (background instanceof MultiResolutionCachedImage) { int width = background.getWidth(null); - Image mrIconImage = ((MultiResolutionBufferedImage) background).map( + Image mrIconImage = ((MultiResolutionCachedImage) background).map( rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width)); return new IconUIResource(new ImageIcon(mrIconImage)); } @@ -287,21 +285,7 @@ private static Image getNSIcon(String imageName) { Image icon = Toolkit.getDefaultToolkit() .getImage("NSImage://" + imageName); - - if (icon instanceof MultiResolutionImage) { - return icon; - } - - int w = icon.getWidth(null); - int h = icon.getHeight(null); - - Dimension[] sizes = new Dimension[]{ - new Dimension(w, h), new Dimension(2 * w, 2 * h) - }; - - return new MultiResolutionBufferedImage(icon, sizes, (width, height) -> - AquaUtils.getCImageCreator().createImageFromName( - imageName, width, height)); + return icon; } public static class NineSliceMetrics {
--- a/src/macosx/classes/com/apple/laf/AquaMenuBarUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/com/apple/laf/AquaMenuBarUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -26,11 +26,14 @@ package com.apple.laf; import java.awt.*; +import java.security.AccessController; import javax.swing.*; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicMenuBarUI; +import sun.lwawt.macosx.LWCToolkit; +import sun.security.action.GetBooleanAction; import sun.security.action.GetPropertyAction; // MenuBar implementation for Mac L&F @@ -131,28 +134,20 @@ ScreenMenuBar fScreenMenuBar; boolean useScreenMenuBar = getScreenMenuBarProperty(); - private static String getPrivSysProp(final String propName) { - return java.security.AccessController.doPrivileged(new GetPropertyAction(propName)); - } - static boolean getScreenMenuBarProperty() { - final String props[] = new String[]{""}; - - boolean useScreenMenuBar = false; - try { - props[0] = getPrivSysProp(AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); - - if (props[0] != null && props[0].equals("true")) useScreenMenuBar = true; - else { - props[0] = getPrivSysProp(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar"); - - if (props[0] != null && props[0].equals("true")) { - System.err.println(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar has been deprecated. Please switch to " + AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); - useScreenMenuBar = true; - } - } - } catch(final Throwable t) { }; - - return useScreenMenuBar; + // Do not allow AWT to set the screen menu bar if it's embedded in another UI toolkit + if (LWCToolkit.isEmbedded()) return false; + if (AccessController.doPrivileged( + new GetBooleanAction(AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"))) { + return true; + } + if (AccessController.doPrivileged( + new GetBooleanAction(AquaLookAndFeel.sOldPropertyPrefix + "useScreenMenuBar"))) { + System.err.println(AquaLookAndFeel.sOldPropertyPrefix + + "useScreenMenuBar has been deprecated. Please switch to " + + AquaLookAndFeel.sPropertyPrefix + "useScreenMenuBar"); + return true; + } + return false; } }
--- a/src/macosx/classes/com/apple/laf/AquaPainter.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/com/apple/laf/AquaPainter.java Mon Oct 27 14:09:55 2014 -0700 @@ -174,11 +174,7 @@ bounds, controlState); Image img = cache.getImage(key); if (img == null) { - - Image baseImage = createImage(imgX, imgY, imgW, imgH, bounds, - control, controlState); - - img = new MultiResolutionBufferedImage(baseImage, + img = new MultiResolutionCachedImage(imgW, imgH, (rvWidth, rvHeight) -> createImage(imgX, imgY, rvWidth, rvHeight, bounds, control, controlState));
--- a/src/macosx/classes/com/apple/laf/AquaUtils.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/com/apple/laf/AquaUtils.java Mon Oct 27 14:09:55 2014 -0700 @@ -48,7 +48,7 @@ import sun.swing.SwingUtilities2; import com.apple.laf.AquaImageFactory.SlicedImageControl; -import sun.awt.image.MultiResolutionBufferedImage; +import sun.awt.image.MultiResolutionCachedImage; final class AquaUtils { @@ -124,8 +124,8 @@ static Image generateLightenedImage(final Image image, final int percent) { final GrayFilter filter = new GrayFilter(true, percent); - return (image instanceof MultiResolutionBufferedImage) - ? ((MultiResolutionBufferedImage) image).map( + return (image instanceof MultiResolutionCachedImage) + ? ((MultiResolutionCachedImage) image).map( rv -> generateLightenedImage(rv, filter)) : generateLightenedImage(image, filter); }
--- a/src/macosx/classes/sun/font/CFontManager.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/sun/font/CFontManager.java Mon Oct 27 14:09:55 2014 -0700 @@ -43,7 +43,7 @@ import sun.misc.ThreadGroupUtils; import sun.lwawt.macosx.*; -public class CFontManager extends SunFontManager { +public final class CFontManager extends SunFontManager { private FontConfigManager fcManager = null; private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>(); @@ -61,20 +61,14 @@ return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts); } - private static String[] defaultPlatformFont = null; - /* * Returns an array of two strings. The first element is the * name of the font. The second element is the file name. */ @Override - public synchronized String[] getDefaultPlatformFont() { - if (defaultPlatformFont == null) { - defaultPlatformFont = new String[2]; - defaultPlatformFont[0] = "Lucida Grande"; - defaultPlatformFont[1] = "/System/Library/Fonts/LucidaGrande.ttc"; - } - return defaultPlatformFont; + protected String[] getDefaultPlatformFont() { + return new String[]{"Lucida Grande", + "/System/Library/Fonts/LucidaGrande.ttc"}; } // This is a way to register any kind of Font2D, not just files and composites.
--- a/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java Mon Oct 27 14:09:55 2014 -0700 @@ -94,10 +94,12 @@ @Override public void addDropTarget(DropTarget dt) { + getLwTarget().addDropTarget(dt); } @Override public void removeDropTarget(DropTarget dt) { + getLwTarget().removeDropTarget(dt); } @Override
--- a/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Mon Oct 27 14:09:55 2014 -0700 @@ -37,7 +37,8 @@ private CPlatformResponder responder; private static final Object classLock = new Object(); - private static volatile CEmbeddedFrame focusedWindow; + private static volatile CEmbeddedFrame globalFocusedWindow; + private CEmbeddedFrame browserWindowFocusedApplet; private boolean parentWindowActive = true; public CEmbeddedFrame() { @@ -110,10 +111,10 @@ synchronized (classLock) { // In some cases an applet may not receive the focus lost event // from the parent window (see 8012330) - focusedWindow = (focused) ? this - : ((focusedWindow == this) ? null : focusedWindow); + globalFocusedWindow = (focused) ? this + : ((globalFocusedWindow == this) ? null : globalFocusedWindow); } - if (focusedWindow == this) { + if (globalFocusedWindow == this) { // see bug 8010925 // we can't put this to handleWindowFocusEvent because // it won't be invoced if focuse is moved to a html element @@ -144,9 +145,23 @@ // non-focused applet. This method can be called from different threads. public void handleWindowFocusEvent(boolean parentWindowActive) { this.parentWindowActive = parentWindowActive; + // If several applets are running in different browser's windows, it is necessary to + // detect the switching between the parent windows and update globalFocusedWindow accordingly. + synchronized (classLock) { + if (!parentWindowActive) { + this.browserWindowFocusedApplet = globalFocusedWindow; + } + if (parentWindowActive && globalFocusedWindow != this && isParentWindowChanged()) { + // It looks like we have switched to another browser window, let's restore focus to + // the previously focused applet in this window. If no applets were focused in the + // window, we will set focus to the first applet in the window. + globalFocusedWindow = (this.browserWindowFocusedApplet != null) ? this.browserWindowFocusedApplet + : this; + } + } // ignore focus "lost" native request as it may mistakenly // deactivate active window (see 8001161) - if (focusedWindow == this && parentWindowActive) { + if (globalFocusedWindow == this && parentWindowActive) { responder.handleWindowFocusEvent(parentWindowActive, null); } } @@ -154,4 +169,10 @@ public boolean isParentWindowActive() { return parentWindowActive; } + + private boolean isParentWindowChanged() { + // If globalFocusedWindow is located at inactive parent window or null, we have swithed to + // another window. + return globalFocusedWindow != null ? !globalFocusedWindow.isParentWindowActive() : true; + } }
--- a/src/macosx/classes/sun/lwawt/macosx/CImage.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CImage.java Mon Oct 27 14:09:55 2014 -0700 @@ -32,7 +32,7 @@ import java.util.Arrays; import java.util.List; import sun.awt.image.MultiResolutionImage; -import sun.awt.image.MultiResolutionBufferedImage; +import sun.awt.image.MultiResolutionCachedImage; import sun.awt.image.SunWritableRaster; @@ -60,41 +60,41 @@ // This is used to create a CImage with an NSImage pointer. It MUST be a CFRetained // NSImage, and the CImage takes ownership of the non-GC retain. If callers need the // NSImage themselves, they MUST call retain on the NSImage themselves. - public BufferedImage createImageUsingNativeSize(final long image) { + public Image createImageUsingNativeSize(final long image) { if (image == 0) return null; final Dimension2D size = nativeGetNSImageSize(image); - return createBufferedImage(image, size.getWidth(), size.getHeight()); + return createImage(image, size.getWidth(), size.getHeight()); } // the width and height passed in as a parameter could differ than the width and the height of the NSImage (image), in that case, the image will be scaled - BufferedImage createBufferedImage(long image, double width, double height) { + Image createImage(long image, double width, double height) { if (image == 0) throw new Error("Unable to instantiate CImage with null native image reference."); return createImageWithSize(image, width, height); } - public BufferedImage createImageWithSize(final long image, final double width, final double height) { + public Image createImageWithSize(final long image, final double width, final double height) { final CImage img = new CImage(image); img.resize(width, height); return img.toImage(); } // This is used to create a CImage that represents the icon of the given file. - public BufferedImage createImageOfFile(final String file, final int width, final int height) { - return createBufferedImage(nativeCreateNSImageOfFileFromLaunchServices(file), width, height); + public Image createImageOfFile(final String file, final int width, final int height) { + return createImage(nativeCreateNSImageOfFileFromLaunchServices(file), width, height); } - public BufferedImage createImageFromFile(final String file, final double width, final double height) { + public Image createImageFromFile(final String file, final double width, final double height) { final long image = nativeCreateNSImageFromFileContents(file); nativeSetNSImageSize(image, width, height); - return createBufferedImage(image, width, height); + return createImage(image, width, height); } - public BufferedImage createSystemImageFromSelector(final String iconSelector, final int width, final int height) { - return createBufferedImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height); + public Image createSystemImageFromSelector(final String iconSelector, final int width, final int height) { + return createImage(nativeCreateNSImageFromIconSelector(getSelectorAsInt(iconSelector)), width, height); } public Image createImageFromName(final String name, final int width, final int height) { - return createBufferedImage(nativeCreateNSImageFromImageName(name), width, height); + return createImage(nativeCreateNSImageFromImageName(name), width, height); } public Image createImageFromName(final String name) { @@ -213,7 +213,7 @@ } /** @return A MultiResolution image created from nsImagePtr, or null. */ - private BufferedImage toImage() { + private Image toImage() { if (ptr == 0) return null; final Dimension2D size = nativeGetNSImageSize(ptr); @@ -224,11 +224,11 @@ = nativeGetNSImageRepresentationSizes(ptr, size.getWidth(), size.getHeight()); - BufferedImage baseImage = toImage(w, h, w, h); - - return sizes == null || sizes.length < 2 ? baseImage - : new MultiResolutionBufferedImage(baseImage, sizes, - (width, height) -> toImage(w, h, width, height)); + return sizes == null || sizes.length < 2 ? + new MultiResolutionCachedImage(w, h, (width, height) + -> toImage(w, h, width, height)) + : new MultiResolutionCachedImage(w, h, sizes, (width, height) + -> toImage(w, h, width, height)); } private BufferedImage toImage(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Mon Oct 27 14:09:55 2014 -0700 @@ -538,9 +538,9 @@ return super.getImage(filename); } - String fileneame2x = getScaledImageName(filename); - return (imageExists(fileneame2x)) - ? getImageWithResolutionVariant(filename, fileneame2x) + String filename2x = getScaledImageName(filename); + return (imageExists(filename2x)) + ? getImageWithResolutionVariant(filename, filename2x) : super.getImage(filename); } @@ -686,6 +686,11 @@ @Override public DragSourceContextPeer createDragSourceContextPeer( DragGestureEvent dge) throws InvalidDnDOperationException { + final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent()); + if (f != null) { + return f.createDragSourceContextPeer(dge); + } + return CDragSourceContextPeer.createDragSourceContextPeer(dge); } @@ -693,6 +698,11 @@ public <T extends DragGestureRecognizer> T createDragGestureRecognizer( Class<T> abstractRecognizerClass, DragSource ds, Component c, int srcActions, DragGestureListener dgl) { + final LightweightFrame f = SunToolkit.getLightweightFrame(c); + if (f != null) { + return f.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl); + } + DragGestureRecognizer dgr = null; // Create a new mouse drag gesture recognizer if we have a class match: @@ -784,6 +794,13 @@ */ native boolean isApplicationActive(); + /** + * Returns true if AWT toolkit is embedded, false otherwise. + * + * @return true if AWT toolkit is embedded, false otherwise + */ + public static native boolean isEmbedded(); + /************************ * Native methods section ************************/ @@ -891,6 +908,9 @@ } private static boolean isValidPath(String path) { - return !path.isEmpty() && !path.endsWith("/") && !path.endsWith("."); + return path != null && + !path.isEmpty() && + !path.endsWith("/") && + !path.endsWith("."); } }
--- a/src/macosx/native/sun/awt/JavaComponentAccessibility.m Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/native/sun/awt/JavaComponentAccessibility.m Mon Oct 27 14:09:55 2014 -0700 @@ -1122,7 +1122,10 @@ JNIEnv *env = [ThreadUtilities getJNIEnv]; id value = nil; + NSWindow* hostWindow = [[self->fView window] retain]; jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) + [hostWindow release]; + if (focused != NULL) { if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
--- a/src/macosx/native/sun/awt/LWCToolkit.m Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/native/sun/awt/LWCToolkit.m Mon Oct 27 14:09:55 2014 -0700 @@ -452,3 +452,14 @@ } +/* + * Class: sun_lwawt_macosx_LWCToolkit + * Method: isEmbedded + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_sun_lwawt_macosx_LWCToolkit_isEmbedded +(JNIEnv *env, jclass klass) { + return [ThreadUtilities isAWTEmbedded] ? JNI_TRUE : JNI_FALSE; +} +
--- a/src/macosx/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Fri Oct 24 11:49:24 2014 +0000 +++ b/src/macosx/native/sun/util/locale/provider/HostLocaleProviderAdapter_md.c Mon Oct 27 14:09:55 2014 -0700 @@ -24,6 +24,7 @@ */ #include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h" +#include "jni_util.h" #include <CoreFoundation/CoreFoundation.h> #include <stdio.h> @@ -63,6 +64,10 @@ localeString = getMacOSXLocale(posixCat); if (localeString == NULL) { localeString = getPosixLocale(posixCat); + if (localeString == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + return NULL; + } } ret = (*env)->NewStringUTF(env, localeString); free(localeString); @@ -127,6 +132,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { CFLocaleRef cflocale = CFLocaleCopyCurrent(); + jstring tmp_string; if (cflocale != NULL) { CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, cflocale, @@ -138,13 +144,21 @@ if (amStr != NULL) { CFStringGetCString(amStr, buf, BUFLEN, kCFStringEncodingUTF8); CFRelease(amStr); - (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewStringUTF(env, buf)); + tmp_string = (*env)->NewStringUTF(env, buf); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 0, tmp_string); + } } - CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol); - if (pmStr != NULL) { - CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8); - CFRelease(pmStr); - (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewStringUTF(env, buf)); + if (!(*env)->ExceptionCheck(env)){ + CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol); + if (pmStr != NULL) { + CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8); + CFRelease(pmStr); + tmp_string = (*env)->NewStringUTF(env, buf); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, ampms, 1, tmp_string); + } + } } CFRelease(df); } @@ -647,10 +661,16 @@ static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count) { char buf[BUFLEN]; + jstring tmp_string; for (; count > 0; sindex++, dindex++, count--) { CFStringGetCString(CFArrayGetValueAtIndex(cfarray, sindex), buf, BUFLEN, kCFStringEncodingUTF8); - (*env)->SetObjectArrayElement(env, jarray, dindex, (*env)->NewStringUTF(env, buf)); + tmp_string = (*env)->NewStringUTF(env, buf); + if (tmp_string != NULL) { + (*env)->SetObjectArrayElement(env, jarray, dindex, tmp_string); + } else { + break; + } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/back/InterfaceTypeImpl.c Mon Oct 27 14:09:55 2014 -0700 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "util.h" +#include "InterfaceTypeImpl.h" +#include "inStream.h" +#include "outStream.h" + +static jboolean +invokeStatic(PacketInputStream *in, PacketOutputStream *out) +{ + return sharedInvoke(in, out); +} + +void *InterfaceType_Cmds[] = { (void *)0x1 + , (void *)invokeStatic +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/back/InterfaceTypeImpl.h Mon Oct 27 14:09:55 2014 -0700 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +extern void *InterfaceType_Cmds[];
--- a/src/share/back/VirtualMachineImpl.c Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/back/VirtualMachineImpl.c Mon Oct 27 14:09:55 2014 -0700 @@ -36,7 +36,7 @@ static char *versionName = "Java Debug Wire Protocol (Reference Implementation)"; static int majorVersion = 1; /* JDWP major version */ -static int minorVersion = 6; /* JDWP minor version */ +static int minorVersion = 8; /* JDWP minor version */ static jboolean version(PacketInputStream *in, PacketOutputStream *out)
--- a/src/share/back/debugDispatch.c Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/back/debugDispatch.c Mon Oct 27 14:09:55 2014 -0700 @@ -29,6 +29,7 @@ #include "VirtualMachineImpl.h" #include "ReferenceTypeImpl.h" #include "ClassTypeImpl.h" +#include "InterfaceTypeImpl.h" #include "ArrayTypeImpl.h" #include "FieldImpl.h" #include "MethodImpl.h" @@ -67,6 +68,7 @@ l1Array[JDWP_COMMAND_SET(VirtualMachine)] = (void *)VirtualMachine_Cmds; l1Array[JDWP_COMMAND_SET(ReferenceType)] = (void *)ReferenceType_Cmds; l1Array[JDWP_COMMAND_SET(ClassType)] = (void *)ClassType_Cmds; + l1Array[JDWP_COMMAND_SET(InterfaceType)] = (void *)InterfaceType_Cmds; l1Array[JDWP_COMMAND_SET(ArrayType)] = (void *)ArrayType_Cmds; l1Array[JDWP_COMMAND_SET(Field)] = (void *)Field_Cmds;
--- a/src/share/back/util.c Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/back/util.c Mon Oct 27 14:09:55 2014 -0700 @@ -591,6 +591,8 @@ invokeType = INVOKE_CONSTRUCTOR; } else if (inStream_command(in) == JDWP_COMMAND(ClassType, InvokeMethod)) { invokeType = INVOKE_STATIC; + } else if (inStream_command(in) == JDWP_COMMAND(InterfaceType, InvokeMethod)) { + invokeType = INVOKE_STATIC; } else if (inStream_command(in) == JDWP_COMMAND(ObjectReference, InvokeMethod)) { invokeType = INVOKE_INSTANCE; } else {
--- a/src/share/bin/java.c Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/bin/java.c Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,7 @@ */ static void SetClassPath(const char *s); static void SelectVersion(int argc, char **argv, char **main_class); +static void SetJvmEnvironment(int argc, char **argv); static jboolean ParseArguments(int *pargc, char ***pargv, int *pmode, char **pwhat, int *pret, const char *jrepath); @@ -238,6 +239,10 @@ jvmpath, sizeof(jvmpath), jvmcfg, sizeof(jvmcfg)); + if (!IsJavaArgs()) { + SetJvmEnvironment(argc,argv); + } + ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0; @@ -633,6 +638,67 @@ return jvmtype; } +/* + * static void SetJvmEnvironment(int argc, char **argv); + * Is called just before the JVM is loaded. We can set env variables + * that are consumed by the JVM. This function is non-destructive, + * leaving the arg list intact. The first use is for the JVM flag + * -XX:NativeMemoryTracking=value. + */ +static void +SetJvmEnvironment(int argc, char **argv) { + + static const char* NMT_Env_Name = "NMT_LEVEL_"; + + int i; + for (i = 0; i < argc; i++) { + /* + * The following case checks for "-XX:NativeMemoryTracking=value". + * If value is non null, an environmental variable set to this value + * will be created to be used by the JVM. + * The argument is passed to the JVM, which will check validity. + * The JVM is responsible for removing the env variable. + */ + char *arg = argv[i]; + if (JLI_StrCCmp(arg, "-XX:NativeMemoryTracking=") == 0) { + int retval; + // get what follows this parameter, include "=" + size_t pnlen = JLI_StrLen("-XX:NativeMemoryTracking="); + if (JLI_StrLen(arg) > pnlen) { + char* value = arg + pnlen; + size_t pbuflen = pnlen + JLI_StrLen(value) + 10; // 10 max pid digits + + /* + * ensures that malloc successful + * DONT JLI_MemFree() pbuf. JLI_PutEnv() uses system call + * that could store the address. + */ + char * pbuf = (char*)JLI_MemAlloc(pbuflen); + + JLI_Snprintf(pbuf, pbuflen, "%s%d=%s", NMT_Env_Name, JLI_GetPid(), value); + retval = JLI_PutEnv(pbuf); + if (JLI_IsTraceLauncher()) { + char* envName; + char* envBuf; + + // ensures that malloc successful + envName = (char*)JLI_MemAlloc(pbuflen); + JLI_Snprintf(envName, pbuflen, "%s%d", NMT_Env_Name, JLI_GetPid()); + + printf("TRACER_MARKER: NativeMemoryTracking: env var is %s\n",envName); + printf("TRACER_MARKER: NativeMemoryTracking: putenv arg %s\n",pbuf); + envBuf = getenv(envName); + printf("TRACER_MARKER: NativeMemoryTracking: got value %s\n",envBuf); + free(envName); + } + + } + + } + + } +} + /* copied from HotSpot function "atomll()" */ static int parse_size(const char *s, jlong *result) { @@ -1182,11 +1248,13 @@ (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); if (!(*env)->ExceptionOccurred(env)) { if (makePlatformStringMID == NULL) { - NULL_CHECK0(makePlatformStringMID = (*env)->GetStaticMethodID(env, + CHECK_JNI_RETURN_0( + makePlatformStringMID = (*env)->GetStaticMethodID(env, cls, "makePlatformString", "(Z[B)Ljava/lang/String;")); } - str = (*env)->CallStaticObjectMethod(env, cls, - makePlatformStringMID, USE_STDERR, ary); + CHECK_JNI_RETURN_0( + str = (*env)->CallStaticObjectMethod(env, cls, + makePlatformStringMID, USE_STDERR, ary)); (*env)->DeleteLocalRef(env, ary); return str; } @@ -1237,7 +1305,9 @@ "(ZILjava/lang/String;)Ljava/lang/Class;")); str = NewPlatformString(env, name); - result = (*env)->CallStaticObjectMethod(env, cls, mid, USE_STDERR, mode, str); + CHECK_JNI_RETURN_0( + result = (*env)->CallStaticObjectMethod( + env, cls, mid, USE_STDERR, mode, str)); if (JLI_IsTraceLauncher()) { end = CounterGet();
--- a/src/share/bin/java.h Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/bin/java.h Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -256,4 +256,47 @@ #define NULL_CHECK(NC_check_pointer) \ NULL_CHECK_RETURN_VALUE(NC_check_pointer, ) +/* + * For JNI calls : + * - check for thrown exceptions + * - check for null return + * + * JNI calls can return null and/or throw an exception. Check for these. + * + * : CHECK_JNI_RETURN_EXCEPTION() + * return the specified RETURNVALUE if exception was generated + * : CHECK_JNI_RETURN_0(JNISTATEMENT) : check if JNISTATEMENT was successful, return 0 if not + * : CHECK_JNI_RETURN_VOID(JNISTATEMENT) : check if JNISTATEMENT was successful, return void if not + * : CHECK_JNI_RETURN_VALUE(JNISTATEMENT,n) : check if JNISTATEMENT was successful, return n if not + * + * These macros need at least one parameter, the JNI statement [ JNISTATEMENT ]. + * + * E.G.: check the JNI statement, and specify a value to return if a failure was detected. + * + * CHECK_JNI_RETURN_VALUE(str = (*env)->CallStaticObjectMethod(env, cls, + * makePlatformStringMID, USE_STDERR, ary), -1); + */ + +#define RETURNVOID return +#define RETURN0 return 0 +#define RETURN(N) return (N) + +#define CHECK_JNI_RETURN_EXCEPTION(RETURNVALUE) \ + if ((((*env)->ExceptionOccurred(env))!=NULL)) { \ + RETURNVALUE; \ + } + +#define CHECK_JNI_RETURN_0(JNISTATEMENT) \ + CHECK_JNI_RETURN_EXCEPTION(RETURN0); \ + NULL_CHECK0(JNISTATEMENT); + +#define CHECK_JNI_RETURN_VOID(JNISTATEMENT) \ + CHECK_JNI_RETURN_EXCEPTION(RETURNVOID); \ + NULL_CHECK(JNISTATEMENT); + +#define CHECK_JNI_RETURN_VALUE(JNISTATEMENT, NCRV_return_value) \ + CHECK_JNI_RETURN_EXCEPTION(RETURN(NCRV_return_value)); \ + NULL_CHECK_RETURN_VALUE(JNISTATEMENT, NCRV_return_value); + + #endif /* _JAVA_H_ */
--- a/src/share/bin/jli_util.h Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/bin/jli_util.h Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,17 +64,22 @@ #ifdef _WIN32 #include <windows.h> #include <io.h> +#include <process.h> #define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) int JLI_Snprintf(char *buffer, size_t size, const char *format, ...); void JLI_CmdToArgs(char *cmdline); #define JLI_Lseek _lseeki64 +#define JLI_PutEnv _putenv +#define JLI_GetPid _getpid #else /* NIXES */ #include <unistd.h> #include <strings.h> #define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3)) #define JLI_Snprintf snprintf +#define JLI_PutEnv putenv +#define JLI_GetPid getpid #ifdef __solaris__ #define JLI_Lseek llseek #endif
--- a/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/imageio/plugins/png/PNGMetadata.java Mon Oct 27 14:09:55 2014 -0700 @@ -1254,8 +1254,11 @@ if (name.equals("IHDR")) { IHDR_width = getIntAttribute(node, "width"); IHDR_height = getIntAttribute(node, "height"); - IHDR_bitDepth = getEnumeratedAttribute(node, "bitDepth", - IHDR_bitDepths); + IHDR_bitDepth = + Integer.valueOf(IHDR_bitDepths[ + getEnumeratedAttribute(node, + "bitDepth", + IHDR_bitDepths)]); IHDR_colorType = getEnumeratedAttribute(node, "colorType", IHDR_colorTypeNames); IHDR_compressionMethod =
--- a/src/share/classes/com/sun/jarsigner/ContentSigner.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/jarsigner/ContentSigner.java Mon Oct 27 14:09:55 2014 -0700 @@ -37,6 +37,7 @@ * @author Vincent Ryan */ +@jdk.Exported public abstract class ContentSigner { /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/jarsigner/package-info.java Mon Oct 27 14:09:55 2014 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/** + * This package comprises the interfaces and classes used to define the + * signing mechanism used by the <tt>jarsigner</tt> tool. + * <p> + * Clients may override the default signing mechanism of the <tt>jarsigner</tt> + * tool by supplying an alternative implementation of + * {@link com.sun.jarsigner.ContentSigner}. + */ + +@jdk.Exported +package com.sun.jarsigner;
--- a/src/share/classes/com/sun/jarsigner/package.html Fri Oct 24 11:49:24 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -<html> -<!-- - -Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - -This code is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License version 2 only, as -published by the Free Software Foundation. Oracle designates this -particular file as subject to the "Classpath" exception as provided -by Oracle in the LICENSE file that accompanied this code. - -This code is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -version 2 for more details (a copy is included in the LICENSE file that -accompanied this code). - -You should have received a copy of the GNU General Public License version -2 along with this work; if not, write to the Free Software Foundation, -Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - -Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -or visit www.oracle.com if you need additional information or have any -questions. ---> - <head> - <title>Jarsigner Signing Mechanism Package</title> - </head> - <body> -This package comprises the interfaces and classes used to define the -signing mechanism used by the <tt>jarsigner</tt> tool. -<p> -Clients may override the default signing mechanism of the <tt>jarsigner</tt> -tool by supplying an alternative implementation of -{@link com.sun.jarsigner.ContentSigner}. - </body> -</html>
--- a/src/share/classes/com/sun/java/swing/SwingUtilities3.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/SwingUtilities3.java Mon Oct 27 14:09:55 2014 -0700 @@ -27,6 +27,8 @@ import sun.awt.EventQueueDelegate; import sun.awt.AppContext; +import sun.awt.SunToolkit; + import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; @@ -117,8 +119,8 @@ public static RepaintManager getDelegateRepaintManager(Component component) { RepaintManager delegate = null; - if (Boolean.TRUE == AppContext.getAppContext().get( - DELEGATE_REPAINT_MANAGER_KEY)) { + if (Boolean.TRUE == SunToolkit.targetToAppContext(component) + .get(DELEGATE_REPAINT_MANAGER_KEY)) { while (delegate == null && component != null) { while (component != null && ! (component instanceof JComponent)) {
--- a/src/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,11 +130,14 @@ //one second seems plausible value duration = 1000; } else { - duration = XPStyle.getXP().getThemeTransitionDuration( - c, part, - normalizeState(oldState), - normalizeState(newState), - Prop.TRANSITIONDURATIONS); + XPStyle xp = XPStyle.getXP(); + duration = (xp != null) + ? xp.getThemeTransitionDuration( + c, part, + normalizeState(oldState), + normalizeState(newState), + Prop.TRANSITIONDURATIONS) + : 1000; } controller.startAnimation(c, part, oldState, newState, duration); }
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsComboBoxUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.Part; import static com.sun.java.swing.plaf.windows.TMSchema.State; import static com.sun.java.swing.plaf.windows.XPStyle.Skin; + import sun.swing.DefaultLookup; import sun.swing.StringUIClientPropertyKey; @@ -231,6 +232,9 @@ private void paintXPComboBoxBackground(Graphics g, JComponent c) { XPStyle xp = XPStyle.getXP(); + if (xp == null) { + return; + } State state = getXPComboBoxState(c); Skin skin = null; if (! comboBox.isEditable() @@ -400,17 +404,18 @@ * @return a button which represents the popup control */ protected JButton createArrowButton() { - if (XPStyle.getXP() != null) { - return new XPComboBoxButton(); + XPStyle xp = XPStyle.getXP(); + if (xp != null) { + return new XPComboBoxButton(xp); } else { return super.createArrowButton(); } } private class XPComboBoxButton extends XPStyle.GlyphButton { - public XPComboBoxButton() { + public XPComboBoxButton(XPStyle xp) { super(null, - (! XPStyle.getXP().isSkinDefined(comboBox, Part.CP_DROPDOWNBUTTONRIGHT)) + (! xp.isSkinDefined(comboBox, Part.CP_DROPDOWNBUTTONRIGHT)) ? Part.CP_DROPDOWNBUTTON : (comboBox.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT) ? Part.CP_DROPDOWNBUTTONLEFT @@ -423,10 +428,11 @@ protected State getState() { State rv; rv = super.getState(); + XPStyle xp = XPStyle.getXP(); if (rv != State.DISABLED && comboBox != null && ! comboBox.isEditable() - && XPStyle.getXP().isSkinDefined(comboBox, - Part.CP_DROPDOWNBUTTONRIGHT)) { + && xp != null && xp.isSkinDefined(comboBox, + Part.CP_DROPDOWNBUTTONRIGHT)) { /* * for non editable ComboBoxes Vista seems to have the * same glyph for all non DISABLED states
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -125,6 +125,9 @@ static void paintXPText(AbstractButton b, Part part, State state, Graphics g, int x, int y, String text, int mnemIndex) { XPStyle xp = XPStyle.getXP(); + if (xp == null) { + return; + } Color textColor = b.getForeground(); if (textColor instanceof UIResource) {
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java Mon Oct 27 14:09:55 2014 -0700 @@ -613,8 +613,8 @@ private static class MenuArrowIcon implements Icon, UIResource, Serializable { public void paintIcon(Component c, Graphics g, int x, int y) { - if (WindowsMenuItemUI.isVistaPainting()) { - XPStyle xp = XPStyle.getXP(); + XPStyle xp = XPStyle.getXP(); + if (WindowsMenuItemUI.isVistaPainting(xp)) { State state = State.NORMAL; if (c instanceof JMenuItem) { state = ((JMenuItem) c).getModel().isEnabled() @@ -647,16 +647,18 @@ } } public int getIconWidth() { - if (WindowsMenuItemUI.isVistaPainting()) { - Skin skin = XPStyle.getXP().getSkin(null, Part.MP_POPUPSUBMENU); + XPStyle xp = XPStyle.getXP(); + if (WindowsMenuItemUI.isVistaPainting(xp)) { + Skin skin = xp.getSkin(null, Part.MP_POPUPSUBMENU); return skin.getWidth(); } else { return 4; } } public int getIconHeight() { - if (WindowsMenuItemUI.isVistaPainting()) { - Skin skin = XPStyle.getXP().getSkin(null, Part.MP_POPUPSUBMENU); + XPStyle xp = XPStyle.getXP(); + if (WindowsMenuItemUI.isVistaPainting(xp)) { + Skin skin = xp.getSkin(null, Part.MP_POPUPSUBMENU); return skin.getHeight(); } else { return 8; @@ -682,7 +684,8 @@ } static int getIconWidth() { - return XPStyle.getXP().getSkin(null, Part.MP_POPUPCHECK).getWidth() + XPStyle xp = XPStyle.getXP(); + return ((xp != null) ? xp.getSkin(null, Part.MP_POPUPCHECK).getWidth() : 16) + 2 * OFFSET; } @@ -745,12 +748,17 @@ Icon icon = getIcon(); int height = 0; if (icon != null) { - height = icon.getIconHeight() + 2 * OFFSET; + height = icon.getIconHeight(); } else { - Skin skin = - XPStyle.getXP().getSkin(null, Part.MP_POPUPCHECK); - height = skin.getHeight() + 2 * OFFSET; + XPStyle xp = XPStyle.getXP(); + if (xp != null) { + Skin skin = xp.getSkin(null, Part.MP_POPUPCHECK); + height = skin.getHeight(); + } else { + height = 16; + } } + height += 2 * OFFSET; return height; } @@ -798,14 +806,16 @@ ? State.BULLETDISABLED : State.CHECKMARKDISABLED; } - Skin skin; XPStyle xp = XPStyle.getXP(); - skin = xp.getSkin(c, backgroundPart); - skin.paintSkin(g, x, y, - getIconWidth(), getIconHeight(), backgroundState); - if (icon == null) { - skin = xp.getSkin(c, part); - skin.paintSkin(g, x + OFFSET, y + OFFSET, state); + if (xp != null) { + Skin skin; + skin = xp.getSkin(c, backgroundPart); + skin.paintSkin(g, x, y, + getIconWidth(), getIconHeight(), backgroundState); + if (icon == null) { + skin = xp.getSkin(c, part); + skin.paintSkin(g, x + OFFSET, y + OFFSET, state); + } } } }
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,14 +85,15 @@ } } else { buttonWidth += 2; - selectedTitleGradientColor = - UIManager.getColor("InternalFrame.activeTitleGradient"); - notSelectedTitleGradientColor = - UIManager.getColor("InternalFrame.inactiveTitleGradient"); Color activeBorderColor = UIManager.getColor("InternalFrame.activeBorderColor"); setBorder(BorderFactory.createLineBorder(activeBorderColor, 1)); } + // JDK-8039383: initialize these colors because getXP() may return null when theme is changed + selectedTitleGradientColor = + UIManager.getColor("InternalFrame.activeTitleGradient"); + notSelectedTitleGradientColor = + UIManager.getColor("InternalFrame.inactiveTitleGradient"); } protected void uninstallListeners() {
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Mon Oct 27 14:09:55 2014 -0700 @@ -2399,8 +2399,9 @@ } public Object getXPValue(UIDefaults table) { - Border xpBorder = XPStyle.getXP().getBorder(null, (Part)xpValue); - if (extraMargin != null) { + XPStyle xp = XPStyle.getXP(); + Border xpBorder = xp != null ? xp.getBorder(null, (Part)xpValue) : null; + if (xpBorder != null && extraMargin != null) { return new BorderUIResource. CompoundBorderUIResource(xpBorder, extraMargin); } else { @@ -2416,7 +2417,8 @@ public Object getXPValue(UIDefaults table) { XPColorValueKey key = (XPColorValueKey)xpValue; - return XPStyle.getXP().getColor(key.skin, key.prop, null); + XPStyle xp = XPStyle.getXP(); + return xp != null ? xp.getColor(key.skin, key.prop, null) : null; } private static class XPColorValueKey {
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuBarUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -155,8 +155,8 @@ @Override public void paint(Graphics g, JComponent c) { - if (WindowsMenuItemUI.isVistaPainting()) { - XPStyle xp = XPStyle.getXP(); + XPStyle xp = XPStyle.getXP(); + if (WindowsMenuItemUI.isVistaPainting(xp)) { Skin skin; skin = xp.getSkin(c, Part.MP_BARBACKGROUND); int width = c.getWidth();
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,8 +108,9 @@ static void paintBackground(WindowsMenuItemUIAccessor menuItemUI, Graphics g, JMenuItem menuItem, Color bgColor) { - assert isVistaPainting(); - if (isVistaPainting()) { + XPStyle xp = XPStyle.getXP(); + assert isVistaPainting(xp); + if (isVistaPainting(xp)) { int menuWidth = menuItem.getWidth(); int menuHeight = menuItem.getHeight(); if (menuItem.isOpaque()) { @@ -118,7 +119,6 @@ g.fillRect(0,0, menuWidth, menuHeight); g.setColor(oldColor); } - XPStyle xp = XPStyle.getXP(); Part part = menuItemUI.getPart(menuItem); Skin skin = xp.getSkin(menuItem, part); skin.paintSkin(g, 0 , 0, @@ -170,8 +170,11 @@ * is it possible that in some theme some Vista parts are not defined while * others are? */ - static boolean isVistaPainting() { - XPStyle xp = XPStyle.getXP(); + static boolean isVistaPainting(final XPStyle xp) { return xp != null && xp.isSkinDefined(null, Part.MP_POPUPITEM); } + + static boolean isVistaPainting() { + return isVistaPainting(XPStyle.getXP()); + } }
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,8 @@ public void paint(Graphics g, JComponent c) { Dimension s = c.getSize(); - if (WindowsMenuItemUI.isVistaPainting()) { + XPStyle xp = XPStyle.getXP(); + if (WindowsMenuItemUI.isVistaPainting(xp)) { int x = 1; Component parent = c.getParent(); if (parent instanceof JComponent) { @@ -67,7 +68,7 @@ x += WindowsPopupMenuUI.getGutterWidth(); } } - Skin skin = XPStyle.getXP().getSkin(c, Part.MP_POPUPSEPARATOR); + Skin skin = xp.getSkin(c, Part.MP_POPUPSEPARATOR); int skinHeight = skin.getHeight(); int y = (s.height - skinHeight) / 2; skin.paintSkin(g, x, y, s.width - x - 1, skinHeight, State.NORMAL);
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -194,8 +194,8 @@ @Override public void paint(Graphics g, JComponent c) { - if (WindowsMenuItemUI.isVistaPainting()) { - XPStyle xp = XPStyle.getXP(); + XPStyle xp = XPStyle.getXP(); + if (WindowsMenuItemUI.isVistaPainting(xp)) { Skin skin = xp.getSkin(c, Part.MP_POPUPBACKGROUND); skin.paintSkin(g, 0, 0, c.getWidth(),c.getHeight(), State.NORMAL); int textOffset = getTextOffset(c);
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsProgressBarUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -322,8 +322,9 @@ private Rectangle getFullChunkBounds(Rectangle box) { boolean vertical = (progressBar.getOrientation() == JProgressBar.VERTICAL); XPStyle xp = XPStyle.getXP(); - int gap = xp.getInt(progressBar, Part.PP_PROGRESS, null, - Prop.PROGRESSSPACESIZE, 0); + int gap = (xp != null) ? xp.getInt(progressBar, Part.PP_PROGRESS, + null, Prop.PROGRESSSPACESIZE, 0) + : 0; if (!vertical) { int chunksize = box.width+gap; @@ -338,6 +339,9 @@ boolean vertical, int bgwidth, int bgheight) { XPStyle xp = XPStyle.getXP(); + if (xp == null) { + return; + } // create a new graphics to keep drawing surface state Graphics2D gfx = (Graphics2D)g.create(); @@ -396,6 +400,9 @@ private void paintXPBackground(Graphics g, boolean vertical, int barRectWidth, int barRectHeight) { XPStyle xp = XPStyle.getXP(); + if (xp == null) { + return; + } Part part = vertical ? Part.PP_BARVERT : Part.PP_BAR; Skin skin = xp.getSkin(progressBar, part);
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSliderUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -215,7 +215,6 @@ } private Part getXPThumbPart() { - XPStyle xp = XPStyle.getXP(); Part part; boolean vertical = (slider.getOrientation() == JSlider.VERTICAL); boolean leftToRight = slider.getComponentOrientation().isLeftToRight();
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsSpinnerUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,9 @@ private void paintXPBackground(Graphics g, JComponent c) { XPStyle xp = XPStyle.getXP(); + if (xp == null) { + return; + } Skin skin = xp.getSkin(c, Part.EP_EDIT); State state = getXPState(c); skin.paintSkin(g, 0, 0, c.getWidth(), c.getHeight(), state);
--- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java Mon Oct 27 14:09:55 2014 -0700 @@ -90,9 +90,10 @@ this.column = column; this.hasRollover = (column == getRolloverColumn()); if (skin == null) { - skin = XPStyle.getXP().getSkin(header, Part.HP_HEADERITEM); + XPStyle xp = XPStyle.getXP(); + skin = (xp != null) ? xp.getSkin(header, Part.HP_HEADERITEM) : null; } - Insets margins = skin.getContentMargin(); + Insets margins = (skin != null) ? skin.getContentMargin() : null; Border border = null; int contentTop = 0; int contentLeft = 0;
--- a/src/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/XPStyle.java Mon Oct 27 14:09:55 2014 -0700 @@ -115,7 +115,7 @@ } } } - return xp; + return ThemeReader.isXPStyleEnabled() ? xp : null; } static boolean isVista() { @@ -180,9 +180,10 @@ * should probably be cached there instead of here. */ Dimension getDimension(Component c, Part part, State state, Prop prop) { - return ThemeReader.getPosition(part.getControlName(c), part.getValue(), - State.getValue(part, state), - prop.getValue()); + Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(), + State.getValue(part, state), + prop.getValue()); + return (d != null) ? d : new Dimension(); } /** Get a named <code>Point</code> (e.g. a location or an offset) value @@ -199,11 +200,7 @@ Dimension d = ThemeReader.getPosition(part.getControlName(c), part.getValue(), State.getValue(part, state), prop.getValue()); - if (d != null) { - return new Point(d.width, d.height); - } else { - return null; - } + return (d != null) ? new Point(d.width, d.height) : new Point(); } /** Get a named <code>Insets</code> value from the current style @@ -217,9 +214,10 @@ * The return value is already cached in those places. */ Insets getMargin(Component c, Part part, State state, Prop prop) { - return ThemeReader.getThemeMargins(part.getControlName(c), part.getValue(), - State.getValue(part, state), - prop.getValue()); + Insets insets = ThemeReader.getThemeMargins(part.getControlName(c), part.getValue(), + State.getValue(part, state), + prop.getValue()); + return (insets != null) ? insets : new Insets(0, 0, 0, 0); } @@ -505,16 +503,17 @@ int boundingWidth = 100; int boundingHeight = 100; - return ThemeReader.getThemeBackgroundContentMargins( + Insets insets = ThemeReader.getThemeBackgroundContentMargins( part.getControlName(null), part.getValue(), 0, boundingWidth, boundingHeight); + return (insets != null) ? insets : new Insets(0, 0, 0, 0); } private int getWidth(State state) { if (size == null) { size = getPartSize(part, state); } - return size.width; + return (size != null) ? size.width : 0; } int getWidth() { @@ -525,7 +524,7 @@ if (size == null) { size = getPartSize(part, state); } - return size.height; + return (size != null) ? size.height : 0; } int getHeight() { @@ -582,6 +581,9 @@ * @param state which state to paint */ void paintSkin(Graphics g, int dx, int dy, int dw, int dh, State state) { + if (XPStyle.getXP() == null) { + return; + } if (ThemeReader.isGetThemeTransitionDurationDefined() && component instanceof JComponent && SwingUtilities.getAncestorOfClass(CellRendererPane.class, @@ -607,6 +609,9 @@ * @param state which state to paint */ void paintSkinRaw(Graphics g, int dx, int dy, int dw, int dh, State state) { + if (XPStyle.getXP() == null) { + return; + } skinPainter.paint(null, g, dx, dy, dw, dh, this, state); } @@ -625,6 +630,9 @@ */ void paintSkin(Graphics g, int dx, int dy, int dw, int dh, State state, boolean borderFill) { + if (XPStyle.getXP() == null) { + return; + } if(borderFill && "borderfill".equals(getTypeEnumName(component, part, state, Prop.BGTYPE))) { return; @@ -679,7 +687,7 @@ public GlyphButton(Component parent, Part part) { XPStyle xp = getXP(); - skin = xp.getSkin(parent, part); + skin = xp != null ? xp.getSkin(parent, part) : null; setBorder(null); setContentAreaFilled(false); setMinimumSize(new Dimension(5, 5)); @@ -704,13 +712,16 @@ } public void paintComponent(Graphics g) { + if (XPStyle.getXP() == null || skin == null) { + return; + } Dimension d = getSize(); skin.paintSkin(g, 0, 0, d.width, d.height, getState()); } public void setPart(Component parent, Part part) { XPStyle xp = getXP(); - skin = xp.getSkin(parent, part); + skin = xp != null ? xp.getSkin(parent, part) : null; revalidate(); repaint(); }
--- a/src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,7 @@ " -V\u3001--version \u30D7\u30ED\u30B0\u30E9\u30E0\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059", " -J{X} \u30AA\u30D7\u30B7\u30E7\u30F3X\u3092\u57FA\u790E\u3068\u306A\u308BJava VM\u306B\u6E21\u3057\u307E\u3059", "", - "\u6CE8\u610F:", + "\u6CE8:", " -P\u3001-C\u3001-F\u3001-M\u304A\u3088\u3073-D\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u7D2F\u7A4D\u3055\u308C\u307E\u3059\u3002", " \u5C5E\u6027\u5B9A\u7FA9\u306E\u4F8B: -C SourceFile=RUH .", " Config.\u30D5\u30A1\u30A4\u30EB\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306F\u3001Pack200 API\u306B\u3088\u3063\u3066\u5B9A\u7FA9\u3055\u308C\u307E\u3059\u3002",
--- a/src/share/classes/com/sun/jdi/ClassType.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/jdi/ClassType.java Mon Oct 27 14:09:55 2014 -0700 @@ -103,7 +103,7 @@ * <p> * Object values must be assignment compatible with the field type * (This implies that the field type must be loaded through the - * enclosing class's class loader). Primitive values must be + * enclosing class' class loader). Primitive values must be * either assignment compatible with the field type or must be * convertible to the field type without loss of information. * See JLS section 5.2 for more information on assignment @@ -153,7 +153,7 @@ * <p> * Object arguments must be assignment compatible with the argument type * (This implies that the argument type must be loaded through the - * enclosing class's class loader). Primitive arguments must be + * enclosing class' class loader). Primitive arguments must be * either assignment compatible with the argument type or must be * convertible to the argument type without loss of information. * If the method being called accepts a variable number of arguments, @@ -216,7 +216,7 @@ * @return a {@link Value} mirror of the invoked method's return value. * @throws java.lang.IllegalArgumentException if the method is not * a member of this class or a superclass, if the size of the argument list - * does not match the number of declared arguemnts for the method, or + * does not match the number of declared arguments for the method, or * if the method is an initializer, constructor or static intializer. * @throws {@link InvalidTypeException} if any argument in the * argument list is not assignable to the corresponding method argument @@ -230,7 +230,7 @@ * @throws InvalidTypeException If the arguments do not meet this requirement -- * Object arguments must be assignment compatible with the argument * type. This implies that the argument type must be - * loaded through the enclosing class's class loader. + * loaded through the enclosing class' class loader. * Primitive arguments must be either assignment compatible with the * argument type or must be convertible to the argument type without loss * of information. See JLS section 5.2 for more information on assignment @@ -267,7 +267,7 @@ * <p> * Object arguments must be assignment compatible with the argument type * (This implies that the argument type must be loaded through the - * enclosing class's class loader). Primitive arguments must be + * enclosing class' class loader). Primitive arguments must be * either assignment compatible with the argument type or must be * convertible to the argument type without loss of information. * If the method being called accepts a variable number of arguments, @@ -335,7 +335,7 @@ * @throws InvalidTypeException If the arguments do not meet this requirement -- * Object arguments must be assignment compatible with the argument * type. This implies that the argument type must be - * loaded through the enclosing class's class loader. + * loaded through the enclosing class' class loader. * Primitive arguments must be either assignment compatible with the * argument type or must be convertible to the argument type without loss * of information. See JLS section 5.2 for more information on assignment
--- a/src/share/classes/com/sun/jdi/InterfaceType.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/jdi/InterfaceType.java Mon Oct 27 14:09:55 2014 -0700 @@ -79,4 +79,123 @@ * If none exist, returns a zero length List. */ List<ClassType> implementors(); + + /** + * Invokes the specified static {@link Method} in the + * target VM. The + * specified method must be defined in this interface. + * The method must be a static method + * but not a static initializer. + * <p> + * The method invocation will occur in the specified thread. + * Method invocation can occur only if the specified thread + * has been suspended by an event which occurred in that thread. + * Method invocation is not supported + * when the target VM has been suspended through + * {@link VirtualMachine#suspend} or when the specified thread + * is suspended through {@link ThreadReference#suspend}. + * <p> + * The specified method is invoked with the arguments in the specified + * argument list. The method invocation is synchronous; this method + * does not return until the invoked method returns in the target VM. + * If the invoked method throws an exception, this method will throw + * an {@link InvocationException} which contains a mirror to the exception + * object thrown. + * <p> + * Object arguments must be assignment compatible with the argument type + * (This implies that the argument type must be loaded through the + * enclosing class' class loader). Primitive arguments must be + * either assignment compatible with the argument type or must be + * convertible to the argument type without loss of information. + * If the method being called accepts a variable number of arguments, + * then the last argument type is an array of some component type. + * The argument in the matching position can be omitted, or can be null, + * an array of the same component type, or an argument of the + * component type followed by any number of other arguments of the same + * type. If the argument is omitted, then a 0 length array of the + * component type is passed. The component type can be a primitive type. + * Autoboxing is not supported. + * + * See Section 5.2 of + * <cite>The Java™ Language Specification</cite> + * for more information on assignment compatibility. + * <p> + * By default, all threads in the target VM are resumed while + * the method is being invoked if they were previously + * suspended by an event or by {@link VirtualMachine#suspend} or + * {@link ThreadReference#suspend}. This is done to prevent the deadlocks + * that will occur if any of the threads own monitors + * that will be needed by the invoked method. + * Note, however, that this implicit resume acts exactly like + * {@link ThreadReference#resume}, so if the thread's suspend + * count is greater than 1, it will remain in a suspended state + * during the invocation and thus a deadlock could still occur. + * By default, when the invocation completes, + * all threads in the target VM are suspended, regardless their state + * before the invocation. + * It is possible that + * breakpoints or other events might occur during the invocation. + * This can cause deadlocks as described above. It can also cause a deadlock + * if invokeMethod is called from the client's event handler thread. In this + * case, this thread will be waiting for the invokeMethod to complete and + * won't read the EventSet that comes in for the new event. If this + * new EventSet is SUSPEND_ALL, then a deadlock will occur because no + * one will resume the EventSet. To avoid this, all EventRequests should + * be disabled before doing the invokeMethod, or the invokeMethod should + * not be done from the client's event handler thread. + * <p> + * The resumption of other threads during the invocation can be prevented + * by specifying the {@link #INVOKE_SINGLE_THREADED} + * bit flag in the <code>options</code> argument; however, + * there is no protection against or recovery from the deadlocks + * described above, so this option should be used with great caution. + * Only the specified thread will be resumed (as described for all + * threads above). Upon completion of a single threaded invoke, the invoking thread + * will be suspended once again. Note that any threads started during + * the single threaded invocation will not be suspended when the + * invocation completes. + * <p> + * If the target VM is disconnected during the invoke (for example, through + * {@link VirtualMachine#dispose}) the method invocation continues. + * + * @param thread the thread in which to invoke. + * @param method the {@link Method} to invoke. + * @param arguments the list of {@link Value} arguments bound to the + * invoked method. Values from the list are assigned to arguments + * in the order they appear in the method signature. + * @param options the integer bit flag options. + * @return a {@link Value} mirror of the invoked method's return value. + * @throws java.lang.IllegalArgumentException if the method is not + * a member of this interface, if the size of the argument list + * does not match the number of declared arguments for the method, or + * if the method is not static or is a static initializer. + * @throws {@link InvalidTypeException} if any argument in the + * argument list is not assignable to the corresponding method argument + * type. + * @throws ClassNotLoadedException if any argument type has not yet been loaded + * through the appropriate class loader. + * @throws IncompatibleThreadStateException if the specified thread has not + * been suspended by an event. + * @throws InvocationException if the method invocation resulted in + * an exception in the target VM. + * @throws InvalidTypeException If the arguments do not meet this requirement -- + * Object arguments must be assignment compatible with the argument + * type. This implies that the argument type must be + * loaded through the enclosing class' class loader. + * Primitive arguments must be either assignment compatible with the + * argument type or must be convertible to the argument type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}. + * + * @since 1.8 + */ + default Value invokeMethod(ThreadReference thread, Method method, + List<? extends Value> arguments, int options) + throws InvalidTypeException, + ClassNotLoadedException, + IncompatibleThreadStateException, + InvocationException { + throw new UnsupportedOperationException(); + } }
--- a/src/share/classes/com/sun/jdi/Method.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/jdi/Method.java Mon Oct 27 14:09:55 2014 -0700 @@ -138,6 +138,18 @@ boolean isAbstract(); /** + * Determine if this method is a default method + * + * @return <code>true</code> if the method is declared default; + * false otherwise + * + * @since 1.8 + */ + default boolean isDefault() { + throw new UnsupportedOperationException(); + } + + /** * Determine if this method is synchronized. * * @return <code>true</code> if the method is declared synchronized;
--- a/src/share/classes/com/sun/jdi/ObjectReference.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/jdi/ObjectReference.java Mon Oct 27 14:09:55 2014 -0700 @@ -194,10 +194,10 @@ * {@link #INVOKE_NONVIRTUAL} bit flag in the <code>options</code> * argument. If this flag is set, the specified method is invoked * whether or not it is overridden for this object's runtime type. - * The method, in this case, must not belong to an interface and - * must not be abstract. This option is useful for performing method - * invocations like those done with the <code>super</code> keyword in - * the Java programming language. + * The method, in this case, must have an implementation, either in a class + * or an interface. This option is useful for performing method invocations + * like those done with the <code>super</code> keyword in the Java programming + * language. * <p> * By default, all threads in the target VM are resumed while * the method is being invoked if they were previously @@ -246,10 +246,10 @@ * @return a {@link Value} mirror of the invoked method's return value. * @throws java.lang.IllegalArgumentException if the method is not * a member of this object's class, if the size of the argument list - * does not match the number of declared arguemnts for the method, + * does not match the number of declared arguments for the method, * if the method is a constructor or static intializer, or * if {@link #INVOKE_NONVIRTUAL} is specified and the method is - * either abstract or an interface member. + * either abstract or a non-default interface member. * @throws {@link InvalidTypeException} if any argument in the * argument list is not assignable to the corresponding method argument * type.
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/jndi/ldap/Connection.java Mon Oct 27 14:09:55 2014 -0700 @@ -111,6 +111,7 @@ private static final boolean debug = false; private static final int dump = 0; // > 0 r, > 1 rw + public static final long DEFAULT_READ_TIMEOUT_MILLIS = 15 * 1000; // 15 second timeout; final private Thread worker; // Initialized in constructor @@ -460,7 +461,7 @@ // available ldr.wait(readTimeout); } else { - ldr.wait(15 * 1000); // 15 second timeout + ldr.wait(DEFAULT_READ_TIMEOUT_MILLIS); } waited = true; } else {
--- a/src/share/classes/com/sun/security/ntlm/Client.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/security/ntlm/Client.java Mon Oct 27 14:09:55 2014 -0700 @@ -46,7 +46,7 @@ final private String hostname; final private String username; - private String domain; // might be updated by Type 2 msg + private String domain; private byte[] pw1, pw2; /** @@ -82,7 +82,7 @@ } this.hostname = hostname; this.username = username; - this.domain = domain; + this.domain = domain == null ? "" : domain; this.pw1 = getP1(password); this.pw2 = getP2(password); debug("NTLM Client: (h,u,t,version(v)) = (%s,%s,%s,%s(%s))\n", @@ -95,19 +95,13 @@ */ public byte[] type1() { Writer p = new Writer(1, 32); - int flags = 0x8203; - if (hostname != null) { - flags |= 0x2000; - } - if (domain != null) { - flags |= 0x1000; - } + // Negotiate always sign, Negotiate NTLM, + // Request Target, Negotiate OEM, Negotiate unicode + int flags = 0x8207; if (v != Version.NTLM) { flags |= 0x80000; } p.writeInt(12, flags); - p.writeSecurityBuffer(24, hostname, false); - p.writeSecurityBuffer(16, domain, false); debug("NTLM Client: Type 1 created\n"); debug(p.getBytes()); return p.getBytes(); @@ -133,13 +127,10 @@ byte[] challenge = r.readBytes(24, 8); int inputFlags = r.readInt(20); boolean unicode = (inputFlags & 1) == 1; - String domainFromServer = r.readSecurityBuffer(12, unicode); - if (domainFromServer != null) { - domain = domainFromServer; - } - if (domain == null) { - domain = ""; - } + + // IE uses domainFromServer to generate an alist if server has not + // provided one. Firefox/WebKit do not. Neither do we. + //String domainFromServer = r.readSecurityBuffer(12, unicode); int flags = 0x88200 | (inputFlags & 3); Writer p = new Writer(3, 64); @@ -163,7 +154,9 @@ if (writeLM) lm = calcV2(nthash, username.toUpperCase(Locale.US)+domain, nonce, challenge); if (writeNTLM) { - byte[] alist = type2.length > 48 ? + // Some client create a alist even if server does not send + // one: (i16)2 (i16)len target_in_unicode (i16)0 (i16) 0 + byte[] alist = ((inputFlags & 0x800000) != 0) ? r.readSecurityBuffer(40) : new byte[0]; byte[] blob = new byte[32+alist.length]; System.arraycopy(new byte[]{1,1,0,0,0,0,0,0}, 0, blob, 0, 8);
--- a/src/share/classes/com/sun/security/ntlm/Server.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/security/ntlm/Server.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,3 +1,4 @@ + /* * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -92,7 +93,9 @@ debug("NTLM Server: Type 1 received\n"); if (type1 != null) debug(type1); Writer p = new Writer(2, 32); - int flags = 0x80205; + // Negotiate NTLM2 Key, Target Type Domain, + // Negotiate NTLM, Request Target, Negotiate unicode + int flags = 0x90205; p.writeSecurityBuffer(12, domain, true); p.writeInt(20, flags); p.writeBytes(24, nonce); @@ -127,8 +130,9 @@ "Wrong domain: " + incomingDomain + " vs " + domain); // Needed? }*/ + boolean verified = false; - char[] password = getPassword(domain, username); + char[] password = getPassword(incomingDomain, username); if (password == null) { throw new NTLMException(NTLMException.USER_UNKNOWN, "Unknown user"); @@ -179,6 +183,8 @@ } } if (incomingNTLM.length > 0) { + // We didn't sent alist in type2(), so there + // is nothing to check here. byte[] clientBlob = Arrays.copyOfRange( incomingNTLM, 16, incomingNTLM.length); byte[] ntlmresponse = calcV2(nthash,
--- a/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java Mon Oct 27 14:09:55 2014 -0700 @@ -160,9 +160,17 @@ } } try { + String name = ncb.getName(); + if (name == null) { + name = authzid; + } + String domain = dcb.getText(); + if (domain == null) { + domain = serverName; + } client = new Client(version, hostname, - ncb.getName(), - dcb.getText(), + name, + domain, pcb.getPassword()); } catch (NTLMException ne) { throw new SaslException(
--- a/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java Mon Oct 27 14:09:55 2014 -0700 @@ -141,8 +141,10 @@ server = new Server(version, domain) { public char[] getPassword(String ntdomain, String username) { try { - RealmCallback rcb = new RealmCallback( - "Domain: ", ntdomain); + RealmCallback rcb = + (ntdomain == null || ntdomain.isEmpty()) + ? new RealmCallback("Domain: ") + : new RealmCallback("Domain: ", ntdomain); NameCallback ncb = new NameCallback( "Name: ", username); PasswordCallback pcb = new PasswordCallback(
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java Mon Oct 27 14:09:55 2014 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.attach; + +import java.io.IOException; + +/** + * Exception type to signal that an attach operation failed in the target VM. + * + * <p> This exception can be thrown by the various operations of + * {@link com.sun.tools.attach.VirtualMachine} when the operation + * fails in the target VM. If there is a communication error, + * a regular IOException will be thrown. + * + * @since 1.9 + */ +@jdk.Exported +public class AttachOperationFailedException extends IOException { + + private static final long serialVersionUID = 2140308168167478043L; + + /** + * Constructs an <code>AttachOperationFailedException</code> with + * the specified detail message. + * + * @param s the detail message. + */ + public AttachOperationFailedException(String message) { + super(message); + } +}
--- a/src/share/classes/com/sun/tools/attach/VirtualMachine.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/attach/VirtualMachine.java Mon Oct 27 14:09:55 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,16 +76,10 @@ * // attach to target VM * VirtualMachine vm = VirtualMachine.attach("2177"); * - * // get system properties in target VM - * Properties props = vm.getSystemProperties(); - * - * // construct path to management agent - * String home = props.getProperty("java.home"); - * String agent = home + File.separator + "lib" + File.separator - * + "management-agent.jar"; - * - * // load agent into target VM - * vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000"); + * // start management agent + * Properties props = new Properties(); + * props.put("com.sun.management.jmxremote.port", "5000"); + * vm.startManagementAgent(props); * * // detach * vm.detach(); @@ -93,9 +87,9 @@ * </pre> * * <p> In this example we attach to a Java virtual machine that is identified by - * the process identifier <code>2177</code>. The system properties from the target - * VM are then used to construct the path to a <i>management agent</i> which is then - * loaded into the target VM. Once loaded the client detaches from the target VM. </p> + * the process identifier <code>2177</code>. Then the JMX management agent is + * started in the target process using the supplied arguments. Finally, the + * client detaches from the target VM. </p> * * <p> A VirtualMachine is safe for use by multiple concurrent threads. </p> * @@ -564,8 +558,15 @@ * * @return The system properties * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * * @throws IOException - * If an I/O error occurs + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. * * @see java.lang.System#getProperties * @see #loadAgentLibrary @@ -591,12 +592,81 @@ * * @return The agent properties * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * * @throws IOException - * If an I/O error occurs + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. */ public abstract Properties getAgentProperties() throws IOException; /** + * Starts the JMX management agent in the target virtual machine. + * + * <p> The configuration properties are the same as those specified on + * the command line when starting the JMX management agent. In the same + * way as on the command line, you need to specify at least the + * {@code com.sun.management.jmxremote.port} property. + * + * <p> See the online documentation for <a + * href="../../../../../../../../technotes/guides/management/agent.html"> + * Monitoring and Management Using JMX Technology</a> for further details. + * + * @param agentProperties + * A Properties object containing the configuration properties + * for the agent. + * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * + * @throws IOException + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. + * + * @throws IllegalArgumentException + * If keys or values in agentProperties are invalid. + * + * @throws NullPointerException + * If agentProperties is null. + * + * @since 1.8 + */ + public abstract void startManagementAgent(Properties agentProperties) throws IOException; + + /** + * Starts the local JMX management agent in the target virtual machine. + * + * <p> See the online documentation for <a + * href="../../../../../../../../technotes/guides/management/agent.html"> + * Monitoring and Management Using JMX Technology</a> for further details. + * + * @return The String representation of the local connector's service address. + * The value can be parsed by the + * {@link javax.management.remote.JMXServiceURL#JMXServiceURL(String)} + * constructor. + * + * @throws AttachOperationFailedException + * If the target virtual machine is unable to complete the + * attach operation. A more specific error message will be + * given by {@link AttachOperationFailedException#getMessage()}. + * + * @throws IOException + * If an I/O error occurs, a communication error for example, + * that cannot be identified as an error to indicate that the + * operation failed in the target VM. + * + * @since 1.8 + */ + public abstract String startLocalManagementAgent() throws IOException; + + /** * Returns a hash-code value for this VirtualMachine. The hash * code is based upon the VirtualMachine's components, and satifies * the general contract of the {@link java.lang.Object#hashCode()
--- a/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Mon Oct 27 14:09:55 2014 -0700 @@ -559,6 +559,9 @@ } else if (refType instanceof ClassType) { ClassType clazz = (ClassType)refType; return jdiValue = clazz.invokeMethod(thread, matchingMethod, methodArguments, 0); + } else if (refType instanceof InterfaceType) { + InterfaceType iface = (InterfaceType)refType; + return jdiValue = iface.invokeMethod(thread, matchingMethod, methodArguments, 0); } else { throw new InvalidTypeException("Cannot invoke static method on " + refType.name());
--- a/src/share/classes/com/sun/tools/jdi/ArrayTypeImpl.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/jdi/ArrayTypeImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.Map; +import java.util.Set; public class ArrayTypeImpl extends ReferenceTypeImpl implements ArrayType @@ -61,7 +62,8 @@ return findType(componentSignature()); } - void addVisibleMethods(Map<String, Method> map) { + @Override + void addVisibleMethods(Map<String, Method> map, Set<InterfaceType> seenInterfaces) { // arrays don't have methods }
--- a/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -29,9 +29,27 @@ import java.util.*; -public class ClassTypeImpl extends ReferenceTypeImpl +final public class ClassTypeImpl extends InvokableTypeImpl implements ClassType { + private static class IResult implements InvocationResult { + final private JDWP.ClassType.InvokeMethod rslt; + + public IResult(JDWP.ClassType.InvokeMethod rslt) { + this.rslt = rslt; + } + + @Override + public ObjectReferenceImpl getException() { + return rslt.exception; + } + + @Override + public ValueImpl getResult() { + return rslt.returnValue; + } + } + private boolean cachedSuperclass = false; private ClassType superclass = null; private int lastLine = -1; @@ -65,6 +83,7 @@ return superclass; } + @Override public List<InterfaceType> interfaces() { if (interfaces == null) { interfaces = getInterfaces(); @@ -72,26 +91,9 @@ return interfaces; } - void addInterfaces(List<InterfaceType> list) { - List<InterfaceType> immediate = interfaces(); - list.addAll(interfaces()); - - Iterator<InterfaceType> iter = immediate.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - interfaze.addSuperinterfaces(list); - } - - ClassTypeImpl superclass = (ClassTypeImpl)superclass(); - if (superclass != null) { - superclass.addInterfaces(list); - } - } - - public List<InterfaceType> allInterfaces() { - List<InterfaceType> all = new ArrayList<InterfaceType>(); - addInterfaces(all); - return all; + @Override + public List<InterfaceType> allInterfaces() { + return getAllInterfaces(); } public List<ClassType> subclasses() { @@ -159,28 +161,6 @@ } } - PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, - final MethodImpl method, - final ValueImpl[] args, - final int options) { - CommandSender sender = - new CommandSender() { - public PacketStream send() { - return JDWP.ClassType.InvokeMethod.enqueueCommand( - vm, ClassTypeImpl.this, thread, - method.ref(), args, options); - } - }; - - PacketStream stream; - if ((options & INVOKE_SINGLE_THREADED) != 0) { - stream = thread.sendResumingCommand(sender); - } else { - stream = vm.sendResumingCommand(sender); - } - return stream; - } - PacketStream sendNewInstanceCommand(final ThreadReferenceImpl thread, final MethodImpl method, final ValueImpl[] args, @@ -203,52 +183,6 @@ return stream; } - public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, - List<? extends Value> origArguments, int options) - throws InvalidTypeException, - ClassNotLoadedException, - IncompatibleThreadStateException, - InvocationException { - validateMirror(threadIntf); - validateMirror(methodIntf); - validateMirrorsOrNulls(origArguments); - - MethodImpl method = (MethodImpl)methodIntf; - ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf; - - validateMethodInvocation(method); - - List<? extends Value> arguments = method.validateAndPrepareArgumentsForInvoke(origArguments); - - ValueImpl[] args = arguments.toArray(new ValueImpl[0]); - JDWP.ClassType.InvokeMethod ret; - try { - PacketStream stream = - sendInvokeCommand(thread, method, args, options); - ret = JDWP.ClassType.InvokeMethod.waitForReply(vm, stream); - } catch (JDWPException exc) { - if (exc.errorCode() == JDWP.Error.INVALID_THREAD) { - throw new IncompatibleThreadStateException(); - } else { - throw exc.toJDIException(); - } - } - - /* - * There is an implict VM-wide suspend at the conclusion - * of a normal (non-single-threaded) method invoke - */ - if ((options & INVOKE_SINGLE_THREADED) == 0) { - vm.notifySuspend(); - } - - if (ret.exception != null) { - throw new InvocationException(ret.exception); - } else { - return ret.returnValue; - } - } - public ObjectReference newInstance(ThreadReference threadIntf, Method methodIntf, List<? extends Value> origArguments, @@ -311,58 +245,6 @@ return method; } - public List<Method> allMethods() { - ArrayList<Method> list = new ArrayList<Method>(methods()); - - ClassType clazz = superclass(); - while (clazz != null) { - list.addAll(clazz.methods()); - clazz = clazz.superclass(); - } - - /* - * Avoid duplicate checking on each method by iterating through - * duplicate-free allInterfaces() rather than recursing - */ - for (InterfaceType interfaze : allInterfaces()) { - list.addAll(interfaze.methods()); - } - - return list; - } - - List<ReferenceType> inheritedTypes() { - List<ReferenceType> inherited = new ArrayList<ReferenceType>(); - if (superclass() != null) { - inherited.add(0, (ReferenceType)superclass()); /* insert at front */ - } - for (ReferenceType rt : interfaces()) { - inherited.add(rt); - } - return inherited; - } - - void validateMethodInvocation(Method method) - throws InvalidTypeException, - InvocationException { - /* - * Method must be in this class or a superclass. - */ - ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType(); - if (!declType.isAssignableFrom(this)) { - throw new IllegalArgumentException("Invalid method"); - } - - /* - * Method must be a static and not a static initializer - */ - if (!method.isStatic()) { - throw new IllegalArgumentException("Cannot invoke instance method on a class type"); - } else if (method.isStaticInitializer()) { - throw new IllegalArgumentException("Cannot invoke static initializer"); - } - } - void validateConstructorInvocation(Method method) throws InvalidTypeException, InvocationException { @@ -382,47 +264,33 @@ } } - void addVisibleMethods(Map<String, Method> methodMap) { - /* - * Add methods from - * parent types first, so that the methods in this class will - * overwrite them in the hash table - */ - - Iterator<InterfaceType> iter = interfaces().iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - interfaze.addVisibleMethods(methodMap); - } - - ClassTypeImpl clazz = (ClassTypeImpl)superclass(); - if (clazz != null) { - clazz.addVisibleMethods(methodMap); - } - - addToMethodMap(methodMap, methods()); - } - - boolean isAssignableTo(ReferenceType type) { - ClassTypeImpl superclazz = (ClassTypeImpl)superclass(); - if (this.equals(type)) { - return true; - } else if ((superclazz != null) && superclazz.isAssignableTo(type)) { - return true; - } else { - List<InterfaceType> interfaces = interfaces(); - Iterator<InterfaceType> iter = interfaces.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - if (interfaze.isAssignableTo(type)) { - return true; - } - } - return false; - } - } public String toString() { return "class " + name() + " (" + loaderString() + ")"; } + + @Override + CommandSender getInvokeMethodSender(ThreadReferenceImpl thread, + MethodImpl method, + ValueImpl[] args, + int options) { + return () -> + JDWP.ClassType.InvokeMethod.enqueueCommand(vm, + ClassTypeImpl.this, + thread, + method.ref(), + args, + options); + } + + @Override + InvocationResult waitForReply(PacketStream stream) throws JDWPException { + return new IResult(JDWP.ClassType.InvokeMethod.waitForReply(vm, stream)); + } + + @Override + boolean canInvoke(Method method) { + // Method must be in this class or a superclass. + return ((ReferenceTypeImpl)method.declaringType()).isAssignableFrom(this); + } }
--- a/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -29,13 +29,31 @@ import java.util.List; import java.util.ArrayList; -import java.util.Map; -import java.util.Iterator; import java.util.Collections; +import java.util.Set; import java.lang.ref.SoftReference; -public class InterfaceTypeImpl extends ReferenceTypeImpl - implements InterfaceType { +final public class InterfaceTypeImpl extends InvokableTypeImpl + implements InterfaceType { + + private static class IResult implements InvocationResult { + final private JDWP.InterfaceType.InvokeMethod rslt; + + public IResult(JDWP.InterfaceType.InvokeMethod rslt) { + this.rslt = rslt; + } + + @Override + public ObjectReferenceImpl getException() { + return rslt.exception; + } + + @Override + public ValueImpl getResult() { + return rslt.returnValue; + } + + } private SoftReference<List<InterfaceType>> superinterfacesRef = null; @@ -80,98 +98,6 @@ return implementors; } - void addVisibleMethods(Map<String, Method> methodMap) { - /* - * Add methods from - * parent types first, so that the methods in this class will - * overwrite them in the hash table - */ - - for (InterfaceType interfaze : superinterfaces()) { - ((InterfaceTypeImpl)interfaze).addVisibleMethods(methodMap); - } - - addToMethodMap(methodMap, methods()); - } - - public List<Method> allMethods() { - ArrayList<Method> list = new ArrayList<Method>(methods()); - - /* - * It's more efficient if don't do this - * recursively. - */ - for (InterfaceType interfaze : allSuperinterfaces()) { - list.addAll(interfaze.methods()); - } - - return list; - } - - List<InterfaceType> allSuperinterfaces() { - ArrayList<InterfaceType> list = new ArrayList<InterfaceType>(); - addSuperinterfaces(list); - return list; - } - - void addSuperinterfaces(List<InterfaceType> list) { - /* - * This code is a little strange because it - * builds the list with a more suitable order than the - * depth-first approach a normal recursive solution would - * take. Instead, all direct superinterfaces precede all - * indirect ones. - */ - - /* - * Get a list of direct superinterfaces that's not already in the - * list being built. - */ - List<InterfaceType> immediate = new ArrayList<InterfaceType>(superinterfaces()); - Iterator<InterfaceType> iter = immediate.iterator(); - while (iter.hasNext()) { - InterfaceType interfaze = iter.next(); - if (list.contains(interfaze)) { - iter.remove(); - } - } - - /* - * Add all new direct superinterfaces - */ - list.addAll(immediate); - - /* - * Recurse for all new direct superinterfaces. - */ - iter = immediate.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); - interfaze.addSuperinterfaces(list); - } - } - - boolean isAssignableTo(ReferenceType type) { - - // Exact match? - if (this.equals(type)) { - return true; - } else { - // Try superinterfaces. - for (InterfaceType interfaze : superinterfaces()) { - if (((InterfaceTypeImpl)interfaze).isAssignableTo(type)) { - return true; - } - } - - return false; - } - } - - List<InterfaceType> inheritedTypes() { - return superinterfaces(); - } - public boolean isInitialized() { return isPrepared(); } @@ -179,4 +105,39 @@ public String toString() { return "interface " + name() + " (" + loaderString() + ")"; } -} + + @Override + InvocationResult waitForReply(PacketStream stream) throws JDWPException { + return new IResult(JDWP.InterfaceType.InvokeMethod.waitForReply(vm, stream)); + } + + @Override + CommandSender getInvokeMethodSender(final ThreadReferenceImpl thread, + final MethodImpl method, + final ValueImpl[] args, + final int options) { + return () -> + JDWP.InterfaceType.InvokeMethod.enqueueCommand(vm, + InterfaceTypeImpl.this, + thread, + method.ref(), + args, + options); + } + + @Override + ClassType superclass() { + return null; + } + + @Override + List<InterfaceType> interfaces() { + return superinterfaces(); + } + + @Override + boolean canInvoke(Method method) { + // method must be directly in this interface + return this.equals(method.declaringType()); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.jdi; + +import com.sun.jdi.ClassNotLoadedException; +import com.sun.jdi.ClassType; +import com.sun.jdi.IncompatibleThreadStateException; +import com.sun.jdi.InterfaceType; +import com.sun.jdi.InvalidTypeException; +import com.sun.jdi.InvocationException; +import com.sun.jdi.Method; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.ThreadReference; +import com.sun.jdi.Value; +import com.sun.jdi.VirtualMachine; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A supertype for ReferenceTypes allowing method invocations + */ +abstract class InvokableTypeImpl extends ReferenceTypeImpl { + /** + * The invocation result wrapper + * It is necessary because both ClassType and InterfaceType + * use their own type to represent the invocation result + */ + static interface InvocationResult { + ObjectReferenceImpl getException(); + ValueImpl getResult(); + } + + InvokableTypeImpl(VirtualMachine aVm, long aRef) { + super(aVm, aRef); + } + + /** + * Method invocation support. + * Shared by ClassType and InterfaceType + * @param threadIntf the thread in which to invoke. + * @param methodIntf method the {@link Method} to invoke. + * @param origArguments the list of {@link Value} arguments bound to the + * invoked method. Values from the list are assigned to arguments + * in the order they appear in the method signature. + * @param options the integer bit flag options. + * @return a {@link Value} mirror of the invoked method's return value. + * @throws java.lang.IllegalArgumentException if the method is not + * a member of this type, if the size of the argument list + * does not match the number of declared arguments for the method, or + * if the method is not static or is a static initializer. + * @throws {@link InvalidTypeException} if any argument in the + * argument list is not assignable to the corresponding method argument + * type. + * @throws ClassNotLoadedException if any argument type has not yet been loaded + * through the appropriate class loader. + * @throws IncompatibleThreadStateException if the specified thread has not + * been suspended by an event. + * @throws InvocationException if the method invocation resulted in + * an exception in the target VM. + * @throws InvalidTypeException If the arguments do not meet this requirement -- + * Object arguments must be assignment compatible with the argument + * type. This implies that the argument type must be + * loaded through the enclosing class's class loader. + * Primitive arguments must be either assignment compatible with the + * argument type or must be convertible to the argument type without loss + * of information. See JLS section 5.2 for more information on assignment + * compatibility. + * @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}. + */ + final public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, + List<? extends Value> origArguments, int options) + throws InvalidTypeException, + ClassNotLoadedException, + IncompatibleThreadStateException, + InvocationException { + validateMirror(threadIntf); + validateMirror(methodIntf); + validateMirrorsOrNulls(origArguments); + MethodImpl method = (MethodImpl) methodIntf; + ThreadReferenceImpl thread = (ThreadReferenceImpl) threadIntf; + validateMethodInvocation(method); + List<? extends Value> arguments = method.validateAndPrepareArgumentsForInvoke(origArguments); + ValueImpl[] args = arguments.toArray(new ValueImpl[0]); + InvocationResult ret; + try { + PacketStream stream = sendInvokeCommand(thread, method, args, options); + ret = waitForReply(stream); + } catch (JDWPException exc) { + if (exc.errorCode() == JDWP.Error.INVALID_THREAD) { + throw new IncompatibleThreadStateException(); + } else { + throw exc.toJDIException(); + } + } + /* + * There is an implict VM-wide suspend at the conclusion + * of a normal (non-single-threaded) method invoke + */ + if ((options & ClassType.INVOKE_SINGLE_THREADED) == 0) { + vm.notifySuspend(); + } + if (ret.getException() != null) { + throw new InvocationException(ret.getException()); + } else { + return ret.getResult(); + } + } + + @Override + boolean isAssignableTo(ReferenceType type) { + ClassTypeImpl superclazz = (ClassTypeImpl) superclass(); + if (this.equals(type)) { + return true; + } else if ((superclazz != null) && superclazz.isAssignableTo(type)) { + return true; + } else { + List<InterfaceType> interfaces = interfaces(); + Iterator<InterfaceType> iter = interfaces.iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); + if (interfaze.isAssignableTo(type)) { + return true; + } + } + return false; + } + } + + @Override + final void addVisibleMethods(Map<String, Method> methodMap, Set<InterfaceType> seenInterfaces) { + /* + * Add methods from + * parent types first, so that the methods in this class will + * overwrite them in the hash table + */ + Iterator<InterfaceType> iter = interfaces().iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); + if (!seenInterfaces.contains(interfaze)) { + interfaze.addVisibleMethods(methodMap, seenInterfaces); + seenInterfaces.add(interfaze); + } + } + ClassTypeImpl clazz = (ClassTypeImpl) superclass(); + if (clazz != null) { + clazz.addVisibleMethods(methodMap, seenInterfaces); + } + addToMethodMap(methodMap, methods()); + } + + final void addInterfaces(List<InterfaceType> list) { + List<InterfaceType> immediate = interfaces(); + list.addAll(interfaces()); + Iterator<InterfaceType> iter = immediate.iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); + interfaze.addInterfaces(list); + } + ClassTypeImpl superclass = (ClassTypeImpl) superclass(); + if (superclass != null) { + superclass.addInterfaces(list); + } + } + + /** + * Returns all the implemented interfaces recursively + * @return A list of all the implemented interfaces (recursively) + */ + final List<InterfaceType> getAllInterfaces() { + List<InterfaceType> all = new ArrayList<>(); + addInterfaces(all); + return all; + } + + /** + * Shared implementation of {@linkplain ClassType#allMethods()} and + * {@linkplain InterfaceType#allMethods()} + * @return A list of all methods (recursively) + */ + public final List<Method> allMethods() { + ArrayList<Method> list = new ArrayList<>(methods()); + ClassType clazz = superclass(); + while (clazz != null) { + list.addAll(clazz.methods()); + clazz = clazz.superclass(); + } + /* + * Avoid duplicate checking on each method by iterating through + * duplicate-free allInterfaces() rather than recursing + */ + for (InterfaceType interfaze : getAllInterfaces()) { + list.addAll(interfaze.methods()); + } + return list; + } + + @Override + final List<ReferenceType> inheritedTypes() { + List<ReferenceType> inherited = new ArrayList<>(); + if (superclass() != null) { + inherited.add(0, superclass()); /* insert at front */ + } + for (ReferenceType rt : interfaces()) { + inherited.add(rt); + } + return inherited; + } + + private PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, + final MethodImpl method, + final ValueImpl[] args, + final int options) { + CommandSender sender = getInvokeMethodSender(thread, method, args, options); + PacketStream stream; + if ((options & ClassType.INVOKE_SINGLE_THREADED) != 0) { + stream = thread.sendResumingCommand(sender); + } else { + stream = vm.sendResumingCommand(sender); + } + return stream; + } + + private void validateMethodInvocation(Method method) + throws InvalidTypeException, + InvocationException { + if (!canInvoke(method)) { + throw new IllegalArgumentException("Invalid method"); + } + /* + * Method must be a static and not a static initializer + */ + if (!method.isStatic()) { + throw new IllegalArgumentException("Cannot invoke instance method on a class/interface type"); + } else if (method.isStaticInitializer()) { + throw new IllegalArgumentException("Cannot invoke static initializer"); + } + } + + /** + * A subclass will provide specific {@linkplain CommandSender} + * @param thread the current invocation thread + * @param method the method to invoke + * @param args the arguments to pass to the method + * @param options the integer bit flag options + * @return the specific {@literal CommandSender} instance + */ + abstract CommandSender getInvokeMethodSender(ThreadReferenceImpl thread, + MethodImpl method, + ValueImpl[] args, + int options); + + /** + * Waits for the reply to the last sent command + * @param stream the stream to listen for the reply on + * @return the {@linkplain InvocationResult} instance + * @throws JDWPException when something goes wrong in JDWP + */ + abstract InvocationResult waitForReply(PacketStream stream) throws JDWPException; + + /** + * Get the {@linkplain ReferenceType} superclass + * @return the superclass or null + */ + abstract ClassType superclass(); + + /** + * Get the implemented/extended interfaces + * @return the list of implemented/extended interfaces + */ + abstract List<InterfaceType> interfaces(); + + /** + * Checks the provided method whether it can be invoked + * @param method the method to check + * @return {@code TRUE} if the implementation knows how to invoke the method, + * {@code FALSE} otherwise + */ + abstract boolean canInvoke(Method method); +}
--- a/src/share/classes/com/sun/tools/jdi/MethodImpl.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/jdi/MethodImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -187,6 +187,13 @@ return isModifierSet(VMModifiers.ABSTRACT); } + public boolean isDefault() { + return !isModifierSet(VMModifiers.ABSTRACT) && + !isModifierSet(VMModifiers.STATIC) && + !isModifierSet(VMModifiers.PRIVATE) && + declaringType() instanceof InterfaceType; + } + public boolean isSynchronized() { return isModifierSet(VMModifiers.SYNCHRONIZED); }
--- a/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -277,7 +277,6 @@ void validateMethodInvocation(Method method, int options) throws InvalidTypeException, InvocationException { - /* * Method must be in this object's class, a superclass, or * implemented interface @@ -287,6 +286,19 @@ throw new IllegalArgumentException("Invalid method"); } + if (declType instanceof ClassTypeImpl) { + validateClassMethodInvocation(method, options); + } else if (declType instanceof InterfaceTypeImpl) { + validateIfaceMethodInvocation(method, options); + } else { + throw new InvalidTypeException(); + } + } + + void validateClassMethodInvocation(Method method, int options) + throws InvalidTypeException, + InvocationException { + ClassTypeImpl clazz = invokableReferenceType(method); /* @@ -300,9 +312,7 @@ * For nonvirtual invokes, method must have a body */ if ((options & INVOKE_NONVIRTUAL) != 0) { - if (method.declaringType() instanceof InterfaceType) { - throw new IllegalArgumentException("Interface method"); - } else if (method.isAbstract()) { + if (method.isAbstract()) { throw new IllegalArgumentException("Abstract method"); } } @@ -324,7 +334,7 @@ */ Method invoker = clazz.concreteMethodByName(method.name(), method.signature()); - // isAssignableFrom check above guarantees non-null + // invoker is supposed to be non-null under normal circumstances invokedClass = (ClassTypeImpl)invoker.declaringType(); } /* The above code is left over from previous versions. @@ -332,6 +342,17 @@ */ } + void validateIfaceMethodInvocation(Method method, int options) + throws InvalidTypeException, + InvocationException { + /* + * Only default methods allowed for nonvirtual invokes + */ + if (!method.isDefault()) { + throw new IllegalArgumentException("Not a default method"); + } + } + PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, final ClassTypeImpl refType, final MethodImpl method, @@ -370,7 +391,10 @@ ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf; if (method.isStatic()) { - if (referenceType() instanceof ClassType) { + if (referenceType() instanceof InterfaceType) { + InterfaceType type = (InterfaceType)referenceType(); + return type.invokeMethod(thread, method, origArguments, options); + } else if (referenceType() instanceof ClassType) { ClassType type = (ClassType)referenceType(); return type.invokeMethod(thread, method, origArguments, options); } else {
--- a/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/jdi/ReferenceTypeImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -511,7 +511,7 @@ methodMap.put(method.name().concat(method.signature()), method); } - abstract void addVisibleMethods(Map<String, Method> methodMap); + abstract void addVisibleMethods(Map<String, Method> methodMap, Set<InterfaceType> seenInterfaces); public List<Method> visibleMethods() { /* @@ -520,7 +520,7 @@ * concatenation of name and signature. */ Map<String, Method> map = new HashMap<String, Method>(); - addVisibleMethods(map); + addVisibleMethods(map, new HashSet<InterfaceType>()); /* * ... but the hash map destroys order. Methods should be
--- a/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Mon Oct 27 14:09:55 2014 -0700 @@ -48,7 +48,7 @@ private ResourceBundle messages = null; private int vmSequenceNumber = 0; private static final int majorVersion = 1; - private static final int minorVersion = 6; + private static final int minorVersion = 8; private static final Object lock = new Object(); private static VirtualMachineManagerImpl vmm;
--- a/src/share/classes/java/awt/Component.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/awt/Component.java Mon Oct 27 14:09:55 2014 -0700 @@ -3400,7 +3400,7 @@ (width > 0) && (height > 0)) { PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE, new Rectangle(x, y, width, height)); - Toolkit.getEventQueue().postEvent(e); + SunToolkit.postEvent(SunToolkit.targetToAppContext(this), e); } } }
--- a/src/share/classes/java/io/ByteArrayOutputStream.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/io/ByteArrayOutputStream.java Mon Oct 27 14:09:55 2014 -0700 @@ -94,6 +94,14 @@ } /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * @@ -105,14 +113,19 @@ int newCapacity = oldCapacity << 1; if (newCapacity - minCapacity < 0) newCapacity = minCapacity; - if (newCapacity < 0) { - if (minCapacity < 0) // overflow - throw new OutOfMemoryError(); - newCapacity = Integer.MAX_VALUE; - } + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); buf = Arrays.copyOf(buf, newCapacity); } + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; + } + /** * Writes the specified byte to this byte array output stream. *
--- a/src/share/classes/java/io/FileInputStream.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/io/FileInputStream.java Mon Oct 27 14:09:55 2014 -0700 @@ -184,7 +184,16 @@ * Opens the specified file for reading. * @param name the name of the file */ - private native void open(String name) throws FileNotFoundException; + private native void open0(String name) throws FileNotFoundException; + + // wrap native call to allow instrumentation + /** + * Opens the specified file for reading. + * @param name the name of the file + */ + private void open(String name) throws FileNotFoundException { + open0(name); + } /** * Reads a byte of data from this input stream. This method blocks
--- a/src/share/classes/java/io/FileOutputStream.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/io/FileOutputStream.java Mon Oct 27 14:09:55 2014 -0700 @@ -256,9 +256,20 @@ * @param name name of file to be opened * @param append whether the file is to be opened in append mode */ - private native void open(String name, boolean append) + private native void open0(String name, boolean append) throws FileNotFoundException; + // wrap native call to allow instrumentation + /** + * Opens a file, with the specified name, for overwriting or appending. + * @param name name of file to be opened + * @param append whether the file is to be opened in append mode + */ + private void open(String name, boolean append) + throws FileNotFoundException { + open0(name, append); + } + /** * Writes the specified byte to this file output stream. *
--- a/src/share/classes/java/io/RandomAccessFile.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/io/RandomAccessFile.java Mon Oct 27 14:09:55 2014 -0700 @@ -296,9 +296,26 @@ * @param mode the mode flags, a combination of the O_ constants * defined above */ - private native void open(String name, int mode) + private native void open0(String name, int mode) throws FileNotFoundException; + // wrap native call to allow instrumentation + /** + * Opens a file and returns the file descriptor. The file is + * opened in read-write mode if the O_RDWR bit in {@code mode} + * is true, else the file is opened as read-only. + * If the {@code name} refers to a directory, an IOException + * is thrown. + * + * @param name the name of the file + * @param mode the mode flags, a combination of the O_ constants + * defined above + */ + private void open(String name, int mode) + throws FileNotFoundException { + open0(name, mode); + } + // 'Read' primitives /**
--- a/src/share/classes/java/lang/Class.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/Class.java Mon Oct 27 14:09:55 2014 -0700 @@ -130,11 +130,15 @@ } /* - * Constructor. Only the Java Virtual Machine creates Class - * objects. + * Private constructor. Only the Java Virtual Machine creates Class objects. + * This constructor is not used and prevents the default constructor being + * generated. */ - private Class() {} - + private Class(ClassLoader loader) { + // Initialize final field for classLoader. The initialization value of non-null + // prevents future JIT optimizations from assuming this final field is null. + classLoader = loader; + } /** * Converts the object to a string. The string representation is the @@ -682,8 +686,10 @@ } // Package-private to allow ClassLoader access - native ClassLoader getClassLoader0(); - + ClassLoader getClassLoader0() { return classLoader; } + + // Initialized in JVM not by private constructor + private final ClassLoader classLoader; /** * Returns an array of {@code TypeVariable} objects that represent the
--- a/src/share/classes/java/lang/invoke/BoundMethodHandle.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/invoke/BoundMethodHandle.java Mon Oct 27 14:09:55 2014 -0700 @@ -26,11 +26,10 @@ package java.lang.invoke; import static jdk.internal.org.objectweb.asm.Opcodes.*; -import static java.lang.invoke.LambdaForm.basicTypes; -import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; -import java.lang.invoke.LambdaForm.Name; import java.lang.invoke.LambdaForm.NamedFunction; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Field; @@ -51,89 +50,93 @@ * * All bound arguments are encapsulated in dedicated species. */ -/* non-public */ abstract class BoundMethodHandle extends MethodHandle { +/*non-public*/ abstract class BoundMethodHandle extends MethodHandle { - /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) { + /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) { super(type, form); + assert(speciesData() == speciesData(form)); } // // BMH API and internals // - static MethodHandle bindSingle(MethodType type, LambdaForm form, char xtype, Object x) { + static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) { // for some type signatures, there exist pre-defined concrete BMH classes try { switch (xtype) { - case 'L': - if (true) return bindSingle(type, form, x); // Use known fast path. - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x); - case 'I': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x)); - case 'J': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x); - case 'F': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x); - case 'D': - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x); - default : throw new InternalError("unexpected xtype: " + xtype); + case L_TYPE: + return bindSingle(type, form, x); // Use known fast path. + case I_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x)); + case J_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x); + case F_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x); + case D_TYPE: + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x); + default : throw newInternalError("unexpected xtype: " + xtype); } } catch (Throwable t) { throw newInternalError(t); } } - static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) { - return new Species_L(type, form, x); + /*non-public*/ + LambdaFormEditor editor() { + return form.editor(); } - MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) { - try { - switch (xtype) { - case 'L': return cloneExtendL(type, form, x); - case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x)); - case 'J': return cloneExtendJ(type, form, (long) x); - case 'F': return cloneExtendF(type, form, (float) x); - case 'D': return cloneExtendD(type, form, (double) x); - } - } catch (Throwable t) { - throw newInternalError(t); - } - throw new InternalError("unexpected type: " + xtype); + static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) { + return Species_L.make(type, form, x); + } + + @Override // there is a default binder in the super class, for 'L' types only + /*non-public*/ + BoundMethodHandle bindArgumentL(int pos, Object value) { + return editor().bindArgumentL(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentI(int pos, int value) { + return editor().bindArgumentI(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentJ(int pos, long value) { + return editor().bindArgumentJ(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentF(int pos, float value) { + return editor().bindArgumentF(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentD(int pos, double value) { + return editor().bindArgumentD(this, pos, value); } @Override - MethodHandle bindArgument(int pos, char basicType, Object value) { - MethodType type = type().dropParameterTypes(pos, pos+1); - LambdaForm form = internalForm().bind(1+pos, speciesData()); - return cloneExtend(type, form, basicType, value); + BoundMethodHandle rebind() { + if (!tooComplex()) { + return this; + } + return makeReinvoker(this); } - @Override - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops)); - try { - return clone(srcType, form); - } catch (Throwable t) { - throw newInternalError(t); - } + private boolean tooComplex() { + return (fieldCount() > FIELD_COUNT_THRESHOLD || + form.expressionCount() > FORM_EXPRESSION_THRESHOLD); } + private static final int FIELD_COUNT_THRESHOLD = 12; // largest convenient BMH field count + private static final int FORM_EXPRESSION_THRESHOLD = 24; // largest convenient BMH expression count - @Override - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - try { - return clone(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList()))); - } catch (Throwable t) { - throw newInternalError(t); - } - } - - static final String EXTENSION_TYPES = "LIJFD"; - static final byte INDEX_L = 0, INDEX_I = 1, INDEX_J = 2, INDEX_F = 3, INDEX_D = 4; - static byte extensionIndex(char type) { - int i = EXTENSION_TYPES.indexOf(type); - if (i < 0) throw new InternalError(); - return (byte) i; + /** + * A reinvoker MH has this form: + * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }} + */ + static BoundMethodHandle makeReinvoker(MethodHandle target) { + LambdaForm form = DelegatingMethodHandle.makeReinvokerForm( + target, MethodTypeForm.LF_REBIND, + Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0)); + return Species_L.make(target.type(), form, target); } /** @@ -142,9 +145,22 @@ */ /*non-public*/ abstract SpeciesData speciesData(); + /*non-public*/ static SpeciesData speciesData(LambdaForm form) { + Object c = form.names[0].constraint; + if (c instanceof SpeciesData) + return (SpeciesData) c; + // if there is no BMH constraint, then use the null constraint + return SpeciesData.EMPTY; + } + + /** + * Return the number of fields in this BMH. Equivalent to speciesData().fieldCount(). + */ + /*non-public*/ abstract int fieldCount(); + @Override - final Object internalProperties() { - return "/BMH="+internalValues(); + Object internalProperties() { + return "\n& BMH="+internalValues(); } @Override @@ -159,42 +175,28 @@ /*non-public*/ final Object arg(int i) { try { switch (speciesData().fieldType(i)) { - case 'L': return argL(i); - case 'I': return argI(i); - case 'F': return argF(i); - case 'D': return argD(i); - case 'J': return argJ(i); + case L_TYPE: return speciesData().getters[i].invokeBasic(this); + case I_TYPE: return (int) speciesData().getters[i].invokeBasic(this); + case J_TYPE: return (long) speciesData().getters[i].invokeBasic(this); + case F_TYPE: return (float) speciesData().getters[i].invokeBasic(this); + case D_TYPE: return (double) speciesData().getters[i].invokeBasic(this); } } catch (Throwable ex) { throw newInternalError(ex); } - throw new InternalError("unexpected type: " + speciesData().types+"."+i); + throw new InternalError("unexpected type: " + speciesData().typeChars+"."+i); } - /*non-public*/ final Object argL(int i) throws Throwable { return speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final int argI(int i) throws Throwable { return (int) speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final float argF(int i) throws Throwable { return (float) speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); } - /*non-public*/ final long argJ(int i) throws Throwable { return (long) speciesData().getters[i].invokeBasic(this); } // // cloning API // - /*non-public*/ abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable; - /*non-public*/ abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable; - - // The following is a grossly irregular hack: - @Override MethodHandle reinvokerTarget() { - try { - return (MethodHandle) argL(0); - } catch (Throwable ex) { - throw newInternalError(ex); - } - } + /*non-public*/ abstract BoundMethodHandle copyWith(MethodType mt, LambdaForm lf); + /*non-public*/ abstract BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg); + /*non-public*/ abstract BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg); // // concrete BMH classes required to close bootstrap loops @@ -203,150 +205,110 @@ private // make it private to force users to access the enclosing class first static final class Species_L extends BoundMethodHandle { final Object argL0; - /*non-public*/ Species_L(MethodType mt, LambdaForm lf, Object argL0) { + private Species_L(MethodType mt, LambdaForm lf, Object argL0) { super(mt, lf); this.argL0 = argL0; } - // The following is a grossly irregular hack: - @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; } @Override /*non-public*/ SpeciesData speciesData() { return SPECIES_DATA; } + @Override + /*non-public*/ int fieldCount() { + return 1; + } /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class); - @Override - /*non-public*/ final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable { + /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) { return new Species_L(mt, lf, argL0); } @Override - /*non-public*/ final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg); + /*non-public*/ final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Species_L(mt, lf, argL0); } @Override - /*non-public*/ final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } @Override - /*non-public*/ final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } @Override - /*non-public*/ final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } @Override - /*non-public*/ final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg); + /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + } + @Override + /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) { + try { + return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); + } catch (Throwable ex) { + throw uncaughtException(ex); + } } } -/* - static final class Species_LL extends BoundMethodHandle { - final Object argL0; - final Object argL1; - public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) { - super(mt, lf); - this.argL0 = argL0; - this.argL1 = argL1; - } - @Override - public SpeciesData speciesData() { - return SPECIES_DATA; - } - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class); - @Override - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable { - return new Species_LL(mt, lf, argL0, argL1); - } - @Override - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg); - } - } - - static final class Species_JL extends BoundMethodHandle { - final long argJ0; - final Object argL1; - public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) { - super(mt, lf); - this.argJ0 = argJ0; - this.argL1 = argL1; - } - @Override - public SpeciesData speciesData() { - return SPECIES_DATA; - } - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class); - @Override public final long argJ0() { return argJ0; } - @Override public final Object argL1() { return argL1; } - @Override - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable { - return new Species_JL(mt, lf, argJ0, argL1); - } - @Override - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); - } - @Override - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable { - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg); - } - } -*/ - // // BMH species meta-data // /** - * Meta-data wrapper for concrete BMH classes. + * Meta-data wrapper for concrete BMH types. + * Each BMH type corresponds to a given sequence of basic field types (LIJFD). + * The fields are immutable; their values are fully specified at object construction. + * Each BMH type supplies an array of getter functions which may be used in lambda forms. + * A BMH is constructed by cloning a shorter BMH and adding one or more new field values. + * The shortest possible BMH has zero fields; its class is SimpleMethodHandle. + * BMH species are not interrelated by subtyping, even though it would appear that + * a shorter BMH could serve as a supertype of a longer one which extends it. */ static class SpeciesData { - final String types; - final Class<? extends BoundMethodHandle> clazz; + private final String typeChars; + private final BasicType[] typeCodes; + private final Class<? extends BoundMethodHandle> clazz; // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH // Therefore, we need a non-final link in the chain. Use array elements. - final MethodHandle[] constructor; - final MethodHandle[] getters; - final SpeciesData[] extensions; + @Stable private final MethodHandle[] constructor; + @Stable private final MethodHandle[] getters; + @Stable private final NamedFunction[] nominalGetters; + @Stable private final SpeciesData[] extensions; /*non-public*/ int fieldCount() { - return types.length(); + return typeCodes.length; } - /*non-public*/ char fieldType(int i) { - return types.charAt(i); + /*non-public*/ BasicType fieldType(int i) { + return typeCodes[i]; } - + /*non-public*/ char fieldTypeChar(int i) { + return typeChars.charAt(i); + } + Object fieldSignature() { + return typeChars; + } + public Class<? extends BoundMethodHandle> fieldHolder() { + return clazz; + } public String toString() { - return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]"; + return "SpeciesData<"+fieldSignature()+">"; } /** @@ -354,45 +316,59 @@ * represents a MH bound to a generic invoker, which in turn forwards to the corresponding * getter. */ - Name getterName(Name mhName, int i) { - MethodHandle mh = getters[i]; - assert(mh != null) : this+"."+i; - return new Name(mh, mhName); + NamedFunction getterFunction(int i) { + NamedFunction nf = nominalGetters[i]; + assert(nf.memberDeclaringClassOrNull() == fieldHolder()); + assert(nf.returnType() == fieldType(i)); + return nf; } - NamedFunction getterFunction(int i) { - return new NamedFunction(getters[i]); + NamedFunction[] getterFunctions() { + return nominalGetters; + } + + MethodHandle[] getterHandles() { return getters; } + + MethodHandle constructor() { + return constructor[0]; } static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class); private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) { - this.types = types; + this.typeChars = types; + this.typeCodes = basicTypes(types); this.clazz = clazz; if (!INIT_DONE) { - this.constructor = new MethodHandle[1]; + this.constructor = new MethodHandle[1]; // only one ctor this.getters = new MethodHandle[types.length()]; + this.nominalGetters = new NamedFunction[types.length()]; } else { this.constructor = Factory.makeCtors(clazz, types, null); this.getters = Factory.makeGetters(clazz, types, null); + this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters); } - this.extensions = new SpeciesData[EXTENSION_TYPES.length()]; + this.extensions = new SpeciesData[ARG_TYPE_LIMIT]; } private void initForBootstrap() { assert(!INIT_DONE); - if (constructor[0] == null) { + if (constructor() == null) { + String types = typeChars; Factory.makeCtors(clazz, types, this.constructor); Factory.makeGetters(clazz, types, this.getters); + Factory.makeNominalGetters(types, this.nominalGetters, this.getters); } } - private SpeciesData(String types) { + private SpeciesData(String typeChars) { // Placeholder only. - this.types = types; + this.typeChars = typeChars; + this.typeCodes = basicTypes(typeChars); this.clazz = null; this.constructor = null; this.getters = null; + this.nominalGetters = null; this.extensions = null; } private boolean isPlaceholder() { return clazz == null; } @@ -401,18 +377,15 @@ static { CACHE.put("", EMPTY); } // make bootstrap predictable private static final boolean INIT_DONE; // set after <clinit> finishes... - SpeciesData extendWithType(char type) { - int i = extensionIndex(type); - SpeciesData d = extensions[i]; - if (d != null) return d; - extensions[i] = d = get(types+type); - return d; + SpeciesData extendWith(byte type) { + return extendWith(BasicType.basicType(type)); } - SpeciesData extendWithIndex(byte index) { - SpeciesData d = extensions[index]; + SpeciesData extendWith(BasicType type) { + int ord = type.ordinal(); + SpeciesData d = extensions[ord]; if (d != null) return d; - extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index)); + extensions[ord] = d = get(typeChars+type.basicTypeChar()); return d; } @@ -456,8 +429,6 @@ static { // pre-fill the BMH speciesdata cache with BMH's inner classes final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class; - SpeciesData d0 = BoundMethodHandle.SPECIES_DATA; // trigger class init - assert(d0 == null || d0 == lookupCache("")) : d0; try { for (Class<?> c : rootCls.getDeclaredClasses()) { if (rootCls.isAssignableFrom(c)) { @@ -465,7 +436,7 @@ SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh); assert(d != null) : cbmh.getName(); assert(d.clazz == cbmh); - assert(d == lookupCache(d.types)); + assert(d == lookupCache(d.typeChars)); } } } catch (Throwable e) { @@ -516,11 +487,10 @@ static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG; static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG; static final String VOID_SIG = "()V"; + static final String INT_SIG = "()I"; static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;"; - static final Class<?>[] TYPES = new Class<?>[] { Object.class, int.class, long.class, float.class, double.class }; - static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" }; /** @@ -551,31 +521,35 @@ * final Object argL0; * final Object argL1; * final int argI2; - * Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { + * private Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { * super(mt, lf); * this.argL0 = argL0; * this.argL1 = argL1; * this.argI2 = argI2; * } * final SpeciesData speciesData() { return SPECIES_DATA; } + * final int fieldCount() { return 3; } * static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class); - * final BoundMethodHandle clone(MethodType mt, LambdaForm lf) { - * return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2); + * static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { + * return new Species_LLI(mt, lf, argL0, argL1, argI2); * } - * final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) { + * return new Species_LLI(mt, lf, argL0, argL1, argI2); * } - * final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) { + * return SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } - * final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) { + * return SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } - * final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) { + * return SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } - * final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) { - * return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) { + * return SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * } + * public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) { + * return SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } * } * </pre> @@ -586,8 +560,9 @@ static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - final String className = SPECIES_PREFIX_PATH + types; - final String sourceFile = SPECIES_PREFIX_NAME + types; + String shortTypes = LambdaForm.shortenSignature(types); + final String className = SPECIES_PREFIX_PATH + shortTypes; + final String sourceFile = SPECIES_PREFIX_NAME + shortTypes; final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null); cw.visitSource(sourceFile, null); @@ -606,13 +581,13 @@ MethodVisitor mv; // emit constructor - mv = cw.visitMethod(NOT_ACC_PUBLIC, "<init>", makeSignature(types, true), null, null); + mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null); mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 0); // this + mv.visitVarInsn(ALOAD, 1); // type + mv.visitVarInsn(ALOAD, 2); // form - mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true)); + mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false); for (int i = 0, j = 0; i < types.length(); ++i, ++j) { // i counts the arguments, j counts corresponding argument slots @@ -629,16 +604,6 @@ mv.visitMaxs(0, 0); mv.visitEnd(); - // emit implementation of reinvokerTarget() - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG); - mv.visitTypeInsn(CHECKCAST, MH); - mv.visitInsn(ARETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - // emit implementation of speciesData() mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null); mv.visitCode(); @@ -647,51 +612,83 @@ mv.visitMaxs(0, 0); mv.visitEnd(); - // emit clone() - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE); + // emit implementation of fieldCount() + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null); mv.visitCode(); - // return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...) - // obtain constructor - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); - mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG); - mv.visitInsn(ICONST_0); - mv.visitInsn(AALOAD); + int fc = types.length(); + if (fc <= (ICONST_5 - ICONST_0)) { + mv.visitInsn(ICONST_0 + fc); + } else { + mv.visitIntInsn(SIPUSH, fc); + } + mv.visitInsn(IRETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + // emit make() ...factory method wrapping constructor + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null); + mv.visitCode(); + // make instance + mv.visitTypeInsn(NEW, className); + mv.visitInsn(DUP); + // load mt, lf + mv.visitVarInsn(ALOAD, 0); // type + mv.visitVarInsn(ALOAD, 1); // form + // load factory method arguments + for (int i = 0, j = 0; i < types.length(); ++i, ++j) { + // i counts the arguments, j counts corresponding argument slots + char t = types.charAt(i); + mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3 + if (t == 'J' || t == 'D') { + ++j; // adjust argument register access + } + } + + // finally, invoke the constructor and return + mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false); + mv.visitInsn(ARETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + + // emit copyWith() + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null); + mv.visitCode(); + // make instance + mv.visitTypeInsn(NEW, className); + mv.visitInsn(DUP); // load mt, lf mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); // put fields on the stack emitPushFields(types, className, mv); // finally, invoke the constructor and return - mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types, false)); + mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); - // for each type, emit cloneExtendT() - for (Class<?> c : TYPES) { - char t = Wrapper.basicTypeChar(c); - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE); + // for each type, emit copyWithExtendT() + for (BasicType type : BasicType.ARG_TYPES) { + int ord = type.ordinal(); + char btChar = type.basicTypeChar(); + mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE); mv.visitCode(); - // return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg) + // return SPECIES_DATA.extendWith(t).constructor().invokeBasic(mt, lf, argL0, ..., narg) // obtain constructor mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); - int iconstInsn = ICONST_0 + extensionIndex(t); + int iconstInsn = ICONST_0 + ord; assert(iconstInsn <= ICONST_5); mv.visitInsn(iconstInsn); - mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWithIndex", BMHSPECIES_DATA_EWI_SIG); - mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG); - mv.visitInsn(ICONST_0); - mv.visitInsn(AALOAD); + mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false); + mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "constructor", "()" + MH_SIG, false); // load mt, lf mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); // put fields on the stack emitPushFields(types, className, mv); // put narg on stack - mv.visitVarInsn(typeLoadOp(t), 3); + mv.visitVarInsn(typeLoadOp(btChar), 3); // finally, invoke the constructor and return - mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + t, false)); + mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); @@ -702,7 +699,7 @@ mv.visitCode(); mv.visitLdcInsn(types); mv.visitLdcInsn(Type.getObjectType(className)); - mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG); + mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false); mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); @@ -730,7 +727,7 @@ case 'J': return LLOAD; case 'F': return FLOAD; case 'D': return DLOAD; - default : throw new InternalError("unrecognized type " + t); + default : throw newInternalError("unrecognized type " + t); } } @@ -771,10 +768,19 @@ static MethodHandle[] makeCtors(Class<? extends BoundMethodHandle> cbmh, String types, MethodHandle mhs[]) { if (mhs == null) mhs = new MethodHandle[1]; + if (types.equals("")) return mhs; // hack for empty BMH species mhs[0] = makeCbmhCtor(cbmh, types); return mhs; } + static NamedFunction[] makeNominalGetters(String types, NamedFunction[] nfs, MethodHandle[] getters) { + if (nfs == null) nfs = new NamedFunction[types.length()]; + for (int i = 0; i < nfs.length; ++i) { + nfs[i] = new NamedFunction(getters[i]); + } + return nfs; + } + // // Auxiliary methods. // @@ -808,52 +814,11 @@ static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) { try { - return linkConstructor(LOOKUP.findConstructor(cbmh, MethodType.fromMethodDescriptorString(makeSignature(types, true), null))); + return LOOKUP.findStatic(cbmh, "make", MethodType.fromMethodDescriptorString(makeSignature(types, false), null)); } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) { throw newInternalError(e); } } - - /** - * Wrap a constructor call in a {@link LambdaForm}. - * - * If constructors ({@code <init>} methods) are called in LFs, problems might arise if the LFs - * are turned into bytecode, because the call to the allocator is routed through an MH, and the - * verifier cannot find a {@code NEW} instruction preceding the {@code INVOKESPECIAL} to - * {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through - * {@link MethodHandle#linkToSpecial}. - * - * The last {@link LambdaForm.Name Name} in the argument's form is expected to be the {@code void} - * result of the {@code <init>} invocation. This entry is replaced. - */ - private static MethodHandle linkConstructor(MethodHandle cmh) { - final LambdaForm lf = cmh.form; - final int initNameIndex = lf.names.length - 1; - final Name initName = lf.names[initNameIndex]; - final MemberName ctorMN = initName.function.member; - final MethodType ctorMT = ctorMN.getInvocationType(); - - // obtain function member (call target) - // linker method type replaces initial parameter (BMH species) with BMH to avoid naming a species (anonymous class!) - final MethodType linkerMT = ctorMT.changeParameterType(0, BoundMethodHandle.class).appendParameterTypes(MemberName.class); - MemberName linkerMN = new MemberName(MethodHandle.class, "linkToSpecial", linkerMT, REF_invokeStatic); - try { - linkerMN = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linkerMN, null, NoSuchMethodException.class); - assert(linkerMN.isStatic()); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - // extend arguments array - Object[] newArgs = Arrays.copyOf(initName.arguments, initName.arguments.length + 1); - newArgs[newArgs.length - 1] = ctorMN; - // replace function - final NamedFunction nf = new NamedFunction(linkerMN); - final Name linkedCtor = new Name(nf, newArgs); - linkedCtor.initIndex(initNameIndex); - lf.names[initNameIndex] = linkedCtor; - return cmh; - } - } private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
--- a/src/share/classes/java/lang/invoke/CallSite.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/invoke/CallSite.java Mon Oct 27 14:09:55 2014 -0700 @@ -102,7 +102,7 @@ */ /*package-private*/ CallSite(MethodType type) { - target = type.invokers().uninitializedCallSite(); + target = makeUninitializedCallSite(type); } /** @@ -211,27 +211,40 @@ public abstract MethodHandle dynamicInvoker(); /*non-public*/ MethodHandle makeDynamicInvoker() { - MethodHandle getTarget = GET_TARGET.bindReceiver(this); + MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this); MethodHandle invoker = MethodHandles.exactInvoker(this.type()); return MethodHandles.foldArguments(invoker, getTarget); } private static final MethodHandle GET_TARGET; + private static final MethodHandle THROW_UCS; static { try { GET_TARGET = IMPL_LOOKUP. findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); + THROW_UCS = IMPL_LOOKUP. + findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class)); } catch (ReflectiveOperationException e) { throw newInternalError(e); } } /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */ - /*package-private*/ - static Empty uninitializedCallSite() { + private static Object uninitializedCallSite(Object... ignore) { throw new IllegalStateException("uninitialized call site"); } + private MethodHandle makeUninitializedCallSite(MethodType targetType) { + MethodType basicType = targetType.basicType(); + MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS); + if (invoker == null) { + invoker = THROW_UCS.asType(basicType); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker); + } + // unchecked view is OK since no values will be received or returned + return invoker.viewAsType(targetType, false); + } + // unsafe stuff: private static final long TARGET_OFFSET; static { @@ -319,7 +332,7 @@ throw new ClassCastException("bootstrap method failed to produce a CallSite"); } if (!site.getTarget().type().equals(type)) - throw new WrongMethodTypeException("wrong type: "+site.getTarget()); + throw wrongTargetType(site.getTarget(), type); } catch (Throwable ex) { BootstrapMethodError bex; if (ex instanceof BootstrapMethodError)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java Mon Oct 27 14:09:55 2014 -0700 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import java.util.Arrays; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.MethodHandleStatics.*; + +/** + * A method handle whose invocation behavior is determined by a target. + * The delegating MH itself can hold extra "intentions" beyond the simple behavior. + * @author jrose + */ +/*non-public*/ +abstract class DelegatingMethodHandle extends MethodHandle { + protected DelegatingMethodHandle(MethodHandle target) { + this(target.type(), target); + } + + protected DelegatingMethodHandle(MethodType type, MethodHandle target) { + super(type, chooseDelegatingForm(target)); + } + + /** Define this to extract the delegated target which supplies the invocation behavior. */ + abstract protected MethodHandle getTarget(); + + @Override + abstract MethodHandle asTypeUncached(MethodType newType); + + @Override + MemberName internalMemberName() { + return getTarget().internalMemberName(); + } + + @Override + boolean isInvokeSpecial() { + return getTarget().isInvokeSpecial(); + } + + @Override + Class<?> internalCallerClass() { + return getTarget().internalCallerClass(); + } + + @Override + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + // FIXME: rethink 'copyWith' protocol; it is too low-level for use on all MHs + throw newIllegalArgumentException("do not use this"); + } + + @Override + String internalProperties() { + return "\n& Class="+getClass().getSimpleName()+ + "\n& Target="+getTarget().debugString(); + } + + @Override + BoundMethodHandle rebind() { + return getTarget().rebind(); + } + + private static LambdaForm chooseDelegatingForm(MethodHandle target) { + if (target instanceof SimpleMethodHandle) + return target.internalForm(); // no need for an indirection + return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget); + } + + /** Create a LF which simply reinvokes a target of the given basic type. */ + static LambdaForm makeReinvokerForm(MethodHandle target, + int whichCache, + Object constraint, + NamedFunction getTargetFn) { + MethodType mtype = target.type().basicType(); + boolean customized = (whichCache < 0 || + mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY); + LambdaForm form; + if (!customized) { + form = mtype.form().cachedLambdaForm(whichCache); + if (form != null) return form; + } + final int THIS_DMH = 0; + final int ARG_BASE = 1; + final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); + int nameCursor = ARG_LIMIT; + final int NEXT_MH = customized ? -1 : nameCursor++; + final int REINVOKE = nameCursor++; + LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); + assert(names.length == nameCursor); + names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint); + Object[] targetArgs; + if (customized) { + targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class); + names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself + } else { + names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]); + targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class); + targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH + names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs); + } + String debugString; + switch(whichCache) { + case MethodTypeForm.LF_REBIND: debugString = "BMH.reinvoke"; break; + case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate"; break; + default: debugString = "MH.reinvoke"; break; + } + form = new LambdaForm(debugString, ARG_LIMIT, names); + if (!customized) { + form = mtype.form().setCachedLambdaForm(whichCache, form); + } + return form; + } + + private static final NamedFunction NF_getTarget; + static { + try { + NF_getTarget = new NamedFunction(DelegatingMethodHandle.class + .getDeclaredMethod("getTarget")); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } +}
--- a/src/share/classes/java/lang/invoke/DirectMethodHandle.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/invoke/DirectMethodHandle.java Mon Oct 27 14:09:55 2014 -0700 @@ -31,6 +31,7 @@ import sun.invoke.util.VerifyAccess; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodTypeForm.*; import static java.lang.invoke.MethodHandleStatics.*; import java.lang.ref.WeakReference; @@ -58,6 +59,7 @@ MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); if (m != null && m.isPublic()) { + assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong member = m; } } @@ -125,65 +127,30 @@ } @Override + BoundMethodHandle rebind() { + return BoundMethodHandle.makeReinvoker(this); + } + + @Override MethodHandle copyWith(MethodType mt, LambdaForm lf) { + assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses return new DirectMethodHandle(mt, lf, member); } @Override String internalProperties() { - return "/DMH="+member.toString(); + return "\n& DMH.MN="+internalMemberName(); } //// Implementation methods. @Override - MethodHandle viewAsType(MethodType newType) { - return new DirectMethodHandle(newType, form, member); - } - @Override @ForceInline MemberName internalMemberName() { return member; } - @Override - MethodHandle bindArgument(int pos, char basicType, Object value) { - // If the member needs dispatching, do so. - if (pos == 0 && basicType == 'L') { - DirectMethodHandle concrete = maybeRebind(value); - if (concrete != null) - return concrete.bindReceiver(value); - } - return super.bindArgument(pos, basicType, value); - } - - @Override - MethodHandle bindReceiver(Object receiver) { - // If the member needs dispatching, do so. - DirectMethodHandle concrete = maybeRebind(receiver); - if (concrete != null) - return concrete.bindReceiver(receiver); - return super.bindReceiver(receiver); - } - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); - private DirectMethodHandle maybeRebind(Object receiver) { - if (receiver != null) { - switch (member.getReferenceKind()) { - case REF_invokeInterface: - case REF_invokeVirtual: - // Pre-dispatch the member. - Class<?> concreteClass = receiver.getClass(); - MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial); - concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass); - if (concrete != null) - return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete); - break; - } - } - return null; - } - /** * Create a LF which can invoke the given method. * Cache and share this structure among all methods with @@ -264,9 +231,10 @@ } else { names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]); } + assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]); Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class); assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args! - int result = LambdaForm.LAST_RESULT; + int result = LAST_RESULT; if (doesAlloc) { assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2); @@ -274,13 +242,23 @@ result = NEW_OBJ; } names[LINKER_CALL] = new Name(linker, outArgs); - lambdaName += "_" + LambdaForm.basicTypeSignature(mtype); + lambdaName += "_" + shortenSignature(basicTypeSignature(mtype)); LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result); // This is a tricky bit of code. Don't send it through the LF interpreter. lform.compileToBytecode(); return lform; } + static Object findDirectMethodHandle(Name name) { + if (name.function == Lazy.NF_internalMemberName || + name.function == Lazy.NF_internalMemberNameEnsureInit || + name.function == Lazy.NF_constructorMethod) { + assert(name.arguments.length == 1); + return name.arguments[0]; + } + return null; + } + private static void maybeCompile(LambdaForm lform, MemberName m) { if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class)) // Help along bootstrapping... @@ -393,8 +371,8 @@ return true; } @Override - MethodHandle viewAsType(MethodType newType) { - return new Special(newType, form, member); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Special(mt, lf, member); } } @@ -411,8 +389,8 @@ assert(initMethod.isResolved()); } @Override - MethodHandle viewAsType(MethodType newType) { - return new Constructor(newType, form, member, initMethod, instanceClass); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Constructor(mt, lf, member, initMethod, instanceClass); } } @@ -441,8 +419,8 @@ return fieldType.cast(obj); } @Override - MethodHandle viewAsType(MethodType newType) { - return new Accessor(newType, form, member, fieldOffset); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Accessor(mt, lf, member, fieldOffset); } } @@ -484,8 +462,8 @@ return fieldType.cast(obj); } @Override - MethodHandle viewAsType(MethodType newType) { - return new StaticAccessor(newType, form, member, staticBase, staticOffset); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new StaticAccessor(mt, lf, member, staticBase, staticOffset); } }
--- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Mon Oct 27 14:09:55 2014 -0700 @@ -193,10 +193,10 @@ CallSite buildCallSite() throws LambdaConversionException { final Class<?> innerClass = spinInnerClass(); if (invokedType.parameterCount() == 0) { - final Constructor[] ctrs = AccessController.doPrivileged( - new PrivilegedAction<Constructor[]>() { + final Constructor<?>[] ctrs = AccessController.doPrivileged( + new PrivilegedAction<Constructor<?>[]>() { @Override - public Constructor[] run() { + public Constructor<?>[] run() { Constructor<?>[] ctrs = innerClass.getDeclaredConstructors(); if (ctrs.length == 1) { // The lambda implementing inner class constructor is private, set @@ -338,7 +338,7 @@ m.visitVarInsn(getLoadOpcode(argType), varIndex); varIndex += getParameterSize(argType); } - m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString()); + m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); m.visitInsn(ARETURN); m.visitMaxs(-1, -1); m.visitEnd(); @@ -354,7 +354,7 @@ ctor.visitCode(); ctor.visitVarInsn(ALOAD, 0); ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR, - METHOD_DESCRIPTOR_VOID); + METHOD_DESCRIPTOR_VOID, false); int parameterCount = invokedType.parameterCount(); for (int i = 0, lvIndex = 0; i < parameterCount; i++) { ctor.visitVarInsn(ALOAD, 0); @@ -402,7 +402,7 @@ mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR, - DESCR_CTOR_SERIALIZED_LAMBDA); + DESCR_CTOR_SERIALIZED_LAMBDA, false); mv.visitInsn(ARETURN); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored mv.visitMaxs(-1, -1); @@ -421,7 +421,7 @@ mv.visitInsn(DUP); mv.visitLdcInsn("Non-serializable lambda"); mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR, - DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION); + DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); mv.visitInsn(ATHROW); mv.visitMaxs(-1, -1); mv.visitEnd(); @@ -434,7 +434,7 @@ mv.visitInsn(DUP); mv.visitLdcInsn("Non-serializable lambda"); mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR, - DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION); + DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); mv.visitInsn(ATHROW); mv.visitMaxs(-1, -1); mv.visitEnd();
--- a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Mon Oct 27 14:09:55 2014 -0700 @@ -25,20 +25,20 @@ package java.lang.invoke; -import sun.invoke.util.VerifyAccess; -import java.lang.invoke.LambdaForm.Name; - -import sun.invoke.util.Wrapper; - import java.io.*; import java.util.*; +import java.lang.reflect.Modifier; import jdk.internal.org.objectweb.asm.*; -import java.lang.reflect.*; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; + +import sun.invoke.util.VerifyAccess; import sun.invoke.util.VerifyType; +import sun.invoke.util.Wrapper; import sun.reflect.misc.ReflectUtil; /** @@ -62,7 +62,7 @@ private static final String CLL_SIG = "(L" + CLS + ";L" + OBJ + ";)L" + OBJ + ";"; /** Name of its super class*/ - private static final String superName = LF; + private static final String superName = OBJ; /** Name of new class */ private final String className; @@ -73,7 +73,11 @@ private final LambdaForm lambdaForm; private final String invokerName; private final MethodType invokerType; - private final int[] localsMap; + + /** Info about local variables in compiled lambda form */ + private final int[] localsMap; // index + private final BasicType[] localTypes; // basic type + private final Class<?>[] localClasses; // type /** ASM bytecode generation. */ private ClassWriter cw; @@ -82,6 +86,7 @@ private static final MemberName.Factory MEMBERNAME_FACTORY = MemberName.getFactory(); private static final Class<?> HOST_CLASS = LambdaForm.class; + /** Main constructor; other constructors delegate to this one. */ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, String className, String invokerName, MethodType invokerType) { if (invokerName.contains(".")) { @@ -92,23 +97,31 @@ if (DUMP_CLASS_FILES) { className = makeDumpableClassName(className); } - this.className = superName + "$" + className; + this.className = LF + "$" + className; this.sourceFile = "LambdaForm$" + className; this.lambdaForm = lambdaForm; this.invokerName = invokerName; this.invokerType = invokerType; - this.localsMap = new int[localsMapSize]; + this.localsMap = new int[localsMapSize+1]; + // last entry of localsMap is count of allocated local slots + this.localTypes = new BasicType[localsMapSize+1]; + this.localClasses = new Class<?>[localsMapSize+1]; } + /** For generating LambdaForm interpreter entry points. */ private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) { this(null, invokerType.parameterCount(), className, invokerName, invokerType); // Create an array to map name indexes to locals indexes. + localTypes[localTypes.length - 1] = V_TYPE; for (int i = 0; i < localsMap.length; i++) { localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i); + if (i < invokerType.parameterCount()) + localTypes[i] = basicType(invokerType.parameterType(i)); } } + /** For generating customized code for a single LambdaForm. */ private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) { this(form, form.names.length, className, form.debugName, invokerType); @@ -116,7 +129,11 @@ Name[] names = form.names; for (int i = 0, index = 0; i < localsMap.length; i++) { localsMap[i] = index; - index += Wrapper.forBasicType(names[i].type).stackSlots(); + if (i < names.length) { + BasicType type = names[i].type(); + index += type.basicTypeSlots(); + localTypes[i] = type; + } } } @@ -147,7 +164,6 @@ static void maybeDump(final String className, final byte[] classFile) { if (DUMP_CLASS_FILES) { - System.out.println("dump: " + className); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Void>() { public Void run() { @@ -155,6 +171,7 @@ String dumpName = className; //dumpName = dumpName.replace('/', '-'); File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class"); + System.out.println("dump: " + dumpFile); dumpFile.getParentFile().mkdirs(); FileOutputStream file = new FileOutputStream(dumpFile); file.write(classFile); @@ -203,7 +220,7 @@ String constantPlaceholder(Object arg) { String cpPlaceholder = "CONSTANT_PLACEHOLDER_" + cph++; - if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + arg.toString() + ">>"; // debugging aid + if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + debugString(arg) + ">>"; // debugging aid if (cpPatches.containsKey(cpPlaceholder)) { throw new InternalError("observed CP placeholder twice: " + cpPlaceholder); } @@ -224,6 +241,17 @@ return res; } + private static String debugString(Object arg) { + if (arg instanceof MethodHandle) { + MethodHandle mh = (MethodHandle) arg; + MemberName member = mh.internalMemberName(); + if (member != null) + return member.toString(); + return mh.debugString(); + } + return arg.toString(); + } + /** * Extract the number of constant pool entries from a given class file. * @@ -359,118 +387,212 @@ /* * NOTE: These load/store methods use the localsMap to find the correct index! */ - private void emitLoadInsn(char type, int index) { - int opcode; - switch (type) { - case 'I': opcode = Opcodes.ILOAD; break; - case 'J': opcode = Opcodes.LLOAD; break; - case 'F': opcode = Opcodes.FLOAD; break; - case 'D': opcode = Opcodes.DLOAD; break; - case 'L': opcode = Opcodes.ALOAD; break; - default: - throw new InternalError("unknown type: " + type); - } + private void emitLoadInsn(BasicType type, int index) { + int opcode = loadInsnOpcode(type); mv.visitVarInsn(opcode, localsMap[index]); } + + private int loadInsnOpcode(BasicType type) throws InternalError { + switch (type) { + case I_TYPE: return Opcodes.ILOAD; + case J_TYPE: return Opcodes.LLOAD; + case F_TYPE: return Opcodes.FLOAD; + case D_TYPE: return Opcodes.DLOAD; + case L_TYPE: return Opcodes.ALOAD; + default: + throw new InternalError("unknown type: " + type); + } + } private void emitAloadInsn(int index) { - emitLoadInsn('L', index); + emitLoadInsn(L_TYPE, index); } - private void emitStoreInsn(char type, int index) { - int opcode; - switch (type) { - case 'I': opcode = Opcodes.ISTORE; break; - case 'J': opcode = Opcodes.LSTORE; break; - case 'F': opcode = Opcodes.FSTORE; break; - case 'D': opcode = Opcodes.DSTORE; break; - case 'L': opcode = Opcodes.ASTORE; break; - default: - throw new InternalError("unknown type: " + type); - } + private void emitStoreInsn(BasicType type, int index) { + int opcode = storeInsnOpcode(type); mv.visitVarInsn(opcode, localsMap[index]); } + + private int storeInsnOpcode(BasicType type) throws InternalError { + switch (type) { + case I_TYPE: return Opcodes.ISTORE; + case J_TYPE: return Opcodes.LSTORE; + case F_TYPE: return Opcodes.FSTORE; + case D_TYPE: return Opcodes.DSTORE; + case L_TYPE: return Opcodes.ASTORE; + default: + throw new InternalError("unknown type: " + type); + } + } private void emitAstoreInsn(int index) { - emitStoreInsn('L', index); + emitStoreInsn(L_TYPE, index); + } + + private byte arrayTypeCode(Wrapper elementType) { + switch (elementType) { + case BOOLEAN: return Opcodes.T_BOOLEAN; + case BYTE: return Opcodes.T_BYTE; + case CHAR: return Opcodes.T_CHAR; + case SHORT: return Opcodes.T_SHORT; + case INT: return Opcodes.T_INT; + case LONG: return Opcodes.T_LONG; + case FLOAT: return Opcodes.T_FLOAT; + case DOUBLE: return Opcodes.T_DOUBLE; + case OBJECT: return 0; // in place of Opcodes.T_OBJECT + default: throw new InternalError(); + } + } + + private int arrayInsnOpcode(byte tcode, int aaop) throws InternalError { + assert(aaop == Opcodes.AASTORE || aaop == Opcodes.AALOAD); + int xas; + switch (tcode) { + case Opcodes.T_BOOLEAN: xas = Opcodes.BASTORE; break; + case Opcodes.T_BYTE: xas = Opcodes.BASTORE; break; + case Opcodes.T_CHAR: xas = Opcodes.CASTORE; break; + case Opcodes.T_SHORT: xas = Opcodes.SASTORE; break; + case Opcodes.T_INT: xas = Opcodes.IASTORE; break; + case Opcodes.T_LONG: xas = Opcodes.LASTORE; break; + case Opcodes.T_FLOAT: xas = Opcodes.FASTORE; break; + case Opcodes.T_DOUBLE: xas = Opcodes.DASTORE; break; + case 0: xas = Opcodes.AASTORE; break; + default: throw new InternalError(); + } + return xas - Opcodes.AASTORE + aaop; + } + + + private void freeFrameLocal(int oldFrameLocal) { + int i = indexForFrameLocal(oldFrameLocal); + if (i < 0) return; + BasicType type = localTypes[i]; + int newFrameLocal = makeLocalTemp(type); + mv.visitVarInsn(loadInsnOpcode(type), oldFrameLocal); + mv.visitVarInsn(storeInsnOpcode(type), newFrameLocal); + assert(localsMap[i] == oldFrameLocal); + localsMap[i] = newFrameLocal; + assert(indexForFrameLocal(oldFrameLocal) < 0); + } + private int indexForFrameLocal(int frameLocal) { + for (int i = 0; i < localsMap.length; i++) { + if (localsMap[i] == frameLocal && localTypes[i] != V_TYPE) + return i; + } + return -1; + } + private int makeLocalTemp(BasicType type) { + int frameLocal = localsMap[localsMap.length - 1]; + localsMap[localsMap.length - 1] = frameLocal + type.basicTypeSlots(); + return frameLocal; } /** * Emit a boxing call. * - * @param type primitive type class to box. + * @param wrapper primitive type class to box. */ - private void emitBoxing(Class<?> type) { - Wrapper wrapper = Wrapper.forPrimitiveType(type); + private void emitBoxing(Wrapper wrapper) { String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = "valueOf"; String desc = "(" + wrapper.basicTypeChar() + ")L" + owner + ";"; - mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false); } /** * Emit an unboxing call (plus preceding checkcast). * - * @param type wrapper type class to unbox. + * @param wrapper wrapper type class to unbox. */ - private void emitUnboxing(Class<?> type) { - Wrapper wrapper = Wrapper.forWrapperType(type); + private void emitUnboxing(Wrapper wrapper) { String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = wrapper.primitiveSimpleName() + "Value"; String desc = "()" + wrapper.basicTypeChar(); - mv.visitTypeInsn(Opcodes.CHECKCAST, owner); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc); + emitReferenceCast(wrapper.wrapperType(), null); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false); } /** - * Emit an implicit conversion. + * Emit an implicit conversion for an argument which must be of the given pclass. + * This is usually a no-op, except when pclass is a subword type or a reference other than Object or an interface. * * @param ptype type of value present on stack * @param pclass type of value required on stack + * @param arg compile-time representation of value on stack (Node, constant) or null if none */ - private void emitImplicitConversion(char ptype, Class<?> pclass) { + private void emitImplicitConversion(BasicType ptype, Class<?> pclass, Object arg) { + assert(basicType(pclass) == ptype); // boxing/unboxing handled by caller + if (pclass == ptype.basicTypeClass() && ptype != L_TYPE) + return; // nothing to do switch (ptype) { - case 'L': - if (VerifyType.isNullConversion(Object.class, pclass)) + case L_TYPE: + if (VerifyType.isNullConversion(Object.class, pclass, false)) { + if (PROFILE_LEVEL > 0) + emitReferenceCast(Object.class, arg); + return; + } + emitReferenceCast(pclass, arg); return; - if (isStaticallyNameable(pclass)) { - mv.visitTypeInsn(Opcodes.CHECKCAST, getInternalName(pclass)); - } else { - mv.visitLdcInsn(constantPlaceholder(pclass)); - mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); - mv.visitInsn(Opcodes.SWAP); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG); - if (pclass.isArray()) - mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); + case I_TYPE: + if (!VerifyType.isNullConversion(int.class, pclass, false)) + emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); + return; + } + throw newInternalError("bad implicit conversion: tc="+ptype+": "+pclass); + } + + /** Update localClasses type map. Return true if the information is already present. */ + private boolean assertStaticType(Class<?> cls, Name n) { + int local = n.index(); + Class<?> aclass = localClasses[local]; + if (aclass != null && (aclass == cls || cls.isAssignableFrom(aclass))) { + return true; // type info is already present + } else if (aclass == null || aclass.isAssignableFrom(cls)) { + localClasses[local] = cls; // type info can be improved + } + return false; + } + + private void emitReferenceCast(Class<?> cls, Object arg) { + Name writeBack = null; // local to write back result + if (arg instanceof Name) { + Name n = (Name) arg; + if (assertStaticType(cls, n)) + return; // this cast was already performed + if (lambdaForm.useCount(n) > 1) { + // This guy gets used more than once. + writeBack = n; } - return; - case 'I': - if (!VerifyType.isNullConversion(int.class, pclass)) - emitPrimCast(ptype, Wrapper.basicTypeChar(pclass)); - return; - case 'J': - assert(pclass == long.class); - return; - case 'F': - assert(pclass == float.class); - return; - case 'D': - assert(pclass == double.class); - return; } - throw new InternalError("bad implicit conversion: tc="+ptype+": "+pclass); + if (isStaticallyNameable(cls)) { + String sig = getInternalName(cls); + mv.visitTypeInsn(Opcodes.CHECKCAST, sig); + } else { + mv.visitLdcInsn(constantPlaceholder(cls)); + mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); + mv.visitInsn(Opcodes.SWAP); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); + if (Object[].class.isAssignableFrom(cls)) + mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); + else if (PROFILE_LEVEL > 0) + mv.visitTypeInsn(Opcodes.CHECKCAST, OBJ); + } + if (writeBack != null) { + mv.visitInsn(Opcodes.DUP); + emitAstoreInsn(writeBack.index()); + } } /** * Emits an actual return instruction conforming to the given return type. */ - private void emitReturnInsn(Class<?> type) { + private void emitReturnInsn(BasicType type) { int opcode; - switch (Wrapper.basicTypeChar(type)) { - case 'I': opcode = Opcodes.IRETURN; break; - case 'J': opcode = Opcodes.LRETURN; break; - case 'F': opcode = Opcodes.FRETURN; break; - case 'D': opcode = Opcodes.DRETURN; break; - case 'L': opcode = Opcodes.ARETURN; break; - case 'V': opcode = Opcodes.RETURN; break; + switch (type) { + case I_TYPE: opcode = Opcodes.IRETURN; break; + case J_TYPE: opcode = Opcodes.LRETURN; break; + case F_TYPE: opcode = Opcodes.FRETURN; break; + case D_TYPE: opcode = Opcodes.DRETURN; break; + case L_TYPE: opcode = Opcodes.ARETURN; break; + case V_TYPE: opcode = Opcodes.RETURN; break; default: throw new InternalError("unknown return type: " + type); } @@ -478,7 +600,11 @@ } private static String getInternalName(Class<?> c) { - assert(VerifyAccess.isTypeVisible(c, Object.class)); + if (c == Object.class) return OBJ; + else if (c == Object[].class) return OBJARY; + else if (c == Class.class) return CLS; + else if (c == MethodHandle.class) return MH; + assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName(); return c.getName().replace('.', '/'); } @@ -507,39 +633,62 @@ // iterate over the form's names, generating bytecode instructions for each // start iterating at the first name following the arguments + Name onStack = null; for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) { Name name = lambdaForm.names[i]; + + emitStoreResult(onStack); + onStack = name; // unless otherwise modified below + MethodHandleImpl.Intrinsic intr = name.function.intrinsicName(); + switch (intr) { + case SELECT_ALTERNATIVE: + assert isSelectAlternative(i); + onStack = emitSelectAlternative(name, lambdaForm.names[i+1]); + i++; // skip MH.invokeBasic of the selectAlternative result + continue; + case GUARD_WITH_CATCH: + assert isGuardWithCatch(i); + onStack = emitGuardWithCatch(i); + i = i+2; // Jump to the end of GWC idiom + continue; + case NEW_ARRAY: + Class<?> rtype = name.function.methodType().returnType(); + if (isStaticallyNameable(rtype)) { + emitNewArray(name); + continue; + } + break; + case ARRAY_LOAD: + emitArrayLoad(name); + continue; + case ARRAY_STORE: + emitArrayStore(name); + continue; + case IDENTITY: + assert(name.arguments.length == 1); + emitPushArguments(name); + continue; + case ZERO: + assert(name.arguments.length == 0); + emitConst(name.type.basicTypeWrapper().zero()); + continue; + case NONE: + // no intrinsic associated + break; + default: + throw newInternalError("Unknown intrinsic: "+intr); + } + MemberName member = name.function.member(); - - if (isSelectAlternative(i)) { - emitSelectAlternative(name, lambdaForm.names[i + 1]); - i++; // skip MH.invokeBasic of the selectAlternative result - } else if (isGuardWithCatch(i)) { - emitGuardWithCatch(i); - i = i+2; // Jump to the end of GWC idiom - } else if (isStaticallyInvocable(member)) { + if (isStaticallyInvocable(member)) { emitStaticInvoke(member, name); } else { emitInvoke(name); } - - // Update cached form name's info in case an intrinsic spanning multiple names was encountered. - name = lambdaForm.names[i]; - member = name.function.member(); - - // store the result from evaluating to the target name in a local if required - // (if this is the last value, i.e., the one that is going to be returned, - // avoid store/load/return and just return) - if (i == lambdaForm.names.length - 1 && i == lambdaForm.result) { - // return value - do nothing - } else if (name.type != 'V') { - // non-void: actually assign - emitStoreInsn(name.type, name.index()); - } } // return statement - emitReturn(); + emitReturn(onStack); classFileEpilogue(); bogusMethod(lambdaForm); @@ -549,33 +698,47 @@ return classFile; } + void emitArrayLoad(Name name) { emitArrayOp(name, Opcodes.AALOAD); } + void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); } + + void emitArrayOp(Name name, int arrayOpcode) { + assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE; + Class<?> elementType = name.function.methodType().parameterType(0).getComponentType(); + assert elementType != null; + emitPushArguments(name); + if (elementType.isPrimitive()) { + Wrapper w = Wrapper.forPrimitiveType(elementType); + arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode); + } + mv.visitInsn(arrayOpcode); + } + /** * Emit an invoke for the given name. */ void emitInvoke(Name name) { + assert(!isLinkerMethodInvoke(name)); // should use the static path for these if (true) { // push receiver MethodHandle target = name.function.resolvedHandle; assert(target != null) : name.exprString(); mv.visitLdcInsn(constantPlaceholder(target)); - mv.visitTypeInsn(Opcodes.CHECKCAST, MH); + emitReferenceCast(MethodHandle.class, target); } else { // load receiver emitAloadInsn(0); - mv.visitTypeInsn(Opcodes.CHECKCAST, MH); + emitReferenceCast(MethodHandle.class, null); mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", LF_SIG); mv.visitFieldInsn(Opcodes.GETFIELD, LF, "names", LFN_SIG); // TODO more to come } // push arguments - for (int i = 0; i < name.arguments.length; i++) { - emitPushArgument(name, i); - } + emitPushArguments(name); // invocation MethodType type = name.function.methodType(); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString()); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false); } static private Class<?>[] STATICALLY_INVOCABLE_PACKAGES = { @@ -586,6 +749,10 @@ //MethodHandle.class already covered }; + static boolean isStaticallyInvocable(Name name) { + return isStaticallyInvocable(name.function.member()); + } + static boolean isStaticallyInvocable(MemberName member) { if (member == null) return false; if (member.isConstructor()) return false; @@ -612,6 +779,8 @@ } static boolean isStaticallyNameable(Class<?> cls) { + if (cls == Object.class) + return true; while (cls.isArray()) cls = cls.getComponentType(); if (cls.isPrimitive()) @@ -632,12 +801,17 @@ return false; } + void emitStaticInvoke(Name name) { + emitStaticInvoke(name.function.member(), name); + } + /** * Emit an invoke for the given name, using the MemberName directly. */ void emitStaticInvoke(MemberName member, Name name) { assert(member.equals(name.function.member())); - String cname = getInternalName(member.getDeclaringClass()); + Class<?> defc = member.getDeclaringClass(); + String cname = getInternalName(defc); String mname = member.getName(); String mtype; byte refKind = member.getReferenceKind(); @@ -654,9 +828,7 @@ } // push arguments - for (int i = 0; i < name.arguments.length; i++) { - emitPushArgument(name, i); - } + emitPushArguments(name); // invocation if (member.isMethod()) { @@ -667,6 +839,52 @@ mtype = MethodType.toFieldDescriptorString(member.getFieldType()); mv.visitFieldInsn(refKindOpcode(refKind), cname, mname, mtype); } + // Issue a type assertion for the result, so we can avoid casts later. + if (name.type == L_TYPE) { + Class<?> rtype = member.getInvocationType().returnType(); + assert(!rtype.isPrimitive()); + if (rtype != Object.class && !rtype.isInterface()) { + assertStaticType(rtype, name); + } + } + } + + void emitNewArray(Name name) throws InternalError { + Class<?> rtype = name.function.methodType().returnType(); + if (name.arguments.length == 0) { + // The array will be a constant. + Object emptyArray; + try { + emptyArray = name.function.resolvedHandle.invoke(); + } catch (Throwable ex) { + throw newInternalError(ex); + } + assert(java.lang.reflect.Array.getLength(emptyArray) == 0); + assert(emptyArray.getClass() == rtype); // exact typing + mv.visitLdcInsn(constantPlaceholder(emptyArray)); + emitReferenceCast(rtype, emptyArray); + return; + } + Class<?> arrayElementType = rtype.getComponentType(); + assert(arrayElementType != null); + emitIconstInsn(name.arguments.length); + int xas = Opcodes.AASTORE; + if (!arrayElementType.isPrimitive()) { + mv.visitTypeInsn(Opcodes.ANEWARRAY, getInternalName(arrayElementType)); + } else { + byte tc = arrayTypeCode(Wrapper.forPrimitiveType(arrayElementType)); + xas = arrayInsnOpcode(tc, xas); + mv.visitIntInsn(Opcodes.NEWARRAY, tc); + } + // store arguments + for (int i = 0; i < name.arguments.length; i++) { + mv.visitInsn(Opcodes.DUP); + emitIconstInsn(i); + emitPushArgument(name, i); + mv.visitInsn(xas); + } + // the array is left on the stack + assertStaticType(rtype, name); } int refKindOpcode(byte refKind) { switch (refKind) { @@ -709,6 +927,21 @@ } /** + * Check if MemberName is a call to MethodHandle.linkToStatic, etc. + */ + private boolean isLinkerMethodInvoke(Name name) { + if (name.function == null) + return false; + if (name.arguments.length < 1) + return false; // must have MH argument + MemberName member = name.function.member(); + return member != null && + member.getDeclaringClass() == MethodHandle.class && + !member.isPublic() && member.isStatic() && + member.getName().startsWith("linkTo"); + } + + /** * Check if i-th name is a call to MethodHandleImpl.selectAlternative. */ private boolean isSelectAlternative(int pos) { @@ -756,7 +989,9 @@ * t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I} * }</pre></blockquote> */ - private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { + private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { + assert isStaticallyInvocable(invokeBasicName); + Name receiver = (Name) invokeBasicName.arguments[0]; Label L_fallback = new Label(); @@ -764,15 +999,15 @@ // load test result emitPushArgument(selectAlternativeName, 0); - mv.visitInsn(Opcodes.ICONST_1); // if_icmpne L_fallback - mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback); + mv.visitJumpInsn(Opcodes.IFEQ, L_fallback); // invoke selectAlternativeName.arguments[1] + Class<?>[] preForkClasses = localClasses.clone(); emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot - emitInvoke(invokeBasicName); + emitStaticInvoke(invokeBasicName); // goto L_done mv.visitJumpInsn(Opcodes.GOTO, L_done); @@ -781,12 +1016,17 @@ mv.visitLabel(L_fallback); // invoke selectAlternativeName.arguments[2] + System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot - emitInvoke(invokeBasicName); + emitStaticInvoke(invokeBasicName); // L_done: mv.visitLabel(L_done); + // for now do not bother to merge typestate; just reset to the dominator state + System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); + + return invokeBasicName; // return what's on stack } /** @@ -809,7 +1049,7 @@ * return a3.invokeBasic(ex, a6, a7); * }} */ - private void emitGuardWithCatch(int pos) { + private Name emitGuardWithCatch(int pos) { Name args = lambdaForm.names[pos]; Name invoker = lambdaForm.names[pos+1]; Name result = lambdaForm.names[pos+2]; @@ -860,6 +1100,12 @@ mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(L_done); + + return result; + } + + private void emitPushArguments(Name args) { + emitPushArguments(args, 0); } private void emitPushArguments(Name args, int start) { @@ -870,75 +1116,69 @@ private void emitPushArgument(Name name, int paramIndex) { Object arg = name.arguments[paramIndex]; - char ptype = name.function.parameterType(paramIndex); - MethodType mtype = name.function.methodType(); + Class<?> ptype = name.function.methodType().parameterType(paramIndex); + emitPushArgument(ptype, arg); + } + + private void emitPushArgument(Class<?> ptype, Object arg) { + BasicType bptype = basicType(ptype); if (arg instanceof Name) { Name n = (Name) arg; emitLoadInsn(n.type, n.index()); - emitImplicitConversion(n.type, mtype.parameterType(paramIndex)); - } else if ((arg == null || arg instanceof String) && ptype == 'L') { + emitImplicitConversion(n.type, ptype, n); + } else if ((arg == null || arg instanceof String) && bptype == L_TYPE) { emitConst(arg); } else { - if (Wrapper.isWrapperType(arg.getClass()) && ptype != 'L') { + if (Wrapper.isWrapperType(arg.getClass()) && bptype != L_TYPE) { emitConst(arg); } else { mv.visitLdcInsn(constantPlaceholder(arg)); - emitImplicitConversion('L', mtype.parameterType(paramIndex)); + emitImplicitConversion(L_TYPE, ptype, arg); } } } /** + * Store the name to its local, if necessary. + */ + private void emitStoreResult(Name name) { + if (name != null && name.type != V_TYPE) { + // non-void: actually assign + emitStoreInsn(name.type, name.index()); + } + } + + /** * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type. */ - private void emitReturn() { + private void emitReturn(Name onStack) { // return statement - if (lambdaForm.result == -1) { + Class<?> rclass = invokerType.returnType(); + BasicType rtype = lambdaForm.returnType(); + assert(rtype == basicType(rclass)); // must agree + if (rtype == V_TYPE) { // void mv.visitInsn(Opcodes.RETURN); + // it doesn't matter what rclass is; the JVM will discard any value } else { LambdaForm.Name rn = lambdaForm.names[lambdaForm.result]; - char rtype = Wrapper.basicTypeChar(invokerType.returnType()); // put return value on the stack if it is not already there - if (lambdaForm.result != lambdaForm.names.length - 1) { - emitLoadInsn(rn.type, lambdaForm.result); + if (rn != onStack) { + emitLoadInsn(rtype, lambdaForm.result); } - // potentially generate cast - // rtype is the return type of the invoker - generated code must conform to this - // rn.type is the type of the result Name in the LF - if (rtype != rn.type) { - // need cast - if (rtype == 'L') { - // possibly cast the primitive to the correct type for boxing - char boxedType = Wrapper.forWrapperType(invokerType.returnType()).basicTypeChar(); - if (boxedType != rn.type) { - emitPrimCast(rn.type, boxedType); - } - // cast primitive to reference ("boxing") - emitBoxing(invokerType.returnType()); - } else { - // to-primitive cast - if (rn.type != 'L') { - // prim-to-prim cast - emitPrimCast(rn.type, rtype); - } else { - // ref-to-prim cast ("unboxing") - throw new InternalError("no ref-to-prim (unboxing) casts supported right now"); - } - } - } + emitImplicitConversion(rtype, rclass, rn); // generate actual return statement - emitReturnInsn(invokerType.returnType()); + emitReturnInsn(rtype); } } /** * Emit a type conversion bytecode casting from "from" to "to". */ - private void emitPrimCast(char from, char to) { + private void emitPrimCast(Wrapper from, Wrapper to) { // Here's how. // - indicates forbidden // <-> indicates implicit @@ -955,17 +1195,15 @@ // no cast required, should be dead code anyway return; } - Wrapper wfrom = Wrapper.forBasicType(from); - Wrapper wto = Wrapper.forBasicType(to); - if (wfrom.isSubwordOrInt()) { + if (from.isSubwordOrInt()) { // cast from {byte,short,char,int} to anything emitI2X(to); } else { // cast from {long,float,double} to anything - if (wto.isSubwordOrInt()) { + if (to.isSubwordOrInt()) { // cast to {byte,short,char,int} emitX2I(from); - if (wto.bitWidth() < 32) { + if (to.bitWidth() < 32) { // targets other than int require another conversion emitI2X(to); } @@ -973,20 +1211,26 @@ // cast to {long,float,double} - this is verbose boolean error = false; switch (from) { - case 'J': - if (to == 'F') { mv.visitInsn(Opcodes.L2F); } - else if (to == 'D') { mv.visitInsn(Opcodes.L2D); } - else error = true; + case LONG: + switch (to) { + case FLOAT: mv.visitInsn(Opcodes.L2F); break; + case DOUBLE: mv.visitInsn(Opcodes.L2D); break; + default: error = true; break; + } break; - case 'F': - if (to == 'J') { mv.visitInsn(Opcodes.F2L); } - else if (to == 'D') { mv.visitInsn(Opcodes.F2D); } - else error = true; + case FLOAT: + switch (to) { + case LONG : mv.visitInsn(Opcodes.F2L); break; + case DOUBLE: mv.visitInsn(Opcodes.F2D); break; + default: error = true; break; + } break; - case 'D': - if (to == 'J') { mv.visitInsn(Opcodes.D2L); } - else if (to == 'F') { mv.visitInsn(Opcodes.D2F); } - else error = true; + case DOUBLE: + switch (to) { + case LONG : mv.visitInsn(Opcodes.D2L); break; + case FLOAT: mv.visitInsn(Opcodes.D2F); break; + default: error = true; break; + } break; default: error = true; @@ -999,16 +1243,16 @@ } } - private void emitI2X(char type) { + private void emitI2X(Wrapper type) { switch (type) { - case 'B': mv.visitInsn(Opcodes.I2B); break; - case 'S': mv.visitInsn(Opcodes.I2S); break; - case 'C': mv.visitInsn(Opcodes.I2C); break; - case 'I': /* naught */ break; - case 'J': mv.visitInsn(Opcodes.I2L); break; - case 'F': mv.visitInsn(Opcodes.I2F); break; - case 'D': mv.visitInsn(Opcodes.I2D); break; - case 'Z': + case BYTE: mv.visitInsn(Opcodes.I2B); break; + case SHORT: mv.visitInsn(Opcodes.I2S); break; + case CHAR: mv.visitInsn(Opcodes.I2C); break; + case INT: /* naught */ break; + case LONG: mv.visitInsn(Opcodes.I2L); break; + case FLOAT: mv.visitInsn(Opcodes.I2F); break; + case DOUBLE: mv.visitInsn(Opcodes.I2D); break; + case BOOLEAN: // For compatibility with ValueConversions and explicitCastArguments: mv.visitInsn(Opcodes.ICONST_1); mv.visitInsn(Opcodes.IAND); @@ -1017,39 +1261,24 @@ } } - private void emitX2I(char type) { + private void emitX2I(Wrapper type) { switch (type) { - case 'J': mv.visitInsn(Opcodes.L2I); break; - case 'F': mv.visitInsn(Opcodes.F2I); break; - case 'D': mv.visitInsn(Opcodes.D2I); break; - default: throw new InternalError("unknown type: " + type); + case LONG: mv.visitInsn(Opcodes.L2I); break; + case FLOAT: mv.visitInsn(Opcodes.F2I); break; + case DOUBLE: mv.visitInsn(Opcodes.D2I); break; + default: throw new InternalError("unknown type: " + type); } } - private static String basicTypeCharSignature(String prefix, MethodType type) { - StringBuilder buf = new StringBuilder(prefix); - for (Class<?> ptype : type.parameterList()) - buf.append(Wrapper.forBasicType(ptype).basicTypeChar()); - buf.append('_').append(Wrapper.forBasicType(type.returnType()).basicTypeChar()); - return buf.toString(); - } - /** * Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments. */ static MemberName generateLambdaFormInterpreterEntryPoint(String sig) { - assert(LambdaForm.isValidSignature(sig)); - //System.out.println("generateExactInvoker "+sig); - // compute method type - // first parameter and return type - char tret = LambdaForm.signatureReturn(sig); - MethodType type = MethodType.methodType(LambdaForm.typeClass(tret), MethodHandle.class); - // other parameter types - int arity = LambdaForm.signatureArity(sig); - for (int i = 1; i < arity; i++) { - type = type.appendParameterTypes(LambdaForm.typeClass(sig.charAt(i))); - } - InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", "interpret_"+tret, type); + assert(isValidSignature(sig)); + String name = "interpret_"+signatureReturn(sig).basicTypeChar(); + MethodType type = signatureType(sig); // sig includes leading argument + type = type.changeParameterType(0, MethodHandle.class); + InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", name, type); return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes()); } @@ -1071,10 +1300,10 @@ Class<?> ptype = invokerType.parameterType(i); mv.visitInsn(Opcodes.DUP); emitIconstInsn(i); - emitLoadInsn(Wrapper.basicTypeChar(ptype), i); + emitLoadInsn(basicType(ptype), i); // box if primitive type if (ptype.isPrimitive()) { - emitBoxing(ptype); + emitBoxing(Wrapper.forPrimitiveType(ptype)); } mv.visitInsn(Opcodes.AASTORE); } @@ -1082,16 +1311,16 @@ emitAloadInsn(0); mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", "Ljava/lang/invoke/LambdaForm;"); mv.visitInsn(Opcodes.SWAP); // swap form and array; avoid local variable - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LF, "interpretWithArguments", "([Ljava/lang/Object;)Ljava/lang/Object;"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LF, "interpretWithArguments", "([Ljava/lang/Object;)Ljava/lang/Object;", false); // maybe unbox Class<?> rtype = invokerType.returnType(); if (rtype.isPrimitive() && rtype != void.class) { - emitUnboxing(Wrapper.asWrapperType(rtype)); + emitUnboxing(Wrapper.forPrimitiveType(rtype)); } // return statement - emitReturnInsn(rtype); + emitReturnInsn(basicType(rtype)); classFileEpilogue(); bogusMethod(invokerType); @@ -1105,14 +1334,12 @@ * Generate bytecode for a NamedFunction invoker. */ static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) { - MethodType invokerType = LambdaForm.NamedFunction.INVOKER_METHOD_TYPE; - String invokerName = basicTypeCharSignature("invoke_", typeForm.erasedType()); + MethodType invokerType = NamedFunction.INVOKER_METHOD_TYPE; + String invokerName = "invoke_" + shortenSignature(basicTypeSignature(typeForm.erasedType())); InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("NFI", invokerName, invokerType); return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm)); } - static int nfi = 0; - private byte[] generateNamedFunctionInvokerImpl(MethodTypeForm typeForm) { MethodType dstType = typeForm.erasedType(); classFilePrologue(); @@ -1138,14 +1365,14 @@ Class<?> sptype = dstType.basicType().wrap().parameterType(i); Wrapper dstWrapper = Wrapper.forBasicType(dptype); Wrapper srcWrapper = dstWrapper.isSubwordOrInt() ? Wrapper.INT : dstWrapper; // narrow subword from int - emitUnboxing(srcWrapper.wrapperType()); - emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar()); + emitUnboxing(srcWrapper); + emitPrimCast(srcWrapper, dstWrapper); } } // Invoke String targetDesc = dstType.basicType().toMethodDescriptorString(); - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", targetDesc); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", targetDesc, false); // Box primitive types Class<?> rtype = dstType.returnType(); @@ -1153,15 +1380,15 @@ Wrapper srcWrapper = Wrapper.forBasicType(rtype); Wrapper dstWrapper = srcWrapper.isSubwordOrInt() ? Wrapper.INT : srcWrapper; // widen subword to int // boolean casts not allowed - emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar()); - emitBoxing(dstWrapper.primitiveType()); + emitPrimCast(srcWrapper, dstWrapper); + emitBoxing(dstWrapper); } // If the return type is void we return a null reference. if (rtype == void.class) { mv.visitInsn(Opcodes.ACONST_NULL); } - emitReturnInsn(Object.class); // NOTE: NamedFunction invokers always return a reference value. + emitReturnInsn(L_TYPE); // NOTE: NamedFunction invokers always return a reference value. classFileEpilogue(); bogusMethod(dstType);
--- a/src/share/classes/java/lang/invoke/Invokers.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/invoke/Invokers.java Mon Oct 27 14:09:55 2014 -0700 @@ -25,8 +25,9 @@ package java.lang.invoke; +import java.lang.reflect.Array; import java.util.Arrays; -import sun.invoke.empty.Empty; + import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @@ -40,52 +41,63 @@ // exact type (sans leading taget MH) for the outgoing call private final MethodType targetType; - // FIXME: Get rid of the invokers that are not useful. - - // exact invoker for the outgoing call - private /*lazy*/ MethodHandle exactInvoker; - private /*lazy*/ MethodHandle basicInvoker; // invokeBasic (unchecked exact) - - // erased (partially untyped but with primitives) invoker for the outgoing call - // FIXME: get rid of - private /*lazy*/ MethodHandle erasedInvoker; - // FIXME: get rid of - /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric - - // general invoker for the outgoing call - private /*lazy*/ MethodHandle generalInvoker; - - // general invoker for the outgoing call, uses varargs - private /*lazy*/ MethodHandle varargsInvoker; - - // general invoker for the outgoing call; accepts a trailing Object[] - private final /*lazy*/ MethodHandle[] spreadInvokers; - - // invoker for an unbound callsite - private /*lazy*/ MethodHandle uninitializedCallSite; + // Cached adapter information: + private final @Stable MethodHandle[] invokers = new MethodHandle[INV_LIMIT]; + // Indexes into invokers: + static final int + INV_EXACT = 0, // MethodHandles.exactInvoker + INV_GENERIC = 1, // MethodHandles.invoker (generic invocation) + INV_BASIC = 2, // MethodHandles.basicInvoker + INV_LIMIT = 3; /** Compute and cache information common to all collecting adapters * that implement members of the erasure-family of the given erased type. */ /*non-public*/ Invokers(MethodType targetType) { this.targetType = targetType; - this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1]; } /*non-public*/ MethodHandle exactInvoker() { - MethodHandle invoker = exactInvoker; + MethodHandle invoker = cachedInvoker(INV_EXACT); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(true); - exactInvoker = invoker; - return invoker; + return setCachedInvoker(INV_EXACT, invoker); } - /*non-public*/ MethodHandle generalInvoker() { - MethodHandle invoker = generalInvoker; + /*non-public*/ MethodHandle genericInvoker() { + MethodHandle invoker = cachedInvoker(INV_GENERIC); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(false); - generalInvoker = invoker; - return invoker; + return setCachedInvoker(INV_GENERIC, invoker); + } + + /*non-public*/ MethodHandle basicInvoker() { + MethodHandle invoker = cachedInvoker(INV_BASIC); + if (invoker != null) return invoker; + MethodType basicType = targetType.basicType(); + if (basicType != targetType) { + // double cache; not used significantly + return setCachedInvoker(INV_BASIC, basicType.invokers().basicInvoker()); + } + invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_BASIC_INV); + if (invoker == null) { + MemberName method = invokeBasicMethod(basicType); + invoker = DirectMethodHandle.make(method); + assert(checkInvoker(invoker)); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_BASIC_INV, invoker); + } + return setCachedInvoker(INV_BASIC, invoker); + } + + private MethodHandle cachedInvoker(int idx) { + return invokers[idx]; + } + + private synchronized MethodHandle setCachedInvoker(int idx, final MethodHandle invoker) { + // Simulate a CAS, to avoid racy duplication of results. + MethodHandle prev = invokers[idx]; + if (prev != null) return prev; + return invokers[idx] = invoker; } private MethodHandle makeExactOrGeneralInvoker(boolean isExact) { @@ -95,7 +107,7 @@ LambdaForm lform = invokeHandleForm(mtype, false, which); MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype); String whichName = (isExact ? "invokeExact" : "invoke"); - invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype)); + invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype), false); assert(checkInvoker(invoker)); maybeCompileToBytecode(invoker); return invoker; @@ -110,21 +122,6 @@ } } - /*non-public*/ MethodHandle basicInvoker() { - MethodHandle invoker = basicInvoker; - if (invoker != null) return invoker; - MethodType basicType = targetType.basicType(); - if (basicType != targetType) { - // double cache; not used significantly - return basicInvoker = basicType.invokers().basicInvoker(); - } - MemberName method = invokeBasicMethod(basicType); - invoker = DirectMethodHandle.make(method); - assert(checkInvoker(invoker)); - basicInvoker = invoker; - return invoker; - } - // This next one is called from LambdaForm.NamedFunction.<init>. /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) { assert(basicType == basicType.basicType()); @@ -145,87 +142,42 @@ return true; } - // FIXME: get rid of - /*non-public*/ MethodHandle erasedInvoker() { - MethodHandle xinvoker = exactInvoker(); - MethodHandle invoker = erasedInvoker; - if (invoker != null) return invoker; - MethodType erasedType = targetType.erase(); - invoker = xinvoker.asType(erasedType.invokerType()); - erasedInvoker = invoker; - return invoker; + /** + * Find or create an invoker which passes unchanged a given number of arguments + * and spreads the rest from a trailing array argument. + * The invoker target type is the post-spread type {@code (TYPEOF(uarg*), TYPEOF(sarg*))=>RT}. + * All the {@code sarg}s must have a common type {@code C}. (If there are none, {@code Object} is assumed.} + * @param leadingArgCount the number of unchanged (non-spread) arguments + * @return {@code invoker.invokeExact(mh, uarg*, C[]{sarg*}) := (RT)mh.invoke(uarg*, sarg*)} + */ + /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) { + int spreadArgCount = targetType.parameterCount() - leadingArgCount; + MethodType postSpreadType = targetType; + Class<?> argArrayType = impliedRestargType(postSpreadType, leadingArgCount); + if (postSpreadType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { + return genericInvoker().asSpreader(argArrayType, spreadArgCount); + } + // Cannot build a generic invoker here of type ginvoker.invoke(mh, a*[254]). + // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) + // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) + MethodType preSpreadType = postSpreadType + .replaceParameterTypes(leadingArgCount, postSpreadType.parameterCount(), argArrayType); + MethodHandle arrayInvoker = MethodHandles.invoker(preSpreadType); + MethodHandle makeSpreader = MethodHandles.insertArguments(Lazy.MH_asSpreader, 1, argArrayType, spreadArgCount); + return MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); } - /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) { - MethodHandle vaInvoker = spreadInvokers[leadingArgCount]; - if (vaInvoker != null) return vaInvoker; - int spreadArgCount = targetType.parameterCount() - leadingArgCount; - MethodType spreadInvokerType = targetType - .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class); - if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { - // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a) - // where ginvoker.invoke(mh, a*) => mh.invoke(a*). - MethodHandle genInvoker = generalInvoker(); - vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount); - } else { - // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]). - // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) - // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) - MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType); - MethodHandle makeSpreader; - try { - makeSpreader = IMPL_LOOKUP - .findVirtual(MethodHandle.class, "asSpreader", - MethodType.methodType(MethodHandle.class, Class.class, int.class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount); - vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); + private static Class<?> impliedRestargType(MethodType restargType, int fromPos) { + if (restargType.isGeneric()) return Object[].class; // can be nothing else + int maxPos = restargType.parameterCount(); + if (fromPos >= maxPos) return Object[].class; // reasonable default + Class<?> argType = restargType.parameterType(fromPos); + for (int i = fromPos+1; i < maxPos; i++) { + if (argType != restargType.parameterType(i)) + throw newIllegalArgumentException("need homogeneous rest arguments", restargType); } - assert(vaInvoker.type().equals(spreadInvokerType.invokerType())); - maybeCompileToBytecode(vaInvoker); - spreadInvokers[leadingArgCount] = vaInvoker; - return vaInvoker; - } - - /*non-public*/ MethodHandle varargsInvoker() { - MethodHandle vaInvoker = varargsInvoker; - if (vaInvoker != null) return vaInvoker; - vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType()); - varargsInvoker = vaInvoker; - return vaInvoker; - } - - private static MethodHandle THROW_UCS = null; - - /*non-public*/ MethodHandle uninitializedCallSite() { - MethodHandle invoker = uninitializedCallSite; - if (invoker != null) return invoker; - if (targetType.parameterCount() > 0) { - MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount()); - Invokers invokers0 = type0.invokers(); - invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(), - 0, targetType.parameterList()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; - } - invoker = THROW_UCS; - if (invoker == null) { - try { - THROW_UCS = invoker = IMPL_LOOKUP - .findStatic(CallSite.class, "uninitializedCallSite", - MethodType.methodType(Empty.class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - } - invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType())); - invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; + if (argType == Object.class) return Object[].class; + return Array.newInstance(argType, 0).getClass(); } public String toString() { @@ -308,7 +260,9 @@ : Arrays.asList(mtype, customized, which, nameCursor, names.length); if (MTYPE_ARG >= INARG_LIMIT) { assert(names[MTYPE_ARG] == null); - NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0); + BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L(); + names[THIS_MH] = names[THIS_MH].withConstraint(speciesData); + NamedFunction getter = speciesData.getterFunction(0); names[MTYPE_ARG] = new Name(getter, names[THIS_MH]); // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM) } @@ -360,9 +314,6 @@ Object checkGenericType(Object mhObj, Object expectedObj) { MethodHandle mh = (MethodHandle) mhObj; MethodType expected = (MethodType) expectedObj; - if (mh.type() == expected) return mh; - MethodHandle atc = mh.asTypeCache; - if (atc != null && atc.type() == expected) return atc; return mh.asType(expected); /* Maybe add more paths here. Possible optimizations: * for (R)MH.invoke(a*), @@ -436,27 +387,40 @@ } // Local constant functions: - private static final NamedFunction NF_checkExactType; - private static final NamedFunction NF_checkGenericType; - private static final NamedFunction NF_asType; - private static final NamedFunction NF_getCallSiteTarget; + private static final NamedFunction + NF_checkExactType, + NF_checkGenericType, + NF_getCallSiteTarget; static { try { - NF_checkExactType = new NamedFunction(Invokers.class - .getDeclaredMethod("checkExactType", Object.class, Object.class)); - NF_checkGenericType = new NamedFunction(Invokers.class - .getDeclaredMethod("checkGenericType", Object.class, Object.class)); - NF_asType = new NamedFunction(MethodHandle.class - .getDeclaredMethod("asType", MethodType.class)); - NF_getCallSiteTarget = new NamedFunction(Invokers.class - .getDeclaredMethod("getCallSiteTarget", Object.class)); - NF_checkExactType.resolve(); - NF_checkGenericType.resolve(); - NF_getCallSiteTarget.resolve(); - // bound + NamedFunction nfs[] = { + NF_checkExactType = new NamedFunction(Invokers.class + .getDeclaredMethod("checkExactType", Object.class, Object.class)), + NF_checkGenericType = new NamedFunction(Invokers.class + .getDeclaredMethod("checkGenericType", Object.class, Object.class)), + NF_getCallSiteTarget = new NamedFunction(Invokers.class + .getDeclaredMethod("getCallSiteTarget", Object.class)) + }; + for (NamedFunction nf : nfs) { + // Each nf must be statically invocable or we get tied up in our bootstraps. + assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf; + nf.resolve(); + } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } } + private static class Lazy { + private static final MethodHandle MH_asSpreader; + + static { + try { + MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader", + MethodType.methodType(MethodHandle.class, Class.class, int.class)); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } + } }
--- a/src/share/classes/java/lang/invoke/LambdaForm.java Fri Oct 24 11:49:24 2014 +0000 +++ b/src/share/classes/java/lang/invoke/LambdaForm.java Mon Oct 27 14:09:55 2014 -0700 @@ -27,17 +27,16 @@ import java.lang.annotation.*; import java.lang.reflect.Method; -import java.util.Map; import java.util.List; import java.util.Arrays; -import java.util.ArrayList; import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; + import sun.invoke.util.Wrapper; +import java.lang.reflect.Field; + +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; -import java.lang.reflect.Field; -import java.util.Objects; /** * The symbolic, non-executable form of a method handle's invocation semantics. @@ -125,19 +124,136 @@ MemberName vmentry; // low-level behavior, or null if not yet prepared private boolean isCompiled; - // Caches for common structural transforms: - LambdaForm[] bindCache; + Object transformCache; // managed by LambdaFormEditor public static final int VOID_RESULT = -1, LAST_RESULT = -2; + enum BasicType { + L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types + I_TYPE('I', int.class, Wrapper.INT), + J_TYPE('J', long.class, Wrapper.LONG), + F_TYPE('F', float.class, Wrapper.FLOAT), + D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types + V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts + + static final BasicType[] ALL_TYPES = BasicType.values(); + static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1); + + static final int ARG_TYPE_LIMIT = ARG_TYPES.length; + static final int TYPE_LIMIT = ALL_TYPES.length; + + private final char btChar; + private final Class<?> btClass; + private final Wrapper btWrapper; + + private BasicType(char btChar, Class<?> btClass, Wrapper wrapper) { + this.btChar = btChar; + this.btClass = btClass; + this.btWrapper = wrapper; + } + + char basicTypeChar() { + return btChar; + } + Class<?> basicTypeClass() { + return btClass; + } + Wrapper basicTypeWrapper() { + return btWrapper; + } + int basicTypeSlots() { + return btWrapper.stackSlots(); + } + + static BasicType basicType(byte type) { + return ALL_TYPES[type]; + } + static BasicType basicType(char type) { + switch (type) { + case 'L': return L_TYPE; + case 'I': return I_TYPE; + case 'J': return J_TYPE; + case 'F': return F_TYPE; + case 'D': return D_TYPE; + case 'V': return V_TYPE; + // all subword types are represented as ints + case 'Z': + case 'B': + case 'S': + case 'C': + return I_TYPE; + default: + throw newInternalError("Unknown type char: '"+type+"'"); + } + } + static BasicType basicType(Wrapper type) { + char c = type.basicTypeChar(); + return basicType(c); + } + static BasicType basicType(Class<?> type) { + if (!type.isPrimitive()) return L_TYPE; + return basicType(Wrapper.forPrimitiveType(type)); + } + + static char basicTypeChar(Class<?> type) { + return basicType(type).btChar; + } + static BasicType[] basicTypes(List<Class<?>> types) { + BasicType[] btypes = new BasicType[types.size()]; + for (int i = 0; i < btypes.length; i++) { + btypes[i] = basicType(types.get(i)); + } + return btypes; + } + static BasicType[] basicTypes(String types) { + BasicType[] btypes = new BasicType[types.length()]; + for (int i = 0; i < btypes.length; i++) { + btypes[i] = basicType(types.charAt(i)); + } + return btypes; + } + static byte[] basicTypesOrd(BasicType[] btypes) { + byte[] ords = new byte[btypes.length]; + for (int i = 0; i < btypes.length; i++) { + ords[i] = (byte)btypes[i].ordinal(); + } + return ords; + } + static boolean isBasicTypeChar(char c) { + return "LIJFDV".indexOf(c) >= 0; + } + static boolean isArgBasicTypeChar(char c) { + return "LIJFD".indexOf(c) >= 0; + } + + static { assert(checkBasicType()); } + private static boolean checkBasicType() { + for (int i = 0; i < ARG_TYPE_LIMIT; i++) { + assert ARG_TYPES[i].ordinal() == i; + assert ARG_TYPES[i] == ALL_TYPES[i]; + } + for (int i = 0; i < TYPE_LIMIT; i++) { + assert ALL_TYPES[i].ordinal() == i; + } + assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE; + assert !Arrays.asList(ARG_TYPES).contains(V_TYPE); + return true; + } + } + LambdaForm(String debugName, int arity, Name[] names, int result) { assert(namesOK(arity, names)); this.arity = arity; this.result = fixResult(result, names); this.names = names.clone(); - this.debugName = debugName; - normalize(); + this.debugName = fixDebugName(debugName); + int maxOutArity = normalize(); + if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) { + // Cannot use LF interpreter on very high arity expressions. + assert(maxOutArity <= MethodType.MAX_JVM_ARITY); + compileToBytecode(); + } } LambdaForm(String debugName, @@ -168,12 +284,12 @@ // Called only from getPreparedForm. assert(isValidSignature(sig)); this.arity = signatureArity(sig); - this.result = (signatureReturn(sig) == 'V' ? -1 : arity); + this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity); this.names = buildEmptyNames(arity, sig); this.debugName = "LF.zero"; assert(nameRefsAreLegal()); assert(isEmpty()); - assert(sig.equals(basicTypeSignature())); + assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature(); } private static Name[] buildEmptyNames(int arity, String basicTypeSignature) { @@ -181,22 +297,53 @@ int resultPos = arity + 1; // skip '_' if (arity < 0 || basicTypeSignature.length() != resultPos+1) throw new IllegalArgumentException("bad arity for "+basicTypeSignature); - int numRes = (basicTypeSignature.charAt(resultPos) == 'V' ? 0 : 1); + int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1); Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity)); for (int i = 0; i < numRes; i++) { - names[arity + i] = constantZero(arity + i, basicTypeSignature.charAt(resultPos + i)); + Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i)))); + names[arity + i] = zero.newIndex(arity + i); } return names; } private static int fixResult(int result, Name[] names) { - if (result >= 0) { - if (names[result].type == 'V') - return -1; - } else if (result == LAST_RESULT) { - return names.length - 1; + if (result == LAST_RESULT) + result = names.length - 1; // might still be void + if (result >= 0 && names[result].type == V_TYPE) + result = VOID_RESULT; + return result; + } + + private static String fixDebugName(String debugName) { + if (DEBUG_NAME_COUNTERS != null) { + int under = debugName.indexOf('_'); + int length = debugName.length(); + if (under < 0) under = length; + String debugNameStem = debugName.substring(0, under); + Integer ctr; + synchronized (DEBUG_NAME_COUNTERS) { + ctr = DEBUG_NAME_COUNTERS.get(debugNameStem); + if (ctr == null) ctr = 0; + DEBUG_NAME_COUNTERS.put(debugNameStem, ctr+1); + } + StringBuilder buf = new StringBuilder(debugNameStem); + buf.append('_'); + int leadingZero = buf.length(); + buf.append((int) ctr); + for (int i = buf.length() - leadingZero; i < 3; i++) + buf.insert(leadingZero, '0'); + if (under < length) { + ++under; // skip "_" + while (under < length && Character.isDigit(debugName.charAt(under))) { + ++under; + } + if (under < length && debugName.charAt(under) == '_') ++under; + if (under < length) + buf.append('_').append(debugName, under, length); + } + return buf.toString(); } - return result; + return debugName; } private static boolean namesOK(int arity, Name[] names) { @@ -211,9 +358,12 @@ return true; } - /** Renumber and/or replace params so that they are interned and canonically numbered. */ - private void normalize() { + /** Renumber and/or replace params so that they are interned and canonically numbered. + * @return maximum argument list length among the names (since we have to pass over them anyway) + */ + private int normalize() { Name[] oldNames = null; + int maxOutArity = 0; int changesStart = 0; for (int i = 0; i < names.length; i++) { Name n = names[i]; @@ -224,6 +374,8 @@ } names[i] = n.cloneWithIndex(i); } + if (n.arguments != null && maxOutArity < n.arguments.length) + maxOutArity = n.arguments.length; } if (oldNames != null) { int startFixing = arity; @@ -250,6 +402,7 @@ } assert(nameRefsAreLegal()); } + return maxOutArity; } /** @@ -261,7 +414,7 @@ * This allows Name references to be freely reused to construct * fresh lambdas, without confusion. */ - private boolean nameRefsAreLegal() { + boolean nameRefsAreLegal() { assert(arity >= 0 && arity <= names.length); assert(result >= -1 && result < names.length); // Do all names possess an index consistent with their local definition order? @@ -294,16 +447,28 @@ // } /** Report the return type. */ - char returnType() { - if (result < 0) return 'V'; + BasicType returnType() { + if (result < 0) return V_TYPE; Name n = names[result]; return n.type; } /** Report the N-th argument type. */ - char parameterType(int n) { + BasicType parameterType(int n) { + return parameter(n).type; + } + + /** Report the N-th argument name. */ + Name parameter(int n) { assert(n < arity); - return names[n].type; + Name param = names[n]; + assert(param.isParam()); + return param; + } + + /** Report the N-th argument type constraint. */ + Object parameterConstraint(int n) { + return parameter(n).constraint; } /** Report the arity. */ @@ -311,6 +476,11 @@ return arity; } + /** Report the number of expressions (non-parameter names). */ + int expressionCount() { + return names.length - arity; + } + /** Return the method type corresponding to my basic type signature. */ MethodType methodType() { return signatureType(basicTypeSignature()); @@ -319,15 +489,15 @@ final String basicTypeSignature() { StringBuilder buf = new StringBuilder(arity() + 3); for (int i = 0, a = arity(); i < a; i++) - buf.append(parameterType(i)); - return buf.append('_').append(returnType()).toString(); + buf.append(parameterType(i).basicTypeChar()); + return buf.append('_').append(returnType().basicTypeChar()).toString(); } static int signatureArity(String sig) { assert(isValidSignature(sig)); return sig.indexOf('_'); } - static char signatureReturn(String sig) { - return sig.charAt(signatureArity(sig)+1); + static BasicType signatureReturn(String sig) { + return basicType(sig.charAt(signatureArity(sig) + 1)); } static boolean isValidSignature(String sig) { int arity = sig.indexOf('_'); @@ -339,27 +509,15 @@ char c = sig.charAt(i); if (c == 'V') return (i == siglen - 1 && arity == siglen - 2); - if (ALL_TYPES.indexOf(c) < 0) return false; // must be [LIJFD] + if (!isArgBasicTypeChar(c)) return false; // must be [LIJFD] } return true; // [LIJFD]*_[LIJFDV] } - static Class<?> typeClass(char t) { - switch (t) { - case 'I': return int.class; - case 'J': return long.class; - case 'F': return float.class; - case 'D': return double.class; - case 'L': return Object.class; - case 'V': return void.class; - default: assert false; - } - return null; - } static MethodType signatureType(String sig) { Class<?>[] ptypes = new Class<?>[signatureArity(sig)]; for (int i = 0; i < ptypes.length; i++) - ptypes[i] = typeClass(sig.charAt(i)); - Class<?> rtype = typeClass(signatureReturn(sig)); + ptypes[i] = basicType(sig.charAt(i)).btClass; + Class<?> rtype = signatureReturn(sig).btClass; return MethodType.methodType(rtype, ptypes); } @@ -457,21 +615,12 @@ isCompiled = true; return vmentry; } catch (Error | Exception ex) { - throw newInternalError("compileToBytecode", ex); + throw newInternalError(this.toString(), ex); } } - private static final ConcurrentHashMap<String,LambdaForm> PREPARED_FORMS; - static { - int capacity = 512; // expect many distinct signatures over time - float loadFactor = 0.75f; // normal default - int writers = 1; - PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers); - } - - private static Map<String,LambdaForm> computeInitialPreparedForms() { + private static void computeInitialPreparedForms() { // Find all predefined invokers and associate them with canonical empty lambda forms. - HashMap<String,LambdaForm> forms = new HashMap<>(); for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) { if (!m.isStatic() || !m.isPackage()) continue; MethodType mt = m.getMethodType(); @@ -482,13 +631,9 @@ assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_')))); LambdaForm form = new LambdaForm(sig); form.vmentry = m; - form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form); - // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only - forms.put(sig, form); + form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form); } } - //System.out.println("computeInitialPreparedForms => "+forms); - return forms; } // Set this false to disable use of the interpret_L methods defined in this file. @@ -522,13 +667,11 @@ } private static LambdaForm getPreparedForm(String sig) { MethodType mtype = signatureType(sig); - //LambdaForm prep = PREPARED_FORMS.get(sig); LambdaForm prep = mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET); if (prep != null) return prep; assert(isValidSignature(sig)); prep = new LambdaForm(sig); prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig); - //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep); return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep); } @@ -543,21 +686,21 @@ assert(mt.parameterCount() == arity-1); for (int i = 0; i < av.length; i++) { Class<?> pt = (i == 0 ? MethodHandle.class : mt.parameterType(i-1)); - assert(valueMatches(sig.charAt(i), pt, av[i])); + assert(valueMatches(basicType(sig.charAt(i)), pt, av[i])); } return true; } - private static boolean valueMatches(char tc, Class<?> type, Object x) { + private static boolean valueMatches(BasicType tc, Class<?> type, Object x) { // The following line is needed because (...)void method handles can use non-void invokers - if (type == void.class) tc = 'V'; // can drop any kind of value + if (type == void.class) tc = V_TYPE; // can drop any kind of value assert tc == basicType(type) : tc + " == basicType(" + type + ")=" + basicType(type); switch (tc) { - case 'I': assert checkInt(type, x) : "checkInt(" + type + "," + x +")"; break; - case 'J': assert x instanceof Long : "instanceof Long: " + x; break; - case 'F': assert x instanceof Float : "instanceof Float: " + x; break; - case 'D': assert x instanceof Double : "instanceof Double: " + x; break; - case 'L': assert checkRef(type, x) : "checkRef(" + type + "," + x + ")"; break; - case 'V': break; // allow anything here; will be dropped + case I_TYPE: assert checkInt(type, x) : "checkInt(" + type + "," + x +")"; break; + case J_TYPE: assert x instanceof Long : "instanceof Long: " + x; break; + case F_TYPE: assert x instanceof Float : "instanceof Float: " + x; break; + case D_TYPE: assert x instanceof Double : "instanceof Double: " + x; break; + case L_TYPE: assert checkRef(type, x) : "checkRef(" + type + "," + x + ")"; break; + case V_TYPE: break; // allow anything here; will be dropped default: assert(false); } return true; @@ -584,10 +727,7 @@ /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */ private static final int COMPILE_THRESHOLD; static { - if (MethodHandleStatics.COMPILE_THRESHOLD != null) - COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD; - else - COMPILE_THRESHOLD = 30; // default value + COMPILE_THRESHOLD = Math.max(-1, MethodHandleStatics.COMPILE_THRESHOLD); } private int invocationCounter = 0; @@ -603,7 +743,9 @@ for (int i = argumentValues.length; i < values.length; i++) { values[i] = interpretName(names[i], values); } - return (result < 0) ? null : values[result]; + Object rv = (result < 0) ? null : values[result]; + assert(resultCheck(argumentValues, rv)); + return rv; } @Hidden @@ -660,28 +802,6 @@ return rval; } - //** This transform is applied (statically) to every name.function. */ - /* - private static MethodHandle eraseSubwordTypes(MethodHandle mh) { - MethodType mt = mh.type(); - if (mt.hasPrimitives()) { - mt = mt.changeReturnType(eraseSubwordType(mt.returnType())); - for (int i = 0; i < mt.parameterCount(); i++) { - mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i))); - } - mh = MethodHandles.explicitCastArguments(mh, mt); - } - return mh; - } - private static Class<?> eraseSubwordType(Class<?> type) { - if (!type.isPrimitive()) return type; - if (type == int.class) return type; - Wrapper w = Wrapper.forPrimitiveType(type); - if (w.isSubwordOrInt()) return int.class; - return type; - } - */ - static void traceInterpreter(String event, Object obj, Object... args) { if (TRACE_INTERPRETER) { System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : "")); @@ -694,8 +814,16 @@ assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length"; // also check that the leading (receiver) argument is somehow bound to this LF: assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0]; - assert(((MethodHandle)argumentValues[0]).internalForm() == this); + MethodHandle mh = (MethodHandle) argumentValues[0]; + assert(mh.internalForm() == this); // note: argument #0 could also be an interface wrapper, in the future + argumentTypesMatch(basicTypeSignature(), argumentValues); + return true; + } + private boolean resultCheck(Object[] argumentValues, Object result) { + MethodHandle mh = (MethodHandle) argumentValues[0]; + MethodType mt = mh.type(); + assert(valueMatches(returnType(), mt.returnType(), result)); return true; } @@ -714,7 +842,7 @@ if (i == arity) buf.append(")=>{"); Name n = names[i]; if (i >= arity) buf.append("\n "); - buf.append(n); + buf.append(n.paramString()); if (i < arity) { if (i+1 < arity) buf.append(","); continue; @@ -722,6 +850,7 @@ buf.append("=").append(n.exprString()); buf.append(";"); } + if (arity == names.length) buf.append(")=>{"); buf.append(result < 0 ? "void" : names[result]).append("}"); if (TRACE_INTERPRETER) { // Extra verbosity: @@ -731,135 +860,19 @@ return buf.toString(); } - /** - * Apply immediate binding for a Name in this form indicated by its position relative to the form. - * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not - * accepted as valid. - */ - LambdaForm bindImmediate(int pos, char basicType, Object value) { - // must be an argument, and the types must match - assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value); - - int arity2 = arity - 1; - Name[] names2 = new Name[names.length - 1]; - for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2 - Name n = names[r]; - if (n.isParam()) { - if (n.index == pos) { - // do not copy over the argument that is to be replaced with a literal, - // but adjust the write index - --w; - } else { - names2[w] = new Name(w, n.type); - } - } else { - Object[] arguments2 = new Object[n.arguments.length]; - for (int i = 0; i < n.arguments.length; ++i) { - Object arg = n.arguments[i]; - if (arg instanceof Name) { - int ni = ((Name) arg).index; - if (ni == pos) { - arguments2[i] = value; - } else if (ni < pos) { - // replacement position not yet passed - arguments2[i] = names2[ni]; - } else { - // replacement position passed - arguments2[i] = names2[ni - 1]; - } - } else { - arguments2[i] = arg; - } - } - names2[w] = new Name(n.function, arguments2); - names2[w].initIndex(w); - } - } - - int result2 = result == -1 ? -1 : result - 1; - return new LambdaForm(debugName, arity2, names2, result2); + @Override + public boolean equals(Object obj) { + return obj instanceof LambdaForm && equals((LambdaForm)obj); } - - LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) { - Name name = names[namePos]; - BoundMethodHandle.SpeciesData newData = oldData.extendWithType(name.type); - return bind(name, newData.getterName(names[0], oldData.fieldCount()), oldData, newData); + public boolean equals(LambdaForm that) { + if (this.result != that.result) return false; + return Arrays.equals(this.names, that.names); } - LambdaForm bind(Name name, Name binding, - BoundMethodHandle.SpeciesData oldData, - BoundMethodHandle.SpeciesData newData) { - int pos = name.index; - assert(name.isParam()); - assert(!binding.isParam()); - assert(name.type == binding.type); - assert(0 <= pos && pos < arity && names[pos] == name); - assert(binding.function.memberDeclaringClassOrNull() == newData.clazz); - assert(oldData.getters.length == newData.getters.length-1); - if (bindCache != null) { - LambdaForm form = bindCache[pos]; - if (form != null) { - assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>"; - return form; - } - } else { - bindCache = new LambdaForm[arity]; - } - assert(nameRefsAreLegal()); - int arity2 = arity-1; - Name[] names2 = names.clone(); - names2[pos] = binding; // we might move this in a moment - - // The newly created LF will run with a different BMH. - // Switch over any pre-existing BMH field references to the new BMH class. - int firstOldRef = -1; - for (int i = 0; i < names2.length; i++) { - Name n = names[i]; - if (n.function != null && - n.function.memberDeclaringClassOrNull() == oldData.clazz) { - MethodHandle oldGetter = n.function.resolvedHandle; - MethodHandle newGetter = null; - for (int j = 0; j < oldData.getters.length; j++) { - if (oldGetter == oldData.getters[j]) - newGetter = newData.getters[j]; - } - if (newGetter != null) { - if (firstOldRef < 0) firstOldRef = i; - Name n2 = new Name(newGetter, n.arguments); - names2[i] = n2; - } - } - } - - // Walk over the new list of names once, in forward order. - // Replace references to 'name' with 'binding'. - // Replace data structure references to the old BMH species with the new. - // This might cause a ripple effect, but it will settle in one pass. - assert(firstOldRef < 0 || firstOldRef > pos); - for (int i = pos+1; i < names2.length; i++) { - if (i <= arity2) continue; - names2[i] = names2[i].replaceNames(names, names2, pos, i); - } - - // (a0, a1, name=a2, a3, a4) => (a0, a1, a3, a4, binding) - int insPos = pos; - for (; insPos+1 < names2.length; insPos++) { - Name n = names2[insPos+1]; - if (n.isSiblingBindingBefore(binding)) { - names2[insPos] = n; - } else { - break; - } - } - names2[insPos] = binding; - - // Since we moved some stuff, maybe update the result reference: - int result2 = result; - if (result2 == pos) - result2 = insPos; - else if (result2 > pos && result2 <= insPos) - result2 -= 1; - - return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2); + public int hashCode() { + return result + 31 * Arrays.hashCode(names); + } + LambdaFormEditor editor() { + return LambdaFormEditor.lambdaFormEditor(this); } boolean contains(Name name) { @@ -874,17 +887,17 @@ return false; } - LambdaForm addArguments(int pos, char... types) { - assert(pos <= arity); + LambdaForm addArguments(int pos, BasicType... types) { + // names array has MH in slot 0; skip it. + int argpos = pos + 1; + assert(argpos <= arity); int length = names.length; int inTypes = types.length; Name[] names2 = Arrays.copyOf(names, length + inTypes); int arity2 = arity + inTypes; int result2 = result; - if (result2 >= arity) + if (result2 >= argpos) result2 += inTypes; - // names array has MH in slot 0; skip it. - int argpos = pos + 1; // Note: The LF constructor will rename names2[argpos...]. // Make space for new arguments (shift temporaries). System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos); @@ -895,13 +908,10 @@ } LambdaForm addArguments(int pos, List<Class<?>> types) { - char[] basicTypes = new char[types.size()]; - for (int i = 0; i < basicTypes.length; i++) - basicTypes[i] = basicType(types.get(i)); - return addArguments(pos, basicTypes); + return addArguments(pos, basicTypes(types)); } - LambdaForm permuteArguments(int skip, int[] reorder, char[] types) { + LambdaForm permuteArguments(int skip, int[] reorder, BasicType[] types) { // Note: When inArg = reorder[outArg], outArg is fed by a copy of inArg. // The types are the types of the new (incoming) arguments. int length = names.length; @@ -960,7 +970,7 @@ return new LambdaForm(debugName, arity2, names2, result2); } - static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) { + static boolean permutedTypesMatch(int[] reorder, BasicType[] types, Name[] names, int skip) { int inTypes = types.length; int outArgs = reorder.length; for (int i = 0; i < outArgs; i++) { @@ -980,8 +990,9 @@ } NamedFunction(MemberName member, MethodHandle resolvedHandle) { this.member = member; - //resolvedHandle = eraseSubwordTypes(resolvedHandle); this.resolvedHandle = resolvedHandle; + // The following assert is almost always correct, but will fail for corner cases, such as PrivateInvokeTest. + //assert(!isInvokeBasic()); } NamedFunction(MethodType basicInvokerType) { assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType; @@ -992,6 +1003,13 @@ // necessary to pass BigArityTest this.member = Invokers.invokeBasicMethod(basicInvokerType); } + assert(isInvokeBasic()); + } + + private boolean isInvokeBasic() { + return member != null && + member.isMethodHandleInvoke() && + "invokeBasic".equals(member.getName()); } // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc. @@ -1044,10 +1062,10 @@ String sig = m.getName().substring("invoke_".length()); int arity = LambdaForm.signatureArity(sig); MethodType srcType = MethodType.genericMethodType(arity); - if (LambdaForm.signatureReturn(sig) == 'V') + if (LambdaForm.signatureReturn(sig) == V_TYPE) srcType = srcType.changeReturnType(void.class); MethodTypeForm typeForm = srcType.form(); - typeForm.namedFunctionInvoker = DirectMethodHandle.make(m); + typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m)); } } } @@ -1057,85 +1075,104 @@ /** void return type invokers. */ @Hidden static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 0); + assert(arityCheck(0, void.class, mh, a)); mh.invokeBasic(); return null; } @Hidden static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 1); + assert(arityCheck(1, void.class, mh, a)); mh.invokeBasic(a[0]); return null; } @Hidden static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 2); + assert(arityCheck(2, void.class, mh, a)); mh.invokeBasic(a[0], a[1]); return null; } @Hidden static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 3); + assert(arityCheck(3, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2]); return null; } @Hidden static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 4); + assert(arityCheck(4, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2], a[3]); return null; } @Hidden static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 5); + assert(arityCheck(5, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); return null; } /** Object return type invokers. */ @Hidden static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 0); + assert(arityCheck(0, mh, a)); return mh.invokeBasic(); } @Hidden static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 1); + assert(arityCheck(1, mh, a)); return mh.invokeBasic(a[0]); } @Hidden static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 2); + assert(arityCheck(2, mh, a)); return mh.invokeBasic(a[0], a[1]); } @Hidden static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 3); + assert(arityCheck(3, mh, a)); return mh.invokeBasic(a[0], a[1], a[2]); } @Hidden static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 4); + assert(arityCheck(4, mh, a)); return mh.invokeBasic(a[0], a[1], a[2], a[3]); } @Hidden static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 5); + assert(arityCheck(5, mh, a)); return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); } + private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) { + return arityCheck(arity, Object.class, mh, a); + } + private static boolean arityCheck(int arity, Class<?> rtype, MethodHandle mh, Object[] a) { + assert(a.length == arity) + : Arrays.asList(a.length, arity); + assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype)) + : Arrays.asList(mh, rtype, arity); + MemberName member = mh.internalMemberName(); + if (member != null && member.getName().equals("invokeBasic") && member.isMethodHandleInvoke()) { + assert(arity > 0); + assert(a[0] instanceof MethodHandle); + MethodHandle mh2 = (MethodHandle) a[0]; + assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype)) + : Arrays.asList(member, mh2, rtype, arity); + } + return true; + } static final MethodType INVOKER_METHOD_TYPE = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); private static MethodHandle computeInvoker(MethodTypeForm typeForm) { - MethodHandle mh = typeForm.namedFunctionInvoker; + typeForm = typeForm.basicType().form(); // normalize to basic type + MethodHandle mh = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh != null) return mh; MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm); // this could take a while mh = DirectMethodHandle.make(invoker); - MethodHandle mh2 = typeForm.namedFunctionInvoker; + MethodHandle mh2 = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh2 != null) return mh2; // benign race if (!mh.type().equals(INVOKER_METHOD_TYPE)) - throw new InternalError(mh.debugString()); - return typeForm.namedFunctionInvoker = mh; + throw newInternalError(mh.debugString()); + return typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, mh); } @Hidden @@ -1193,11 +1230,6 @@ return true; } - String basicTypeSignature() { - //return LambdaForm.basicTypeSignature(resolvedHandle.type()); - return LambdaForm.basicTypeSignature(methodType()); - } - MethodType methodType() { if (resolvedHandle != null) return resolvedHandle.type(); @@ -1224,18 +1256,15 @@ return (member == null) ? null : member.getDeclaringClass(); } - char returnType() { + BasicType returnType() { return basicType(methodType().returnType()); } - char parameterType(int n) { + BasicType parameterType(int n) { return basicType(methodType().parameterType(n)); } int arity() { - //int siglen = member.getMethodType().parameterCount(); - //if (!member.isStatic()) siglen += 1; - //return siglen; return methodType().parameterCount(); } @@ -1243,74 +1272,109 @@ if (member == null) return String.valueOf(resolvedHandle); return member.getDeclaringClass().getSimpleName()+"."+member.getName(); } + + public boolean isIdentity() { + return this.equals(identity(returnType())); + } + + public boolean isConstantZero() { + return this.equals(constantZero(returnType())); + } + + public MethodHandleImpl.Intrinsic intrinsicName() { + return resolvedHandle == null ? MethodHandleImpl.Intrinsic.NONE + : resolvedHandle.intrinsicName(); + } } - void resolve() { - for (Name n : names) n.resolve(); - } - - public static char basicType(Class<?> type) { - char c = Wrapper.basicTypeChar(type); - if ("ZBSC".indexOf(c) >= 0) c = 'I'; - assert("LIJFDV".indexOf(c) >= 0); - return c; - } - public static char[] basicTypes(List<Class<?>> types) { - char[] btypes = new char[types.size()]; - for (int i = 0; i < btypes.length; i++) { - btypes[i] = basicType(types.get(i)); - } - return btypes; - } public static String basicTypeSignature(MethodType type) { char[] sig = new char[type.parameterCount() + 2]; int sigp = 0; for (Class<?> pt : type.parameterList()) { - sig[sigp++] = basicType(pt); + sig[sigp++] = basicTypeChar(pt); } sig[sigp++] = '_'; - sig[sigp++] = basicType(type.returnType()); + sig[sigp++] = basicTypeChar(type.returnType()); assert(sigp == sig.length); return String.valueOf(sig); } + public static String shortenSignature(String signature) { + // Hack to make signatures more readable when they show up in method names. + final int NO_CHAR = -1, MIN_RUN = 3; + int c0, c1 = NO_CHAR, c1reps = 0; + StringBuilder buf = null; + int len = signature.length(); + if (len < MIN_RUN) return signature; + for (int i = 0; i <= len; i++) { + // shift in the next char: + c0 = c1; c1 = (i == len ? NO_CHAR : signature.charAt(i)); + if (c1 == c0) { ++c1reps; continue; } + // shift in the next count: + int c0reps = c1reps; c1reps = 1; + // end of a character run + if (c0reps < MIN_RUN) { + if (buf != null) { + while (--c0reps >= 0) + buf.append((char)c0); + } + continue; + } + // found three or more in a row + if (buf == null) + buf = new StringBuilder().append(signature, 0, i - c0reps); + buf.append((char)c0).append(c0reps); + } + return (buf == null) ? signature : buf.toString(); + } static final class Name { - final char type; + final BasicType type; private short index; final NamedFunction function; + final Object constraint; // additional type information, if not null @Stable final Object[] arguments; - private Name(int index, char type, NamedFunction function, Object[] arguments) { + private Name(int index, BasicType type, NamedFunction function, Object[] arguments) { this.index = (short)index; this.type = type; this.function = function; this.arguments = arguments; + this.constraint = null; assert(this.index == index); } + private Name(Name that, Object constraint) { + this.index = that.index; + this.type = that.type; + this.function = that.function; + this.arguments = that.arguments; + this.constraint = constraint; + assert(constraint == null || isParam()); // only params have constraints + assert(constraint == null || constraint instanceof BoundMethodHandle.SpeciesData || constraint instanceof Class); + } Name(MethodHandle function, Object... arguments) { this(new NamedFunction(function), arguments); } Name(MethodType functionType, Object... arguments) { this(new NamedFunction(functionType), arguments); - assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == 'L'); + assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == L_TYPE); } Name(MemberName function, Object... arguments) { this(new NamedFunction(function), arguments); } Name(NamedFunction function, Object... arguments) { - this(-1, function.returnType(), function, arguments = arguments.clone()); + this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class)); assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString(); for (int i = 0; i < arguments.length; i++) assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString(); } - Name(int index, char type) { + /** Create a raw parameter of the given type, with an expected index. */ + Name(int index, BasicType type) { this(index, type, null, null); } - Name(char type) { - this(-1, type); - } + /** Create a raw parameter of the given type. */ + Name(BasicType type) { this(-1, type); } - char type() { return type; } + BasicType type() { return type; } int index() { return index; } boolean initIndex(int i) { if (index != i) { @@ -1319,7 +1383,9 @@ } return true; } - + char typeChar() { + return type.btChar; + } void resolve() { if (function != null) @@ -1332,7 +1398,11 @@ } Name cloneWithIndex(int i) { Object[] newArguments = (arguments == null) ? null : arguments.clone(); - return new Name(i, type, function, newArguments); + return new Name(i, type, function, newArguments).withConstraint(constraint); + } + Name withConstraint(Object constraint) { + if (constraint == this.constraint) return this; + return new Name(this, constraint); } Name replaceName(Name oldName, Name newName) { // FIXME: use replaceNames uniformly if (oldName == newName) return this; @@ -1352,7 +1422,11 @@ if (!replaced) return this; return new Name(function, arguments); } + /** In the arguments of this Name, replace oldNames[i] pairwise by newNames[i]. + * Limit such replacements to {@code start<=i<end}. Return possibly changed self. + */ Name replaceNames(Name[] oldNames, Name[] newNames, int start, int end) { + if (start >= end) return this; @SuppressWarnings("LocalVariableHidesMemberVariable") Object[] arguments = this.arguments; boolean replaced = false; @@ -1397,18 +1471,26 @@ return function == null; } boolean isConstantZero() { - return !isParam() && arguments.length == 0 && function.equals(constantZero(0, type).function); + return !isParam() && arguments.length == 0 && function.isConstantZero(); } public String toString() { - return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+type; + return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+typeChar(); } public String debugString() { - String s = toString(); + String s = paramString(); return (function == null) ? s : s + "=" + exprString(); } + public String paramString() { + String s = toString(); + Object c = constraint; + if (c == null) + return s; + if (c instanceof Class) c = ((Class<?>)c).getSimpleName(); + return s + "/" + c; + } public String exprString() { - if (function == null) return "null"; + if (function == null) return toString(); StringBuilder buf = new StringBuilder(function.toString()); buf.append("("); String cma = ""; @@ -1423,48 +1505,20 @@ return buf.toString(); } - private static boolean typesMatch(char parameterType, Object object) { + static boolean typesMatch(BasicType parameterType, Object object) { if (object instanceof Name) { return ((Name)object).type == parameterType; } switch (parameterType) { - case 'I': return object instanceof Integer; - case 'J': return object instanceof Long; - case 'F': return object instanceof Float; - case 'D': return object instanceof Double; + case I_TYPE: return object instanceof Integer; + case J_TYPE: return object instanceof Long; + case F_TYPE: return object instanceof Float; + case D_TYPE: return object instanceof Double; } - assert(parameterType == 'L'); + assert(parameterType == L_TYPE); return true; } - /** - * Does this Name precede the given binding node in some canonical order? - * This predicate is used to order data bindings (via insertion sort) - * with some stability. - */ - boolean isSiblingBindingBefore(Name binding) { - assert(!binding.isParam()); - if (isParam()) return true; - if (function.equals(binding.function) && - arguments.length == binding.arguments.length) { - boolean sawInt = false; - for (int i = 0; i < arguments.length; i++) { - Object a1 = arguments[i]; - Object a2 = binding.arguments[i]; - if (!a1.equals(a2)) { - if (a1 instanceof Integer && a2 instanceof Integer) { - if (sawInt) continue; - sawInt = true; - if ((int)a1 < (int)a2) continue; // still might be true - } - return false; - } - } - return sawInt; - } - return false; - } - /** Return the index of the last occurrence of n in the argument array. * Return -1 if the name is not used. */ @@ -1510,7 +1564,7 @@ @Override public int hashCode() { if (isParam()) - return index | (type << 8); + return index | (type.ordinal() << 8); return function.hashCode() ^ Arrays.hashCode(arguments); } } @@ -1545,14 +1599,17 @@ } static Name argument(int which, char type) { - int tn = ALL_TYPES.indexOf(type); - if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT) + return argument(which, basicType(type)); + } + static Name argument(int which, BasicType type) { + if (which >= INTERNED_ARGUMENT_LIMIT) return new Name(which, type); - return INTERNED_ARGUMENTS[tn][which]; + retu