diff options
author | asaha <none@none> | 2015-04-09 12:57:26 -0700 |
---|---|---|
committer | asaha <none@none> | 2015-04-09 12:57:26 -0700 |
commit | cc41475ab9760c94bb807fd711aa05ef0256a6ae (patch) | |
tree | 5f60f139da5e78215b3c8427a90107c26d7b8f6d | |
parent | 21132f61eb5701c130b715fecea8fc21675155b6 (diff) | |
parent | 544330ea8b2d8261033794cde47aa15c05757f5b (diff) |
Mergejdk8u45-b01
82 files changed, 2457 insertions, 594 deletions
@@ -365,4 +365,5 @@ ba80109a9b3eb92b56012c9ec3aafd9aee2efa69 jdk8u40-b13 ffc348308de2e872f5d510d440604c3726a67a18 jdk8u40-b14 31dac938108da722c56a0526fba7f6ae84773056 jdk8u40-b15 9dc67d03e6e540f646f27092ed23e94e95fa789e jdk8u40-b16 +fc4f5546417071c70cffd89ca83302309f6f7da9 jdk8u40-b17 1ecc234bd38950a2bc047aa253a5e803f0836a4e jdk8u45-b00 diff --git a/make/CompileJavaClasses.gmk b/make/CompileJavaClasses.gmk index 93ca5a5f1..865eb24fd 100644 --- a/make/CompileJavaClasses.gmk +++ b/make/CompileJavaClasses.gmk @@ -59,7 +59,6 @@ endif ifndef OPENJDK # 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 diff --git a/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java b/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java index c9a86b851..5345828c4 100644 --- a/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java +++ b/src/macosx/classes/com/apple/laf/AquaComboBoxUI.java @@ -486,10 +486,15 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable { // This is somewhat messy. The difference here from BasicComboBoxUI.EnterAction is that // arrow up or down does not automatically select the - private static final Action triggerSelectionAction = new AbstractAction() { + private final Action triggerSelectionAction = new AbstractAction() { public void actionPerformed(final ActionEvent e) { triggerSelectionEvent((JComboBox)e.getSource(), e); } + + @Override + public boolean isEnabled() { + return comboBox.isPopupVisible() && super.isEnabled(); + } }; private static final Action toggleSelectionAction = new AbstractAction() { diff --git a/src/macosx/classes/com/apple/laf/AquaIcon.java b/src/macosx/classes/com/apple/laf/AquaIcon.java index 4af5599b6..3a24c35e2 100644 --- a/src/macosx/classes/com/apple/laf/AquaIcon.java +++ b/src/macosx/classes/com/apple/laf/AquaIcon.java @@ -62,7 +62,7 @@ public class AquaIcon { if (w <= 0 || h <= 0) return null; // This could be any kind of icon, so we need to make a buffer for it, draw it and then pass the new image off to appkit. - final BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + final BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); final Graphics g = image.getGraphics(); i.paintIcon(null, g, 0, 0); g.dispose(); diff --git a/src/macosx/classes/com/apple/laf/AquaImageFactory.java b/src/macosx/classes/com/apple/laf/AquaImageFactory.java index d19486395..28977cb6e 100644 --- a/src/macosx/classes/com/apple/laf/AquaImageFactory.java +++ b/src/macosx/classes/com/apple/laf/AquaImageFactory.java @@ -129,7 +129,7 @@ public class AquaImageFactory { }; final BufferedImage image = new BufferedImage(scaledAlertIconSize, - scaledAlertIconSize, BufferedImage.TYPE_INT_ARGB); + scaledAlertIconSize, BufferedImage.TYPE_INT_ARGB_PRE); final Graphics g = image.getGraphics(); g.drawImage(background, 0, 0, scaledAlertIconSize, scaledAlertIconSize, null); diff --git a/src/macosx/classes/com/apple/laf/AquaNativeResources.java b/src/macosx/classes/com/apple/laf/AquaNativeResources.java index e0e7c41db..f87037ed6 100644 --- a/src/macosx/classes/com/apple/laf/AquaNativeResources.java +++ b/src/macosx/classes/com/apple/laf/AquaNativeResources.java @@ -66,11 +66,12 @@ public class AquaNativeResources { } static BufferedImage getRadioButtonSizerImage() { - final BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB); + final BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB_PRE); Graphics g = img.getGraphics(); g.setColor(Color.pink); g.fillRect(0, 0, 20, 20); + g.dispose(); return img; } diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index a055acfea..9cd88ee29 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -568,7 +568,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo CWrapper.NSWindow.makeKeyWindow(nsWindowPtr); } } else { + // immediately hide the window CWrapper.NSWindow.orderOut(nsWindowPtr); + // process the close + CWrapper.NSWindow.close(nsWindowPtr); } } else { // otherwise, put it in a proper z-order diff --git a/src/macosx/classes/sun/lwawt/macosx/CWrapper.java b/src/macosx/classes/sun/lwawt/macosx/CWrapper.java index f0fec624d..516b8de15 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CWrapper.java +++ b/src/macosx/classes/sun/lwawt/macosx/CWrapper.java @@ -54,8 +54,26 @@ final class CWrapper { static native void orderFront(long window); static native void orderFrontRegardless(long window); static native void orderWindow(long window, int ordered, long relativeTo); + + /** + * Removes the window from the screen. + * + * @param window the pointer of the NSWindow + */ static native void orderOut(long window); + /** + * Removes the window from the screen and releases it. According to + * documentation this method should be similar to {@link #orderOut}, + * because we use ReleasedWhenClosed:NO, so the window shouldn't be + * released. But the close method works differently, for example it + * close the space if the window was in the full screen via + * {@link CPlatformWindow#toggleFullScreen()}. + * + * @param window the pointer of the NSWindow + */ + static native void close(long window); + static native void addChildWindow(long parent, long child, int ordered); static native void removeChildWindow(long parent, long child); diff --git a/src/macosx/native/sun/awt/CWrapper.m b/src/macosx/native/sun/awt/CWrapper.m index bf0d6b2fc..bb14ef5ae 100644 --- a/src/macosx/native/sun/awt/CWrapper.m +++ b/src/macosx/native/sun/awt/CWrapper.m @@ -175,6 +175,23 @@ JNF_COCOA_EXIT(env); /* * Class: sun_lwawt_macosx_CWrapper$NSWindow + * Method: close + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_sun_lwawt_macosx_CWrapper_00024NSWindow_close + (JNIEnv *env, jclass cls, jlong windowPtr) +{ +JNF_COCOA_ENTER(env); + NSWindow *window = (NSWindow *)jlong_to_ptr(windowPtr); + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + [window close]; + }]; +JNF_COCOA_EXIT(env); +} + +/* + * Class: sun_lwawt_macosx_CWrapper$NSWindow * Method: orderFrontRegardless * Signature: (J)V */ diff --git a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m index 647042f57..1ad7d042e 100644 --- a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m +++ b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m @@ -72,7 +72,9 @@ OGLGC_DestroyOGLGraphicsConfig(jlong pConfigInfo) } [pool drain]; free(ctxinfo); + oglc->ctxInfo = NULL; } + cglinfo->context = NULL; } free(cglinfo); diff --git a/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m b/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m index 84c1fb12c..e4dccabcf 100644 --- a/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m +++ b/src/macosx/native/sun/java2d/opengl/CGLSurfaceData.m @@ -187,6 +187,11 @@ OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo) } OGLContext *oglc = cglInfo->context; + if (oglc == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_SetScratchContext: ogl context is null"); + return NULL; + } + CGLCtxInfo *ctxinfo = (CGLCtxInfo *)oglc->ctxInfo; JNF_COCOA_ENTER(env); diff --git a/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java b/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java index a98eea62c..b79847810 100644 --- a/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java +++ b/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java @@ -38,11 +38,13 @@ import java.net.URL; import java.net.MalformedURLException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import sun.awt.AppContext; @@ -102,19 +104,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { private static final String HTML_TEXT_BASE_TYPE = "text/html"; /** - * This constant is passed to flavorToNativeLookup() to indicate that a - * a native should be synthesized, stored, and returned by encoding the - * DataFlavor's MIME type in case if the DataFlavor is not found in - * 'flavorToNative' map. - */ - private static final boolean SYNTHESIZE_IF_NOT_FOUND = true; - - /** * Maps native Strings to Lists of DataFlavors (or base type Strings for * text DataFlavors). * Do not use the field directly, use getNativeToFlavor() instead. */ - private final Map<String, List<DataFlavor>> nativeToFlavor = new HashMap<>(); + private final Map<String, LinkedHashSet<DataFlavor>> nativeToFlavor = new HashMap<>(); /** * Accessor to nativeToFlavor map. Since we use lazy initialization we must @@ -123,7 +117,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * * @return nativeToFlavor */ - private Map<String, List<DataFlavor>> getNativeToFlavor() { + private Map<String, LinkedHashSet<DataFlavor>> getNativeToFlavor() { if (!isMapInitialized) { initSystemFlavorMap(); } @@ -135,7 +129,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * native Strings. * Do not use the field directly, use getFlavorToNative() instead. */ - private final Map<DataFlavor, List<String>> flavorToNative = new HashMap<>(); + private final Map<DataFlavor, LinkedHashSet<String>> flavorToNative = new HashMap<>(); /** * Accessor to flavorToNative map. Since we use lazy initialization we must @@ -144,7 +138,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * * @return flavorToNative */ - private synchronized Map<DataFlavor, List<String>> getFlavorToNative() { + private synchronized Map<DataFlavor, LinkedHashSet<String>> getFlavorToNative() { if (!isMapInitialized) { initSystemFlavorMap(); } @@ -152,21 +146,44 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } /** + * Maps a text DataFlavor primary mime-type to the native. Used only to store + * standard mappings registered in the flavormap.properties + * Do not use this field directly, use getTextTypeToNative() instead. + */ + private Map<String, LinkedHashSet<String>> textTypeToNative = new HashMap<>(); + + /** * Shows if the object has been initialized. */ private boolean isMapInitialized = false; /** + * An accessor to textTypeToNative map. Since we use lazy initialization we + * must use this accessor instead of direct access to the field which may not + * be initialized yet. This method will initialize the field if needed. + * + * @return textTypeToNative + */ + private synchronized Map<String, LinkedHashSet<String>> getTextTypeToNative() { + if (!isMapInitialized) { + initSystemFlavorMap(); + // From this point the map should not be modified + textTypeToNative = Collections.unmodifiableMap(textTypeToNative); + } + return textTypeToNative; + } + + /** * Caches the result of getNativesForFlavor(). Maps DataFlavors to - * SoftReferences which reference Lists of String natives. + * SoftReferences which reference LinkedHashSet of String natives. */ - private Map<DataFlavor, SoftReference<List<String>>> getNativesForFlavorCache = new HashMap<>(); + private final SoftCache<DataFlavor, String> nativesForFlavorCache = new SoftCache<>(); /** * Caches the result getFlavorsForNative(). Maps String natives to - * SoftReferences which reference Lists of DataFlavors. + * SoftReferences which reference LinkedHashSet of DataFlavors. */ - private Map<String, SoftReference<List<DataFlavor>>> getFlavorsForNativeCache = new HashMap<>(); + private final SoftCache<String, DataFlavor> flavorsForNativeCache = new SoftCache<>(); /** * Dynamic mapping generation used for text mappings should not be applied @@ -174,7 +191,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * explicitly specified with setFlavorsForNative() or * setNativesForFlavor(). This keeps all such keys. */ - private Set disabledMappingGenerationKeys = new HashSet(); + private Set<Object> disabledMappingGenerationKeys = new HashSet<>(); /** * Returns the default FlavorMap for this thread's ClassLoader. @@ -403,7 +420,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { flavor = new DataFlavor(value); } catch (Exception e) { try { - flavor = new DataFlavor(value, (String)null); + flavor = new DataFlavor(value, null); } catch (Exception ee) { ee.printStackTrace(); continue; @@ -411,11 +428,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } final LinkedHashSet<DataFlavor> dfs = new LinkedHashSet<>(); - dfs.add(flavor); if ("text".equals(flavor.getPrimaryType())) { dfs.addAll(convertMimeTypeToDataFlavors(value)); + store(flavor.mimeType.getBaseType(), key, getTextTypeToNative()); } for (DataFlavor df : dfs) { @@ -504,10 +521,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * the appropriate Map location, but rather will be appended to a List * stored in that location. */ - private <H, L> void store(H hashed, L listed, Map<H, List<L>> map) { - List<L> list = map.get(hashed); + private <H, L> void store(H hashed, L listed, Map<H, LinkedHashSet<L>> map) { + LinkedHashSet<L> list = map.get(hashed); if (list == null) { - list = new ArrayList<>(1); + list = new LinkedHashSet<>(1); map.put(hashed, list); } if (!list.contains(listed)) { @@ -521,17 +538,17 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * case, a new DataFlavor is synthesized, stored, and returned, if and * only if the specified native is encoded as a Java MIME type. */ - private List<DataFlavor> nativeToFlavorLookup(String nat) { - List<DataFlavor> flavors = getNativeToFlavor().get(nat); + private LinkedHashSet<DataFlavor> nativeToFlavorLookup(String nat) { + LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(nat); + if (nat != null && !disabledMappingGenerationKeys.contains(nat)) { DataTransferer transferer = DataTransferer.getInstance(); if (transferer != null) { - List<DataFlavor> platformFlavors = + LinkedHashSet<DataFlavor> platformFlavors = transferer.getPlatformMappingsForNative(nat); if (!platformFlavors.isEmpty()) { if (flavors != null) { - platformFlavors.removeAll(new HashSet<>(flavors)); // Prepending the platform-specific mappings ensures // that the flavors added with // addFlavorForUnencodedNative() are at the end of @@ -557,24 +574,22 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } if (flavor != null) { - flavors = new ArrayList<>(1); + flavors = new LinkedHashSet<>(1); getNativeToFlavor().put(nat, flavors); flavors.add(flavor); - getFlavorsForNativeCache.remove(nat); - getFlavorsForNativeCache.remove(null); + flavorsForNativeCache.remove(nat); - List<String> natives = getFlavorToNative().get(flavor); + LinkedHashSet<String> natives = getFlavorToNative().get(flavor); if (natives == null) { - natives = new ArrayList<>(1); + natives = new LinkedHashSet<>(1); getFlavorToNative().put(flavor, natives); } natives.add(nat); - getNativesForFlavorCache.remove(flavor); - getNativesForFlavorCache.remove(null); + nativesForFlavorCache.remove(flavor); } } - return (flavors != null) ? flavors : new ArrayList<>(0); + return (flavors != null) ? flavors : new LinkedHashSet<>(0); } /** @@ -585,18 +600,18 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * encoding the DataFlavor's MIME type. Otherwise an empty List is returned * and 'flavorToNative' remains unaffected. */ - private List<String> flavorToNativeLookup(final DataFlavor flav, - final boolean synthesize) { - List<String> natives = getFlavorToNative().get(flav); + private LinkedHashSet<String> flavorToNativeLookup(final DataFlavor flav, + final boolean synthesize) { + + LinkedHashSet<String> natives = getFlavorToNative().get(flav); if (flav != null && !disabledMappingGenerationKeys.contains(flav)) { DataTransferer transferer = DataTransferer.getInstance(); if (transferer != null) { - List<String> platformNatives = + LinkedHashSet<String> platformNatives = transferer.getPlatformMappingsForFlavor(flav); if (!platformNatives.isEmpty()) { if (natives != null) { - platformNatives.removeAll(new HashSet<>(natives)); // Prepend the platform-specific mappings to ensure // that the natives added with // addUnencodedNativeForFlavor() are at the end of @@ -611,26 +626,25 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { if (natives == null) { if (synthesize) { String encoded = encodeDataFlavor(flav); - natives = new ArrayList<>(1); + natives = new LinkedHashSet<>(1); getFlavorToNative().put(flav, natives); natives.add(encoded); - getNativesForFlavorCache.remove(flav); - getNativesForFlavorCache.remove(null); - List<DataFlavor> flavors = getNativeToFlavor().get(encoded); + LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(encoded); if (flavors == null) { - flavors = new ArrayList<>(1); + flavors = new LinkedHashSet<>(1); getNativeToFlavor().put(encoded, flavors); } flavors.add(flav); - getFlavorsForNativeCache.remove(encoded); - getFlavorsForNativeCache.remove(null); + + nativesForFlavorCache.remove(flav); + flavorsForNativeCache.remove(encoded); } else { - natives = new ArrayList<>(0); + natives = new LinkedHashSet<>(0); } } - return natives; + return new LinkedHashSet<>(natives); } /** @@ -658,103 +672,63 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * @see #encodeDataFlavor * @since 1.4 */ + @Override public synchronized List<String> getNativesForFlavor(DataFlavor flav) { - List<String> retval = null; - - // Check cache, even for null flav - SoftReference<List<String>> ref = getNativesForFlavorCache.get(flav); - if (ref != null) { - retval = ref.get(); - if (retval != null) { - // Create a copy, because client code can modify the returned - // list. - return new ArrayList<>(retval); - } + LinkedHashSet<String> retval = nativesForFlavorCache.check(flav); + if (retval != null) { + return new ArrayList<>(retval); } if (flav == null) { - retval = new ArrayList<>(getNativeToFlavor().keySet()); + retval = new LinkedHashSet<>(getNativeToFlavor().keySet()); } else if (disabledMappingGenerationKeys.contains(flav)) { // In this case we shouldn't synthesize a native for this flavor, // since its mappings were explicitly specified. - retval = flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND); + retval = flavorToNativeLookup(flav, false); } else if (DataTransferer.isFlavorCharsetTextType(flav)) { + retval = new LinkedHashSet<>(0); // For text/* flavors, flavor-to-native mappings specified in // flavormap.properties are stored per flavor's base type. if ("text".equals(flav.getPrimaryType())) { - retval = getAllNativesForType(flav.mimeType.getBaseType()); - if (retval != null) { - // To prevent the List stored in the map from modification. - retval = new ArrayList(retval); + LinkedHashSet<String> textTypeNatives = + getTextTypeToNative().get(flav.mimeType.getBaseType()); + if (textTypeNatives != null) { + retval.addAll(textTypeNatives); } } // Also include text/plain natives, but don't duplicate Strings - List<String> textPlainList = getAllNativesForType(TEXT_PLAIN_BASE_TYPE); - - if (textPlainList != null && !textPlainList.isEmpty()) { - // To prevent the List stored in the map from modification. - // This also guarantees that removeAll() is supported. - textPlainList = new ArrayList<>(textPlainList); - if (retval != null && !retval.isEmpty()) { - // Use HashSet to get constant-time performance for search. - textPlainList.removeAll(new HashSet<>(retval)); - retval.addAll(textPlainList); - } else { - retval = textPlainList; - } + LinkedHashSet<String> textTypeNatives = + getTextTypeToNative().get(TEXT_PLAIN_BASE_TYPE); + if (textTypeNatives != null) { + retval.addAll(textTypeNatives); } - if (retval == null || retval.isEmpty()) { - retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND); + if (retval.isEmpty()) { + retval = flavorToNativeLookup(flav, true); } else { // In this branch it is guaranteed that natives explicitly // listed for flav's MIME type were added with // addUnencodedNativeForFlavor(), so they have lower priority. - List<String> explicitList = - flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND); - - // flavorToNativeLookup() never returns null. - // It can return an empty List, however. - if (!explicitList.isEmpty()) { - // To prevent the List stored in the map from modification. - // This also guarantees that removeAll() is supported. - explicitList = new ArrayList<>(explicitList); - // Use HashSet to get constant-time performance for search. - explicitList.removeAll(new HashSet<>(retval)); - retval.addAll(explicitList); - } + retval.addAll(flavorToNativeLookup(flav, false)); } } else if (DataTransferer.isFlavorNoncharsetTextType(flav)) { - retval = getAllNativesForType(flav.mimeType.getBaseType()); + retval = getTextTypeToNative().get(flav.mimeType.getBaseType()); if (retval == null || retval.isEmpty()) { - retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND); + retval = flavorToNativeLookup(flav, true); } else { // In this branch it is guaranteed that natives explicitly // listed for flav's MIME type were added with // addUnencodedNativeForFlavor(), so they have lower priority. - List<String> explicitList = - flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND); - - // flavorToNativeLookup() never returns null. - // It can return an empty List, however. - if (!explicitList.isEmpty()) { - // To prevent the List stored in the map from modification. - // This also guarantees that add/removeAll() are supported. - retval = new ArrayList<>(retval); - explicitList = new ArrayList<>(explicitList); - // Use HashSet to get constant-time performance for search. - explicitList.removeAll(new HashSet<>(retval)); - retval.addAll(explicitList); - } + retval.addAll(flavorToNativeLookup(flav, false)); } } else { - retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND); + retval = flavorToNativeLookup(flav, true); } - getNativesForFlavorCache.put(flav, new SoftReference<>(retval)); + nativesForFlavorCache.put(flav, retval); // Create a copy, because client code can modify the returned list. return new ArrayList<>(retval); } @@ -790,62 +764,38 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * @see #encodeJavaMIMEType * @since 1.4 */ + @Override public synchronized List<DataFlavor> getFlavorsForNative(String nat) { - - // Check cache, even for null nat - SoftReference<List<DataFlavor>> ref = getFlavorsForNativeCache.get(nat); - if (ref != null) { - List<DataFlavor> retval = ref.get(); - if (retval != null) { - return new ArrayList<>(retval); - } + LinkedHashSet<DataFlavor> returnValue = flavorsForNativeCache.check(nat); + if (returnValue != null) { + return new ArrayList<>(returnValue); + } else { + returnValue = new LinkedHashSet<>(); } - final LinkedHashSet <DataFlavor> returnValue = - new LinkedHashSet<>(); - if (nat == null) { - final List<String> natives = getNativesForFlavor(null); - - for (String n : natives) - { - final List<DataFlavor> flavors = getFlavorsForNative(n); - - for (DataFlavor df : flavors) - { - returnValue.add(df); - } + for (String n : getNativesForFlavor(null)) { + returnValue.addAll(getFlavorsForNative(n)); } } else { - - final List<DataFlavor> flavors = nativeToFlavorLookup(nat); - + final LinkedHashSet<DataFlavor> flavors = nativeToFlavorLookup(nat); if (disabledMappingGenerationKeys.contains(nat)) { - return flavors; + return new ArrayList<>(flavors); } - final List<DataFlavor> flavorsAndBaseTypes = - nativeToFlavorLookup(nat); + final LinkedHashSet<DataFlavor> flavorsWithSynthesized = + nativeToFlavorLookup(nat); - for (DataFlavor df : flavorsAndBaseTypes) { + for (DataFlavor df : flavorsWithSynthesized) { returnValue.add(df); if ("text".equals(df.getPrimaryType())) { - try { - returnValue.addAll( - convertMimeTypeToDataFlavors( - new MimeType(df.getMimeType() - ).getBaseType())); - } catch (MimeTypeParseException e) { - e.printStackTrace(); - } + String baseType = df.mimeType.getBaseType(); + returnValue.addAll(convertMimeTypeToDataFlavors(baseType)); } } - } - - final List<DataFlavor> arrayList = new ArrayList<>(returnValue); - getFlavorsForNativeCache.put(nat, new SoftReference<>(arrayList)); - return new ArrayList<>(arrayList); + flavorsForNativeCache.put(nat, returnValue); + return new ArrayList<>(returnValue); } private static Set<DataFlavor> convertMimeTypeToDataFlavors( @@ -861,7 +811,6 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } catch (MimeTypeParseException mtpe) { // Cannot happen, since we checked all mappings // on load from flavormap.properties. - assert(false); } if (DataTransferer.doesSubtypeSupportCharset(subType, null)) { @@ -940,10 +889,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } private static final String [] htmlDocumntTypes = - new String [] {"all", "selection", "fragment"}; + new String [] {"all", "selection", "fragment"}; - private static LinkedHashSet<String> handleHtmlMimeTypes( - String baseType, String mimeType) { + private static LinkedHashSet<String> handleHtmlMimeTypes(String baseType, + String mimeType) { LinkedHashSet<String> returnValues = new LinkedHashSet<>(); @@ -980,14 +929,14 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * @see #getNativesForFlavor * @see #encodeDataFlavor */ - public synchronized Map<DataFlavor,String> - getNativesForFlavors(DataFlavor[] flavors) + @Override + public synchronized Map<DataFlavor,String> getNativesForFlavors(DataFlavor[] flavors) { // Use getNativesForFlavor to generate extra natives for text flavors // and stringFlavor if (flavors == null) { - List flavor_list = getFlavorsForNative(null); + List<DataFlavor> flavor_list = getFlavorsForNative(null); flavors = new DataFlavor[flavor_list.size()]; flavor_list.toArray(flavors); } @@ -1026,15 +975,14 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * @see #getFlavorsForNative * @see #encodeJavaMIMEType */ - public synchronized Map<String,DataFlavor> - getFlavorsForNatives(String[] natives) + @Override + public synchronized Map<String,DataFlavor> getFlavorsForNatives(String[] natives) { // Use getFlavorsForNative to generate extra flavors for text natives - if (natives == null) { - List native_list = getNativesForFlavor(null); - natives = new String[native_list.size()]; - native_list.toArray(natives); + List<String> nativesList = getNativesForFlavor(null); + natives = new String[nativesList.size()]; + nativesList.toArray(natives); } Map<String, DataFlavor> retval = new HashMap<>(natives.length, 1.0f); @@ -1043,7 +991,6 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { DataFlavor flav = (flavors.isEmpty())? null : flavors.get(0); retval.put(aNative, flav); } - return retval; } @@ -1069,20 +1016,16 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { */ public synchronized void addUnencodedNativeForFlavor(DataFlavor flav, String nat) { - if (flav == null || nat == null) { - throw new NullPointerException("null arguments not permitted"); - } + Objects.requireNonNull(nat, "Null native not permitted"); + Objects.requireNonNull(flav, "Null flavor not permitted"); - List<String> natives = getFlavorToNative().get(flav); + LinkedHashSet<String> natives = getFlavorToNative().get(flav); if (natives == null) { - natives = new ArrayList<>(1); + natives = new LinkedHashSet<>(1); getFlavorToNative().put(flav, natives); - } else if (natives.contains(nat)) { - return; } natives.add(nat); - getNativesForFlavorCache.remove(flav); - getNativesForFlavorCache.remove(null); + nativesForFlavorCache.remove(flav); } /** @@ -1115,18 +1058,15 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { */ public synchronized void setNativesForFlavor(DataFlavor flav, String[] natives) { - if (flav == null || natives == null) { - throw new NullPointerException("null arguments not permitted"); - } + Objects.requireNonNull(natives, "Null natives not permitted"); + Objects.requireNonNull(flav, "Null flavors not permitted"); getFlavorToNative().remove(flav); for (String aNative : natives) { addUnencodedNativeForFlavor(flav, aNative); } disabledMappingGenerationKeys.add(flav); - // Clear the cache to handle the case of empty natives. - getNativesForFlavorCache.remove(flav); - getNativesForFlavorCache.remove(null); + nativesForFlavorCache.remove(flav); } /** @@ -1149,20 +1089,16 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { */ public synchronized void addFlavorForUnencodedNative(String nat, DataFlavor flav) { - if (nat == null || flav == null) { - throw new NullPointerException("null arguments not permitted"); - } + Objects.requireNonNull(nat, "Null native not permitted"); + Objects.requireNonNull(flav, "Null flavor not permitted"); - List<DataFlavor> flavors = getNativeToFlavor().get(nat); + LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(nat); if (flavors == null) { - flavors = new ArrayList<>(1); + flavors = new LinkedHashSet<>(1); getNativeToFlavor().put(nat, flavors); - } else if (flavors.contains(flav)) { - return; } flavors.add(flav); - getFlavorsForNativeCache.remove(nat); - getFlavorsForNativeCache.remove(null); + flavorsForNativeCache.remove(nat); } /** @@ -1194,18 +1130,15 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { */ public synchronized void setFlavorsForNative(String nat, DataFlavor[] flavors) { - if (nat == null || flavors == null) { - throw new NullPointerException("null arguments not permitted"); - } + Objects.requireNonNull(nat, "Null native not permitted"); + Objects.requireNonNull(flavors, "Null flavors not permitted"); getNativeToFlavor().remove(nat); for (DataFlavor flavor : flavors) { addFlavorForUnencodedNative(nat, flavor); } disabledMappingGenerationKeys.add(nat); - // Clear the cache to handle the case of empty flavors. - getFlavorsForNativeCache.remove(nat); - getFlavorsForNativeCache.remove(null); + flavorsForNativeCache.remove(nat); } /** @@ -1304,17 +1237,29 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { : null; } - private List<String> getAllNativesForType(String type) { - Set<String> retval = null; - for (DataFlavor dataFlavor : convertMimeTypeToDataFlavors(type)) { - List<String> natives = getFlavorToNative().get(dataFlavor); - if (natives != null && !natives.isEmpty()) { - if (retval == null) { - retval = new LinkedHashSet<>(); - } - retval.addAll(natives); + private static final class SoftCache<K, V> { + Map<K, SoftReference<LinkedHashSet<V>>> cache; + + public void put(K key, LinkedHashSet<V> value) { + if (cache == null) { + cache = new HashMap<>(1); + } + cache.put(key, new SoftReference<>(value)); + } + + public void remove(K key) { + if (cache == null) return; + cache.remove(null); + cache.remove(key); + } + + public LinkedHashSet<V> check(K key) { + if (cache == null) return null; + SoftReference<LinkedHashSet<V>> ref = cache.get(key); + if (ref != null) { + return ref.get(); } + return null; } - return retval == null ? null : new ArrayList<>(retval); } } diff --git a/src/share/classes/java/beans/Introspector.java b/src/share/classes/java/beans/Introspector.java index 427a28ea2..5ba5f66ea 100644 --- a/src/share/classes/java/beans/Introspector.java +++ b/src/share/classes/java/beans/Introspector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -729,27 +729,53 @@ public class Introspector { if (igpd != null && ispd != null) { // Complete indexed properties set // Merge any classic property descriptors - if (gpd != null) { - PropertyDescriptor tpd = mergePropertyDescriptor(igpd, gpd); - if (tpd instanceof IndexedPropertyDescriptor) { - igpd = (IndexedPropertyDescriptor)tpd; - } - } - if (spd != null) { - PropertyDescriptor tpd = mergePropertyDescriptor(ispd, spd); - if (tpd instanceof IndexedPropertyDescriptor) { - ispd = (IndexedPropertyDescriptor)tpd; - } + if ((gpd == spd) || (gpd == null)) { + pd = spd; + } else if (spd == null) { + pd = gpd; + } else if (spd instanceof IndexedPropertyDescriptor) { + pd = mergePropertyWithIndexedProperty(gpd, (IndexedPropertyDescriptor) spd); + } else if (gpd instanceof IndexedPropertyDescriptor) { + pd = mergePropertyWithIndexedProperty(spd, (IndexedPropertyDescriptor) gpd); + } else { + pd = mergePropertyDescriptor(gpd, spd); } if (igpd == ispd) { - pd = igpd; + ipd = igpd; } else { - pd = mergePropertyDescriptor(igpd, ispd); + ipd = mergePropertyDescriptor(igpd, ispd); + } + if (pd == null) { + pd = ipd; + } else { + Class<?> propType = pd.getPropertyType(); + Class<?> ipropType = ipd.getIndexedPropertyType(); + if (propType.isArray() && propType.getComponentType() == ipropType) { + pd = pd.getClass0().isAssignableFrom(ipd.getClass0()) + ? new IndexedPropertyDescriptor(pd, ipd) + : new IndexedPropertyDescriptor(ipd, pd); + } else if (pd.getClass0().isAssignableFrom(ipd.getClass0())) { + pd = pd.getClass0().isAssignableFrom(ipd.getClass0()) + ? new PropertyDescriptor(pd, ipd) + : new PropertyDescriptor(ipd, pd); + } else { + pd = ipd; + } } } else if (gpd != null && spd != null) { + if (igpd != null) { + gpd = mergePropertyWithIndexedProperty(gpd, igpd); + } + if (ispd != null) { + spd = mergePropertyWithIndexedProperty(spd, ispd); + } // Complete simple properties set if (gpd == spd) { pd = gpd; + } else if (spd instanceof IndexedPropertyDescriptor) { + pd = mergePropertyWithIndexedProperty(gpd, (IndexedPropertyDescriptor) spd); + } else if (gpd instanceof IndexedPropertyDescriptor) { + pd = mergePropertyWithIndexedProperty(spd, (IndexedPropertyDescriptor) gpd); } else { pd = mergePropertyDescriptor(gpd, spd); } @@ -809,6 +835,16 @@ public class Introspector { return ((current == null) || (candidate == null)) ? current == candidate : current.isAssignableFrom(candidate); } + private PropertyDescriptor mergePropertyWithIndexedProperty(PropertyDescriptor pd, IndexedPropertyDescriptor ipd) { + Class<?> type = pd.getPropertyType(); + if (type.isArray() && (type.getComponentType() == ipd.getIndexedPropertyType())) { + return pd.getClass0().isAssignableFrom(ipd.getClass0()) + ? new IndexedPropertyDescriptor(pd, ipd) + : new IndexedPropertyDescriptor(ipd, pd); + } + return pd; + } + /** * Adds the property descriptor to the indexedproperty descriptor only if the * types are the same. @@ -828,6 +864,12 @@ public class Introspector { } else { result = new IndexedPropertyDescriptor(ipd, pd); } + } else if ((ipd.getReadMethod() == null) && (ipd.getWriteMethod() == null)) { + if (pd.getClass0().isAssignableFrom(ipd.getClass0())) { + result = new PropertyDescriptor(pd, ipd); + } else { + result = new PropertyDescriptor(ipd, pd); + } } else { // Cannot merge the pd because of type mismatch // Return the most specific pd @@ -879,7 +921,7 @@ public class Introspector { } // Handle regular ipd merge - private PropertyDescriptor mergePropertyDescriptor(IndexedPropertyDescriptor ipd1, + private IndexedPropertyDescriptor mergePropertyDescriptor(IndexedPropertyDescriptor ipd1, IndexedPropertyDescriptor ipd2) { if (ipd1.getClass0().isAssignableFrom(ipd2.getClass0())) { return new IndexedPropertyDescriptor(ipd1, ipd2); diff --git a/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java b/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java index 63ba8fea5..5c874f497 100644 --- a/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java +++ b/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java @@ -44,6 +44,10 @@ abstract class DelegatingMethodHandle extends MethodHandle { super(type, chooseDelegatingForm(target)); } + protected DelegatingMethodHandle(MethodType type, LambdaForm form) { + super(type, form); + } + /** Define this to extract the delegated target which supplies the invocation behavior. */ abstract protected MethodHandle getTarget(); @@ -88,14 +92,31 @@ abstract class DelegatingMethodHandle extends MethodHandle { 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) { + 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; + } + // No pre-action needed. + return makeReinvokerForm(target, whichCache, constraint, debugString, true, getTargetFn, null); + } + /** Create a LF which simply reinvokes a target of the given basic type. */ + static LambdaForm makeReinvokerForm(MethodHandle target, + int whichCache, + Object constraint, + String debugString, + boolean forceInline, + NamedFunction getTargetFn, + NamedFunction preActionFn) { MethodType mtype = target.type().basicType(); boolean customized = (whichCache < 0 || mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY); + boolean hasPreAction = (preActionFn != null); LambdaForm form; if (!customized) { form = mtype.form().cachedLambdaForm(whichCache); @@ -105,12 +126,16 @@ abstract class DelegatingMethodHandle extends MethodHandle { final int ARG_BASE = 1; final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); int nameCursor = ARG_LIMIT; + final int PRE_ACTION = hasPreAction ? nameCursor++ : -1; 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 (hasPreAction) { + names[PRE_ACTION] = new LambdaForm.Name(preActionFn, names[THIS_DMH]); + } 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 @@ -120,20 +145,14 @@ abstract class DelegatingMethodHandle extends MethodHandle { 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); + form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline); if (!customized) { form = mtype.form().setCachedLambdaForm(whichCache, form); } return form; } - private static final NamedFunction NF_getTarget; + static final NamedFunction NF_getTarget; static { try { NF_getTarget = new NamedFunction(DelegatingMethodHandle.class diff --git a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index cdbbebcbe..6e8d091a6 100644 --- a/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -628,8 +628,13 @@ class InvokerBytecodeGenerator { // Mark this method as a compiled LambdaForm mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true); - // Force inlining of this invoker method. - mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true); + if (lambdaForm.forceInline) { + // Force inlining of this invoker method. + mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true); + } else { + mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true); + } + // iterate over the form's names, generating bytecode instructions for each // start iterating at the first name following the arguments diff --git a/src/share/classes/java/lang/invoke/LambdaForm.java b/src/share/classes/java/lang/invoke/LambdaForm.java index b83040647..e1791719c 100644 --- a/src/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/share/classes/java/lang/invoke/LambdaForm.java @@ -119,6 +119,7 @@ import static java.lang.invoke.MethodHandleNatives.Constants.*; class LambdaForm { final int arity; final int result; + final boolean forceInline; @Stable final Name[] names; final String debugName; MemberName vmentry; // low-level behavior, or null if not yet prepared @@ -243,11 +244,16 @@ class LambdaForm { LambdaForm(String debugName, int arity, Name[] names, int result) { + this(debugName, arity, names, result, true); + } + LambdaForm(String debugName, + int arity, Name[] names, int result, boolean forceInline) { assert(namesOK(arity, names)); this.arity = arity; this.result = fixResult(result, names); this.names = names.clone(); this.debugName = fixDebugName(debugName); + this.forceInline = forceInline; int maxOutArity = normalize(); if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) { // Cannot use LF interpreter on very high arity expressions. @@ -255,17 +261,23 @@ class LambdaForm { compileToBytecode(); } } - LambdaForm(String debugName, int arity, Name[] names) { - this(debugName, - arity, names, LAST_RESULT); + this(debugName, arity, names, LAST_RESULT, true); + } + LambdaForm(String debugName, + int arity, Name[] names, boolean forceInline) { + this(debugName, arity, names, LAST_RESULT, forceInline); } - LambdaForm(String debugName, Name[] formals, Name[] temps, Name result) { this(debugName, - formals.length, buildNames(formals, temps, result), LAST_RESULT); + formals.length, buildNames(formals, temps, result), LAST_RESULT, true); + } + LambdaForm(String debugName, + Name[] formals, Name[] temps, Name result, boolean forceInline) { + this(debugName, + formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline); } private static Name[] buildNames(Name[] formals, Name[] temps, Name result) { @@ -279,6 +291,10 @@ class LambdaForm { } private LambdaForm(String sig) { + this(sig, true); + } + + private LambdaForm(String sig, boolean forceInline) { // Make a blank lambda form, which returns a constant zero or null. // It is used as a template for managing the invocation of similar forms that are non-empty. // Called only from getPreparedForm. @@ -287,6 +303,7 @@ class LambdaForm { this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity); this.names = buildEmptyNames(arity, sig); this.debugName = "LF.zero"; + this.forceInline = forceInline; assert(nameRefsAreLegal()); assert(isEmpty()); assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature(); diff --git a/src/share/classes/java/lang/invoke/MethodHandle.java b/src/share/classes/java/lang/invoke/MethodHandle.java index f0169e73d..9b586a317 100644 --- a/src/share/classes/java/lang/invoke/MethodHandle.java +++ b/src/share/classes/java/lang/invoke/MethodHandle.java @@ -867,15 +867,11 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray MethodType postSpreadType = asSpreaderChecks(arrayType, arrayLength); int arity = type().parameterCount(); int spreadArgPos = arity - arrayLength; - if (USE_LAMBDA_FORM_EDITOR) { - MethodHandle afterSpread = this.asType(postSpreadType); - BoundMethodHandle mh = afterSpread.rebind(); - LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength); - MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType); - return mh.copyWith(preSpreadType, lform); - } else { - return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength); - } + MethodHandle afterSpread = this.asType(postSpreadType); + BoundMethodHandle mh = afterSpread.rebind(); + LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength); + MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType); + return mh.copyWith(preSpreadType, lform); } /** @@ -996,23 +992,15 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); public MethodHandle asCollector(Class<?> arrayType, int arrayLength) { asCollectorChecks(arrayType, arrayLength); int collectArgPos = type().parameterCount() - 1; - if (USE_LAMBDA_FORM_EDITOR) { - BoundMethodHandle mh = rebind(); - MethodType resultType = type().asCollectorType(arrayType, arrayLength); - MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); - LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray); - if (lform != null) { - return mh.copyWith(resultType, lform); - } - lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType()); - return mh.copyWithExtendL(resultType, lform, newArray); - } else { - MethodHandle target = this; - if (arrayType != type().parameterType(collectArgPos)) - target = MethodHandleImpl.makePairwiseConvert(this, type().changeParameterType(collectArgPos, arrayType), true); - MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength); - return MethodHandles.collectArguments(target, collectArgPos, collector); + BoundMethodHandle mh = rebind(); + MethodType resultType = type().asCollectorType(arrayType, arrayLength); + MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); + LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray); + if (lform != null) { + return mh.copyWith(resultType, lform); } + lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType()); + return mh.copyWithExtendL(resultType, lform, newArray); } /** @@ -1438,10 +1426,9 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); /*non-public*/ void updateForm(LambdaForm newForm) { if (form == newForm) return; - assert(this instanceof DirectMethodHandle && this.internalMemberName().isStatic()); - // ISSUE: Should we have a memory fence here? + newForm.prepare(); // as in MethodHandle.<init> UNSAFE.putObject(this, FORM_OFFSET, newForm); - this.form.prepare(); // as in MethodHandle.<init> + UNSAFE.fullFence(); } private static final long FORM_OFFSET; diff --git a/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/share/classes/java/lang/invoke/MethodHandleImpl.java index 3cab70696..8812b6d2a 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -30,6 +30,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.function.Function; import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; @@ -190,11 +191,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MethodType dstType = target.type(); if (srcType == dstType) return target; - if (USE_LAMBDA_FORM_EDITOR) { - return makePairwiseConvertByEditor(target, srcType, strict, monobox); - } else { - return makePairwiseConvertIndirect(target, srcType, strict, monobox); - } + return makePairwiseConvertByEditor(target, srcType, strict, monobox); } private static int countNonNull(Object[] array) { @@ -713,10 +710,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; LambdaForm form = makeGuardWithTestForm(basicType); BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); BoundMethodHandle mh; + try { mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, - (Object) test, (Object) target, (Object) fallback); + (Object) test, (Object) profile(target), (Object) profile(fallback)); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -724,6 +722,129 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return mh; } + + static + MethodHandle profile(MethodHandle target) { + if (DONT_INLINE_THRESHOLD >= 0) { + return makeBlockInlningWrapper(target); + } else { + return target; + } + } + + /** + * Block inlining during JIT-compilation of a target method handle if it hasn't been invoked enough times. + * Corresponding LambdaForm has @DontInline when compiled into bytecode. + */ + static + MethodHandle makeBlockInlningWrapper(MethodHandle target) { + LambdaForm lform = PRODUCE_BLOCK_INLINING_FORM.apply(target); + return new CountingWrapper(target, lform, + PRODUCE_BLOCK_INLINING_FORM, PRODUCE_REINVOKER_FORM, + DONT_INLINE_THRESHOLD); + } + + /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */ + private static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() { + @Override + public LambdaForm apply(MethodHandle target) { + return DelegatingMethodHandle.makeReinvokerForm(target, + MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, "reinvoker.dontInline", false, + DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting); + } + }; + + /** Constructs simple reinvoker lambda form for a particular method handle */ + private static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() { + @Override + public LambdaForm apply(MethodHandle target) { + return DelegatingMethodHandle.makeReinvokerForm(target, + MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget); + } + }; + + /** + * Counting method handle. It has 2 states: counting and non-counting. + * It is in counting state for the first n invocations and then transitions to non-counting state. + * Behavior in counting and non-counting states is determined by lambda forms produced by + * countingFormProducer & nonCountingFormProducer respectively. + */ + static class CountingWrapper extends DelegatingMethodHandle { + private final MethodHandle target; + private int count; + private Function<MethodHandle, LambdaForm> countingFormProducer; + private Function<MethodHandle, LambdaForm> nonCountingFormProducer; + private volatile boolean isCounting; + + private CountingWrapper(MethodHandle target, LambdaForm lform, + Function<MethodHandle, LambdaForm> countingFromProducer, + Function<MethodHandle, LambdaForm> nonCountingFormProducer, + int count) { + super(target.type(), lform); + this.target = target; + this.count = count; + this.countingFormProducer = countingFromProducer; + this.nonCountingFormProducer = nonCountingFormProducer; + this.isCounting = (count > 0); + } + + @Hidden + @Override + protected MethodHandle getTarget() { + return target; + } + + @Override + public MethodHandle asTypeUncached(MethodType newType) { + MethodHandle newTarget = target.asType(newType); + MethodHandle wrapper; + if (isCounting) { + LambdaForm lform; + lform = countingFormProducer.apply(target); + wrapper = new CountingWrapper(newTarget, lform, countingFormProducer, nonCountingFormProducer, DONT_INLINE_THRESHOLD); + } else { + wrapper = newTarget; // no need for a counting wrapper anymore + } + return (asTypeCache = wrapper); + } + + boolean countDown() { + if (count <= 0) { + // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility. + if (isCounting) { + isCounting = false; + return true; + } else { + return false; + } + } else { + --count; + return false; + } + } + + @Hidden + static void maybeStopCounting(Object o1) { + CountingWrapper wrapper = (CountingWrapper) o1; + if (wrapper.countDown()) { + // Reached invocation threshold. Replace counting behavior with a non-counting one. + LambdaForm lform = wrapper.nonCountingFormProducer.apply(wrapper.target); + lform.compileToBytecode(); // speed up warmup by avoiding LF interpretation again after transition + wrapper.updateForm(lform); + } + } + + static final NamedFunction NF_maybeStopCounting; + static { + Class<?> THIS_CLASS = CountingWrapper.class; + try { + NF_maybeStopCounting = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeStopCounting", Object.class)); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } + } + static LambdaForm makeGuardWithTestForm(MethodType basicType) { LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT); diff --git a/src/share/classes/java/lang/invoke/MethodHandleStatics.java b/src/share/classes/java/lang/invoke/MethodHandleStatics.java index c3d9ac12c..335a32289 100644 --- a/src/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/src/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -45,20 +45,20 @@ import sun.misc.Unsafe; static final boolean DUMP_CLASS_FILES; static final boolean TRACE_INTERPRETER; static final boolean TRACE_METHOD_LINKAGE; - static final boolean USE_LAMBDA_FORM_EDITOR; static final int COMPILE_THRESHOLD; + static final int DONT_INLINE_THRESHOLD; static final int PROFILE_LEVEL; static { - final Object[] values = { false, false, false, false, false, null, null }; + final Object[] values = new Object[7]; AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"); values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"); values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"); - values[4] = Boolean.getBoolean("java.lang.invoke.MethodHandle.USE_LF_EDITOR"); - values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 30); + values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 0); + values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30); values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); return null; } @@ -67,8 +67,8 @@ import sun.misc.Unsafe; DUMP_CLASS_FILES = (Boolean) values[1]; TRACE_INTERPRETER = (Boolean) values[2]; TRACE_METHOD_LINKAGE = (Boolean) values[3]; - USE_LAMBDA_FORM_EDITOR = (Boolean) values[4]; - COMPILE_THRESHOLD = (Integer) values[5]; + COMPILE_THRESHOLD = (Integer) values[4]; + DONT_INLINE_THRESHOLD = (Integer) values[5]; PROFILE_LEVEL = (Integer) values[6]; } diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java index 91855fb86..3c60a8c3c 100644 --- a/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/share/classes/java/lang/invoke/MethodHandles.java @@ -2104,115 +2104,65 @@ assert((int)twice.invokeExact(21) == 42); reorder = reorder.clone(); // get a private copy MethodType oldType = target.type(); permuteArgumentChecks(reorder, newType, oldType); - if (USE_LAMBDA_FORM_EDITOR) { - // first detect dropped arguments and handle them separately - int[] originalReorder = reorder; - BoundMethodHandle result = target.rebind(); - LambdaForm form = result.form; - int newArity = newType.parameterCount(); - // Normalize the reordering into a real permutation, - // by removing duplicates and adding dropped elements. - // This somewhat improves lambda form caching, as well - // as simplifying the transform by breaking it up into steps. - for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) { - if (ddIdx > 0) { - // We found a duplicated entry at reorder[ddIdx]. - // Example: (x,y,z)->asList(x,y,z) - // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1) - // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0) - // The starred element corresponds to the argument - // deleted by the dupArgumentForm transform. - int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos]; - boolean killFirst = false; - for (int val; (val = reorder[--dstPos]) != dupVal; ) { - // Set killFirst if the dup is larger than an intervening position. - // This will remove at least one inversion from the permutation. - if (dupVal > val) killFirst = true; - } - if (!killFirst) { - srcPos = dstPos; - dstPos = ddIdx; - } - form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos); - assert (reorder[srcPos] == reorder[dstPos]); - oldType = oldType.dropParameterTypes(dstPos, dstPos + 1); - // contract the reordering by removing the element at dstPos - int tailPos = dstPos + 1; - System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos); - reorder = Arrays.copyOf(reorder, reorder.length - 1); - } else { - int dropVal = ~ddIdx, insPos = 0; - while (insPos < reorder.length && reorder[insPos] < dropVal) { - // Find first element of reorder larger than dropVal. - // This is where we will insert the dropVal. - insPos += 1; - } - Class<?> ptype = newType.parameterType(dropVal); - form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype)); - oldType = oldType.insertParameterTypes(insPos, ptype); - // expand the reordering by inserting an element at insPos - int tailPos = insPos + 1; - reorder = Arrays.copyOf(reorder, reorder.length + 1); - System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos); - reorder[insPos] = dropVal; + // first detect dropped arguments and handle them separately + int[] originalReorder = reorder; + BoundMethodHandle result = target.rebind(); + LambdaForm form = result.form; + int newArity = newType.parameterCount(); + // Normalize the reordering into a real permutation, + // by removing duplicates and adding dropped elements. + // This somewhat improves lambda form caching, as well + // as simplifying the transform by breaking it up into steps. + for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) { + if (ddIdx > 0) { + // We found a duplicated entry at reorder[ddIdx]. + // Example: (x,y,z)->asList(x,y,z) + // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1) + // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0) + // The starred element corresponds to the argument + // deleted by the dupArgumentForm transform. + int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos]; + boolean killFirst = false; + for (int val; (val = reorder[--dstPos]) != dupVal; ) { + // Set killFirst if the dup is larger than an intervening position. + // This will remove at least one inversion from the permutation. + if (dupVal > val) killFirst = true; } - assert (permuteArgumentChecks(reorder, newType, oldType)); - } - assert (reorder.length == newArity); // a perfect permutation - // Note: This may cache too many distinct LFs. Consider backing off to varargs code. - form = form.editor().permuteArgumentsForm(1, reorder); - if (newType == result.type() && form == result.internalForm()) - return result; - return result.copyWith(newType, form); - } else { - // first detect dropped arguments and handle them separately - MethodHandle originalTarget = target; - int newArity = newType.parameterCount(); - for (int dropIdx; (dropIdx = findFirstDrop(reorder, newArity)) >= 0; ) { - // dropIdx is missing from reorder; add it in at the end - int oldArity = reorder.length; - target = dropArguments(target, oldArity, newType.parameterType(dropIdx)); - reorder = Arrays.copyOf(reorder, oldArity + 1); - reorder[oldArity] = dropIdx; + if (!killFirst) { + srcPos = dstPos; + dstPos = ddIdx; + } + form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos); + assert (reorder[srcPos] == reorder[dstPos]); + oldType = oldType.dropParameterTypes(dstPos, dstPos + 1); + // contract the reordering by removing the element at dstPos + int tailPos = dstPos + 1; + System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos); + reorder = Arrays.copyOf(reorder, reorder.length - 1); + } else { + int dropVal = ~ddIdx, insPos = 0; + while (insPos < reorder.length && reorder[insPos] < dropVal) { + // Find first element of reorder larger than dropVal. + // This is where we will insert the dropVal. + insPos += 1; + } + Class<?> ptype = newType.parameterType(dropVal); + form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype)); + oldType = oldType.insertParameterTypes(insPos, ptype); + // expand the reordering by inserting an element at insPos + int tailPos = insPos + 1; + reorder = Arrays.copyOf(reorder, reorder.length + 1); + System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos); + reorder[insPos] = dropVal; } - assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type())); - // Note: This may cache too many distinct LFs. Consider backing off to varargs code. - BoundMethodHandle result = target.rebind(); - LambdaForm form = result.form.permuteArguments(1, reorder, basicTypes(newType.parameterList())); - return result.copyWith(newType, form); - } - } - - /** Return the first value in [0..newArity-1] that is not present in reorder. */ - private static int findFirstDrop(int[] reorder, int newArity) { - final int BIT_LIMIT = 63; // max number of bits in bit mask - if (newArity < BIT_LIMIT) { - long mask = 0; - for (int arg : reorder) { - assert(arg < newArity); - mask |= (1L << arg); - } - if (mask == (1L << newArity) - 1) { - assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity); - return -1; - } - // find first zero - long zeroBit = Long.lowestOneBit(~mask); - int zeroPos = Long.numberOfTrailingZeros(zeroBit); - assert(zeroPos < newArity); - return zeroPos; - } else { - BitSet mask = new BitSet(newArity); - for (int arg : reorder) { - assert (arg < newArity); - mask.set(arg); - } - int zeroPos = mask.nextClearBit(0); - assert(zeroPos <= newArity); - if (zeroPos == newArity) - return -1; - return zeroPos; + assert (permuteArgumentChecks(reorder, newType, oldType)); } + assert (reorder.length == newArity); // a perfect permutation + // Note: This may cache too many distinct LFs. Consider backing off to varargs code. + form = form.editor().permuteArgumentsForm(1, reorder); + if (newType == result.type() && form == result.internalForm()) + return result; + return result.copyWith(newType, form); } /** @@ -2503,13 +2453,9 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); if (dropped == 0) return target; BoundMethodHandle result = target.rebind(); LambdaForm lform = result.form; - if (USE_LAMBDA_FORM_EDITOR) { - int insertFormArg = 1 + pos; - for (Class<?> ptype : valueTypes) { - lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype)); - } - } else { - lform = lform.addArguments(pos, valueTypes); + int insertFormArg = 1 + pos; + for (Class<?> ptype : valueTypes) { + lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype)); } result = result.copyWith(newType, lform); return result; @@ -2660,18 +2606,14 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY /*non-public*/ static MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) { filterArgumentChecks(target, pos, filter); - if (USE_LAMBDA_FORM_EDITOR) { - MethodType targetType = target.type(); - MethodType filterType = filter.type(); - BoundMethodHandle result = target.rebind(); - Class<?> newParamType = filterType.parameterType(0); - LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType)); - MethodType newType = targetType.changeParameterType(pos, newParamType); - result = result.copyWithExtendL(newType, lform, filter); - return result; - } else { - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); - } + MethodType targetType = target.type(); + MethodType filterType = filter.type(); + BoundMethodHandle result = target.rebind(); + Class<?> newParamType = filterType.parameterType(0); + LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType)); + MethodType newType = targetType.changeParameterType(pos, newParamType); + result = result.copyWithExtendL(newType, lform, filter); + return result; } private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) { @@ -2798,21 +2740,17 @@ assertEquals("[top, [[up, down, strange], charm], bottom]", public static MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) { MethodType newType = collectArgumentsChecks(target, pos, filter); - if (USE_LAMBDA_FORM_EDITOR) { - MethodType collectorType = filter.type(); - BoundMethodHandle result = target.rebind(); - LambdaForm lform; - if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) { - lform = result.editor().collectArgumentArrayForm(1 + pos, filter); - if (lform != null) { - return result.copyWith(newType, lform); - } + MethodType collectorType = filter.type(); + BoundMethodHandle result = target.rebind(); + LambdaForm lform; + if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) { + lform = result.editor().collectArgumentArrayForm(1 + pos, filter); + if (lform != null) { + return result.copyWith(newType, lform); } - lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType()); - return result.copyWithExtendL(newType, lform, filter); - } else { - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); } + lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType()); + return result.copyWithExtendL(newType, lform, filter); } private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException { @@ -2891,16 +2829,12 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 MethodType targetType = target.type(); MethodType filterType = filter.type(); filterReturnValueChecks(targetType, filterType); - if (USE_LAMBDA_FORM_EDITOR) { - BoundMethodHandle result = target.rebind(); - BasicType rtype = BasicType.basicType(filterType.returnType()); - LambdaForm lform = result.editor().filterReturnForm(rtype, false); - MethodType newType = targetType.changeReturnType(filterType.returnType()); - result = result.copyWithExtendL(newType, lform, filter); - return result; - } else { - return MethodHandleImpl.makeCollectArguments(filter, target, 0, false); - } + BoundMethodHandle result = target.rebind(); + BasicType rtype = BasicType.basicType(filterType.returnType()); + LambdaForm lform = result.editor().filterReturnForm(rtype, false); + MethodType newType = targetType.changeReturnType(filterType.returnType()); + result = result.copyWithExtendL(newType, lform, filter); + return result; } private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException { @@ -2994,19 +2928,15 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); MethodType targetType = target.type(); MethodType combinerType = combiner.type(); Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType); - if (USE_LAMBDA_FORM_EDITOR) { - BoundMethodHandle result = target.rebind(); - boolean dropResult = (rtype == void.class); - // Note: This may cache too many distinct LFs. Consider backing off to varargs code. - LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType()); - MethodType newType = targetType; - if (!dropResult) - newType = newType.dropParameterTypes(foldPos, foldPos + 1); - result = result.copyWithExtendL(newType, lform, combiner); - return result; - } else { - return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true); - } + BoundMethodHandle result = target.rebind(); + boolean dropResult = (rtype == void.class); + // Note: This may cache too many distinct LFs. Consider backing off to varargs code. + LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType()); + MethodType newType = targetType; + if (!dropResult) + newType = newType.dropParameterTypes(foldPos, foldPos + 1); + result = result.copyWithExtendL(newType, lform, combiner); + return result; } private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) { diff --git a/src/share/classes/java/lang/invoke/MethodTypeForm.java b/src/share/classes/java/lang/invoke/MethodTypeForm.java index 43e855894..6733e29ef 100644 --- a/src/share/classes/java/lang/invoke/MethodTypeForm.java +++ b/src/share/classes/java/lang/invoke/MethodTypeForm.java @@ -63,24 +63,25 @@ final class MethodTypeForm { final @Stable LambdaForm[] lambdaForms; // Indexes into lambdaForms: static final int - LF_INVVIRTUAL = 0, // DMH invokeVirtual - LF_INVSTATIC = 1, - LF_INVSPECIAL = 2, - LF_NEWINVSPECIAL = 3, - LF_INVINTERFACE = 4, - LF_INVSTATIC_INIT = 5, // DMH invokeStatic with <clinit> barrier - LF_INTERPRET = 6, // LF interpreter - LF_REBIND = 7, // BoundMethodHandle - LF_DELEGATE = 8, // DelegatingMethodHandle - LF_EX_LINKER = 9, // invokeExact_MT (for invokehandle) - LF_EX_INVOKER = 10, // MHs.invokeExact - LF_GEN_LINKER = 11, // generic invoke_MT (for invokehandle) - LF_GEN_INVOKER = 12, // generic MHs.invoke - LF_CS_LINKER = 13, // linkToCallSite_CS - LF_MH_LINKER = 14, // linkToCallSite_MH - LF_GWC = 15, // guardWithCatch (catchException) - LF_GWT = 16, // guardWithTest - LF_LIMIT = 17; + LF_INVVIRTUAL = 0, // DMH invokeVirtual + LF_INVSTATIC = 1, + LF_INVSPECIAL = 2, + LF_NEWINVSPECIAL = 3, + LF_INVINTERFACE = 4, + LF_INVSTATIC_INIT = 5, // DMH invokeStatic with <clinit> barrier + LF_INTERPRET = 6, // LF interpreter + LF_REBIND = 7, // BoundMethodHandle + LF_DELEGATE = 8, // DelegatingMethodHandle + LF_DELEGATE_BLOCK_INLINING = 9, // Counting DelegatingMethodHandle w/ @DontInline + LF_EX_LINKER = 10, // invokeExact_MT (for invokehandle) + LF_EX_INVOKER = 11, // MHs.invokeExact + LF_GEN_LINKER = 12, // generic invoke_MT (for invokehandle) + LF_GEN_INVOKER = 13, // generic MHs.invoke + LF_CS_LINKER = 14, // linkToCallSite_CS + LF_MH_LINKER = 15, // linkToCallSite_MH + LF_GWC = 16, // guardWithCatch (catchException) + LF_GWT = 17, // guardWithTest + LF_LIMIT = 18; /** Return the type corresponding uniquely (1-1) to this MT-form. * It might have any primitive returns or arguments, but will have no references except Object. diff --git a/src/share/classes/java/lang/reflect/Executable.java b/src/share/classes/java/lang/reflect/Executable.java index 75642265a..ca55d09bf 100644 --- a/src/share/classes/java/lang/reflect/Executable.java +++ b/src/share/classes/java/lang/reflect/Executable.java @@ -287,6 +287,53 @@ public abstract class Executable extends AccessibleObject } /** + * Behaves like {@code getGenericParameterTypes}, but returns type + * information for all parameters, including synthetic parameters. + */ + Type[] getAllGenericParameterTypes() { + final boolean genericInfo = hasGenericInformation(); + + // Easy case: we don't have generic parameter information. In + // this case, we just return the result of + // getParameterTypes(). + if (!genericInfo) { + return getParameterTypes(); + } else { + final boolean realParamData = hasRealParameterData(); + final Type[] genericParamTypes = getGenericParameterTypes(); + final Type[] nonGenericParamTypes = getParameterTypes(); + final Type[] out = new Type[nonGenericParamTypes.length]; + final Parameter[] params = getParameters(); + int fromidx = 0; + // If we have real parameter data, then we use the + // synthetic and mandate flags to our advantage. + if (realParamData) { + for (int i = 0; i < out.length; i++) { + final Parameter param = params[i]; + if (param.isSynthetic() || param.isImplicit()) { + // If we hit a synthetic or mandated parameter, + // use the non generic parameter info. + out[i] = nonGenericParamTypes[i]; + } else { + // Otherwise, use the generic parameter info. + out[i] = genericParamTypes[fromidx]; + fromidx++; + } + } + } else { + // Otherwise, use the non-generic parameter data. + // Without method parameter reflection data, we have + // no way to figure out which parameters are + // synthetic/mandated, thus, no way to match up the + // indexes. + return genericParamTypes.length == nonGenericParamTypes.length ? + genericParamTypes : nonGenericParamTypes; + } + return out; + } + } + + /** * Returns an array of {@code Parameter} objects that represent * all the parameters to the underlying executable represented by * this object. Returns an array of length 0 if the executable @@ -654,7 +701,7 @@ public abstract class Executable extends AccessibleObject getConstantPool(getDeclaringClass()), this, getDeclaringClass(), - getGenericParameterTypes(), + getAllGenericParameterTypes(), TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER); } diff --git a/src/share/classes/java/lang/reflect/Parameter.java b/src/share/classes/java/lang/reflect/Parameter.java index d8c992c15..38e738177 100644 --- a/src/share/classes/java/lang/reflect/Parameter.java +++ b/src/share/classes/java/lang/reflect/Parameter.java @@ -198,7 +198,7 @@ public final class Parameter implements AnnotatedElement { public Type getParameterizedType() { Type tmp = parameterTypeCache; if (null == tmp) { - tmp = executable.getGenericParameterTypes()[index]; + tmp = executable.getAllGenericParameterTypes()[index]; parameterTypeCache = tmp; } diff --git a/src/share/classes/javax/swing/CellEditor.java b/src/share/classes/javax/swing/CellEditor.java index 3211a788c..9f4c0ab5d 100644 --- a/src/share/classes/javax/swing/CellEditor.java +++ b/src/share/classes/javax/swing/CellEditor.java @@ -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 @@ -47,7 +47,7 @@ import javax.swing.event.*; * new component implement the interface. Or the developer can * choose a wrapper based approach and provide a companion object which * implements the <code>CellEditor</code> interface (See - * <code>JCellEditor</code> for example). The wrapper approach + * <code>DefaultCellEditor</code> for example). The wrapper approach * is particularly useful if the user want to use a 3rd party ISV * editor with <code>JTable</code>, but the ISV didn't implement the * <code>CellEditor</code> interface. The user can simply create an object diff --git a/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java b/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java index 82be7d0f9..7fdb6f5ff 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java @@ -31,16 +31,14 @@ import java.awt.event.*; import javax.accessibility.AccessibleContext; import javax.swing.*; import javax.swing.plaf.*; -import javax.swing.border.*; import javax.swing.event.InternalFrameEvent; -import java.util.EventListener; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; -import java.beans.VetoableChangeListener; import java.beans.PropertyVetoException; import sun.swing.DefaultLookup; -import sun.swing.UIAction; + +import static sun.swing.SwingUtilities2.AA_TEXT_PROPERTY_KEY; /** * The class that manages a basic title bar @@ -125,6 +123,12 @@ public class BasicInternalFrameTitlePane extends JComponent createButtons(); addSubComponents(); + updateProperties(); + } + + private void updateProperties() { + final Object aaTextInfo = frame.getClientProperty(AA_TEXT_PROPERTY_KEY); + putClientProperty(AA_TEXT_PROPERTY_KEY, aaTextInfo); } protected void addSubComponents() { diff --git a/src/share/classes/javax/swing/plaf/basic/BasicTransferable.java b/src/share/classes/javax/swing/plaf/basic/BasicTransferable.java index 7ed4e3d53..23020eaf7 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicTransferable.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicTransferable.java @@ -24,6 +24,8 @@ */ package javax.swing.plaf.basic; +import sun.awt.datatransfer.DataTransferer; + import java.io.*; import java.awt.datatransfer.*; import javax.swing.plaf.UIResource; @@ -145,7 +147,7 @@ class BasicTransferable implements Transferable, UIResource { } else if (Reader.class.equals(flavor.getRepresentationClass())) { return new StringReader(data); } else if (InputStream.class.equals(flavor.getRepresentationClass())) { - return new StringBufferInputStream(data); + return createInputStream(flavor, data); } // fall through to unsupported } else if (isPlainFlavor(flavor)) { @@ -156,7 +158,7 @@ class BasicTransferable implements Transferable, UIResource { } else if (Reader.class.equals(flavor.getRepresentationClass())) { return new StringReader(data); } else if (InputStream.class.equals(flavor.getRepresentationClass())) { - return new StringBufferInputStream(data); + return createInputStream(flavor, data); } // fall through to unsupported @@ -168,6 +170,15 @@ class BasicTransferable implements Transferable, UIResource { throw new UnsupportedFlavorException(flavor); } + private InputStream createInputStream(DataFlavor flavor, String data) + throws IOException, UnsupportedFlavorException { + String cs = DataTransferer.getTextCharset(flavor); + if (cs == null) { + throw new UnsupportedFlavorException(flavor); + } + return new ByteArrayInputStream(data.getBytes(cs)); + } + // --- richer subclass flavors ---------------------------------------------- protected boolean isRicherFlavor(DataFlavor flavor) { diff --git a/src/share/classes/sun/awt/datatransfer/DataTransferer.java b/src/share/classes/sun/awt/datatransfer/DataTransferer.java index b21dab69a..e1677b9c8 100644 --- a/src/share/classes/sun/awt/datatransfer/DataTransferer.java +++ b/src/share/classes/sun/awt/datatransfer/DataTransferer.java @@ -77,6 +77,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.SortedMap; @@ -273,7 +274,7 @@ public abstract class DataTransferer { * instead, null will be returned. */ public static synchronized DataTransferer getInstance() { - return ((ComponentFactory) Toolkit.getDefaultToolkit()).getDataTransferer(); + return ((SunToolkit) Toolkit.getDefaultToolkit()).getDataTransferer(); } /** @@ -1294,6 +1295,15 @@ search: // bytes and dump them into a byte array. For text flavors, decode back // to a String and recur to reencode according to the requested format. } else if (flavor.isRepresentationClassInputStream()) { + + // Workaround to JDK-8024061: Exception thrown when drag and drop + // between two components is executed quickly. + // and JDK-8065098: JColorChooser no longer supports drag and drop + // between two JVM instances + if (!(obj instanceof InputStream)) { + return new byte[0]; + } + try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { try (InputStream is = (InputStream)obj) { boolean eof = false; @@ -2424,8 +2434,8 @@ search: * If there are no platform-specific mappings for this native, the method * returns an empty <code>List</code>. */ - public List getPlatformMappingsForNative(String nat) { - return new ArrayList(); + public LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat) { + return new LinkedHashSet<>(); } /** @@ -2433,8 +2443,8 @@ search: * If there are no platform-specific mappings for this flavor, the method * returns an empty <code>List</code>. */ - public List getPlatformMappingsForFlavor(DataFlavor df) { - return new ArrayList(); + public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) { + return new LinkedHashSet<>(); } /** diff --git a/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java b/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java index b1c89e70b..c81ce90f5 100644 --- a/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java +++ b/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java @@ -239,13 +239,6 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, if (localTransferable != null) { return localTransferable.getTransferData(df); - } else if (df.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType)) { - // Workaround to JDK-8024061: Exception thrown when drag and drop - // between two components is executed quickly. - // It is expected localTransferable is not null if javaJVMLocalObjectMimeType - // is used. Executing further results in ClassCastException, so null is - // returned here as no transfer data is available in this case. - return null; } if (dropStatus != STATUS_ACCEPT || dropComplete) { diff --git a/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java b/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java index abc78f210..e40ee731a 100644 --- a/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java +++ b/src/share/classes/sun/java2d/opengl/OGLBlitLoops.java @@ -47,7 +47,7 @@ import sun.java2d.pipe.RenderQueue; import static sun.java2d.pipe.BufferedOpCodes.*; import java.lang.annotation.Native; -class OGLBlitLoops { +final class OGLBlitLoops { static void register() { Blit blitIntArgbPreToSurface = @@ -56,7 +56,9 @@ class OGLBlitLoops { Blit blitIntArgbPreToTexture = new OGLSwToTextureBlit(SurfaceType.IntArgbPre, OGLSurfaceData.PF_INT_ARGB_PRE); - + TransformBlit transformBlitIntArgbPreToSurface = + new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre, + OGLSurfaceData.PF_INT_ARGB_PRE); GraphicsPrimitive[] primitives = { // surface->surface ops new OGLSurfaceToSurfaceBlit(), @@ -100,7 +102,7 @@ class OGLBlitLoops { CompositeType.AnyAlpha, blitIntArgbPreToSurface), - new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLSurface), + new OGLAnyCompositeBlit(), new OGLSwToSurfaceScale(SurfaceType.IntRgb, OGLSurfaceData.PF_INT_RGB), @@ -145,8 +147,9 @@ class OGLBlitLoops { OGLSurfaceData.PF_BYTE_GRAY), new OGLSwToSurfaceTransform(SurfaceType.UshortGray, OGLSurfaceData.PF_USHORT_GRAY), - new OGLSwToSurfaceTransform(SurfaceType.IntArgbPre, - OGLSurfaceData.PF_INT_ARGB_PRE), + transformBlitIntArgbPreToSurface, + + new OGLGeneralTransformedBlit(transformBlitIntArgbPreToSurface), // texture->surface ops new OGLTextureToSurfaceBlit(), @@ -178,9 +181,6 @@ class OGLBlitLoops { new OGLGeneralBlit(OGLSurfaceData.OpenGLTexture, CompositeType.SrcNoEa, blitIntArgbPreToTexture), - - new OGLAnyCompositeBlit(OGLSurfaceData.OpenGLTexture), - }; GraphicsPrimitiveMgr.register(primitives); } @@ -781,11 +781,11 @@ class OGLTextureToSurfaceTransform extends TransformBlit { * This general Blit implementation converts any source surface to an * intermediate IntArgbPre surface, and then uses the more specific * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate - * (premultiplied) surface down to OpenGL. + * (premultiplied) surface down to OpenGL using simple blit. */ class OGLGeneralBlit extends Blit { - private Blit performop; + private final Blit performop; private WeakReference srcTmp; OGLGeneralBlit(SurfaceType dstType, @@ -826,12 +826,56 @@ class OGLGeneralBlit extends Blit { } } -class OGLAnyCompositeBlit extends Blit { +/** + * This general TransformedBlit implementation converts any source surface to an + * intermediate IntArgbPre surface, and then uses the more specific + * IntArgbPre->OpenGLSurface/Texture loop to get the intermediate + * (premultiplied) surface down to OpenGL using simple transformBlit. + */ +final class OGLGeneralTransformedBlit extends TransformBlit { + + private final TransformBlit performop; + private WeakReference<SurfaceData> srcTmp; + + OGLGeneralTransformedBlit(final TransformBlit performop) { + super(SurfaceType.Any, CompositeType.AnyAlpha, + OGLSurfaceData.OpenGLSurface); + this.performop = performop; + } + + @Override + public synchronized void Transform(SurfaceData src, SurfaceData dst, + Composite comp, Region clip, + AffineTransform at, int hint, int srcx, + int srcy, int dstx, int dsty, int width, + int height){ + Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), + CompositeType.SrcNoEa, + SurfaceType.IntArgbPre); + // use cached intermediate surface, if available + final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; + // convert source to IntArgbPre + src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, + BufferedImage.TYPE_INT_ARGB_PRE); + + // transform IntArgbPre intermediate surface to OpenGL surface + performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, + width, height); + + if (src != cachedSrc) { + // cache the intermediate surface + srcTmp = new WeakReference<>(src); + } + } +} + +final class OGLAnyCompositeBlit extends Blit { private WeakReference<SurfaceData> dstTmp; - public OGLAnyCompositeBlit(SurfaceType dstType) { - super(SurfaceType.Any, CompositeType.Any, dstType); + OGLAnyCompositeBlit() { + super(SurfaceType.Any, CompositeType.Any, OGLSurfaceData.OpenGLSurface); } + public synchronized void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, @@ -848,15 +892,15 @@ class OGLAnyCompositeBlit extends Blit { cachedDst = dstTmp.get(); } - // convert source to IntArgbPre + // convert destination to IntArgbPre SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h, cachedDst, BufferedImage.TYPE_INT_ARGB_PRE); + Region bufferClip = + clip == null ? null : clip.getTranslatedRegion(-dx, -dy); Blit performop = Blit.getFromCache(src.getSurfaceType(), CompositeType.Any, dstBuffer.getSurfaceType()); - - performop.Blit(src, dstBuffer, comp, clip, - sx, sy, 0, 0, w, h); + performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h); if (dstBuffer != cachedDst) { // cache the intermediate surface diff --git a/src/share/classes/sun/java2d/pipe/DrawImage.java b/src/share/classes/sun/java2d/pipe/DrawImage.java index d27ee470f..6b10d247e 100644 --- a/src/share/classes/sun/java2d/pipe/DrawImage.java +++ b/src/share/classes/sun/java2d/pipe/DrawImage.java @@ -510,7 +510,7 @@ public class DrawImage implements DrawImagePipe // We need to transform to a temp image and then copy // just the pieces that are valid data to the dest. BufferedImage tmpimg = new BufferedImage(dx2-dx1, dy2-dy1, - BufferedImage.TYPE_INT_ARGB); + BufferedImage.TYPE_INT_ARGB_PRE); SurfaceData tmpData = SurfaceData.getPrimarySurfaceData(tmpimg); SurfaceType tmpType = tmpData.getSurfaceType(); MaskBlit tmpmaskblit = diff --git a/src/share/classes/sun/management/Flag.java b/src/share/classes/sun/management/Flag.java index 6bb1bf664..6c040ad9e 100644 --- a/src/share/classes/sun/management/Flag.java +++ b/src/share/classes/sun/management/Flag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ package sun.management; import java.util.*; import com.sun.management.VMOption; import com.sun.management.VMOption.Origin; +import java.security.AccessController; /** * Flag class is a helper class for constructing a VMOption. @@ -114,6 +115,13 @@ class Flag { static synchronized native void setStringValue(String name, String value); static { + AccessController.doPrivileged( + new java.security.PrivilegedAction<Void>() { + public Void run() { + System.loadLibrary("management"); + return null; + } + }); initialize(); } private static native void initialize(); diff --git a/src/share/classes/sun/net/www/http/HttpClient.java b/src/share/classes/sun/net/www/http/HttpClient.java index 3013da01d..723a56bad 100644 --- a/src/share/classes/sun/net/www/http/HttpClient.java +++ b/src/share/classes/sun/net/www/http/HttpClient.java @@ -657,9 +657,10 @@ public class HttpClient extends NetworkClient { cachedHttpClient = false; if (!failedOnce && requests != null) { failedOnce = true; - if (getRequestMethod().equals("CONNECT") || - (httpuc.getRequestMethod().equals("POST") && - (!retryPostProp || streaming))) { + if (getRequestMethod().equals("CONNECT") + || streaming + || (httpuc.getRequestMethod().equals("POST") + && !retryPostProp)) { // do not retry the request } else { // try once more @@ -769,9 +770,10 @@ public class HttpClient extends NetworkClient { } else if (nread != 8) { if (!failedOnce && requests != null) { failedOnce = true; - if (getRequestMethod().equals("CONNECT") || - (httpuc.getRequestMethod().equals("POST") && - (!retryPostProp || streaming))) { + if (getRequestMethod().equals("CONNECT") + || streaming + || (httpuc.getRequestMethod().equals("POST") + && !retryPostProp)) { // do not retry the request } else { closeServer(); diff --git a/src/share/classes/sun/reflect/BootstrapConstructorAccessorImpl.java b/src/share/classes/sun/reflect/BootstrapConstructorAccessorImpl.java index 9c8e83359..d44fc8904 100644 --- a/src/share/classes/sun/reflect/BootstrapConstructorAccessorImpl.java +++ b/src/share/classes/sun/reflect/BootstrapConstructorAccessorImpl.java @@ -32,7 +32,7 @@ import java.lang.reflect.Constructor; bootstrapping. */ class BootstrapConstructorAccessorImpl extends ConstructorAccessorImpl { - private Constructor<?> constructor; + private final Constructor<?> constructor; BootstrapConstructorAccessorImpl(Constructor<?> c) { this.constructor = c; diff --git a/src/share/classes/sun/reflect/InstantiationExceptionConstructorAccessorImpl.java b/src/share/classes/sun/reflect/InstantiationExceptionConstructorAccessorImpl.java index 08f921f82..854febe7b 100644 --- a/src/share/classes/sun/reflect/InstantiationExceptionConstructorAccessorImpl.java +++ b/src/share/classes/sun/reflect/InstantiationExceptionConstructorAccessorImpl.java @@ -33,7 +33,7 @@ import java.lang.reflect.InvocationTargetException; class InstantiationExceptionConstructorAccessorImpl extends ConstructorAccessorImpl { - private String message; + private final String message; InstantiationExceptionConstructorAccessorImpl(String message) { this.message = message; diff --git a/src/share/classes/sun/reflect/Label.java b/src/share/classes/sun/reflect/Label.java index 53c912d18..4caa3b40a 100644 --- a/src/share/classes/sun/reflect/Label.java +++ b/src/share/classes/sun/reflect/Label.java @@ -47,10 +47,10 @@ class Label { } // This won't work for more than one assembler anyway, so this is // unnecessary - ClassFileAssembler asm; - short instrBCI; - short patchBCI; - int stackDepth; + final ClassFileAssembler asm; + final short instrBCI; + final short patchBCI; + final int stackDepth; } private List<PatchInfo> patches = new ArrayList<>(); diff --git a/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java b/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java index d56c3caab..171521dd2 100644 --- a/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java +++ b/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java @@ -32,7 +32,7 @@ import sun.reflect.misc.ReflectUtil; afterward, switches to bytecode-based implementation */ class NativeConstructorAccessorImpl extends ConstructorAccessorImpl { - private Constructor<?> c; + private final Constructor<?> c; private DelegatingConstructorAccessorImpl parent; private int numInvocations; diff --git a/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java b/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java index b1d39e7c9..a33670fe8 100644 --- a/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java +++ b/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java @@ -32,7 +32,7 @@ import sun.reflect.misc.ReflectUtil; switches to bytecode-based implementation */ class NativeMethodAccessorImpl extends MethodAccessorImpl { - private Method method; + private final Method method; private DelegatingMethodAccessorImpl parent; private int numInvocations; diff --git a/src/share/classes/sun/reflect/ReflectionFactory.java b/src/share/classes/sun/reflect/ReflectionFactory.java index 0dbada7d5..dc26fab81 100644 --- a/src/share/classes/sun/reflect/ReflectionFactory.java +++ b/src/share/classes/sun/reflect/ReflectionFactory.java @@ -50,9 +50,9 @@ import sun.reflect.misc.ReflectUtil; public class ReflectionFactory { private static boolean initted = false; - private static Permission reflectionFactoryAccessPerm + private static final Permission reflectionFactoryAccessPerm = new RuntimePermission("reflectionFactoryAccess"); - private static ReflectionFactory soleInstance = new ReflectionFactory(); + private static final ReflectionFactory soleInstance = new ReflectionFactory(); // Provides access to package-private mechanisms in java.lang.reflect private static volatile LangReflectAccess langReflectAccess; diff --git a/src/share/classes/sun/reflect/SignatureIterator.java b/src/share/classes/sun/reflect/SignatureIterator.java index 7b4ac45cb..ea7fd3c80 100644 --- a/src/share/classes/sun/reflect/SignatureIterator.java +++ b/src/share/classes/sun/reflect/SignatureIterator.java @@ -28,7 +28,7 @@ package sun.reflect; /** Assists in iterating down a method's signature */ public class SignatureIterator { - private String sig; + private final String sig; private int idx; public SignatureIterator(String sig) { diff --git a/src/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java b/src/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java index 423a0ebf3..7520403ff 100644 --- a/src/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java +++ b/src/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java @@ -34,7 +34,7 @@ import java.util.Objects; */ public class GenericArrayTypeImpl implements GenericArrayType { - private Type genericComponentType; + private final Type genericComponentType; // private constructor enforces use of static factory private GenericArrayTypeImpl(Type ct) { diff --git a/src/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java b/src/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java index 7e80afb72..1addbcc9c 100644 --- a/src/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java +++ b/src/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java @@ -38,9 +38,9 @@ import java.util.Objects; /** Implementing class for ParameterizedType interface. */ public class ParameterizedTypeImpl implements ParameterizedType { - private Type[] actualTypeArguments; - private Class<?> rawType; - private Type ownerType; + private final Type[] actualTypeArguments; + private final Class<?> rawType; + private final Type ownerType; private ParameterizedTypeImpl(Class<?> rawType, Type[] actualTypeArguments, diff --git a/src/share/classes/sun/reflect/generics/scope/DummyScope.java b/src/share/classes/sun/reflect/generics/scope/DummyScope.java index 3370c9f3b..8a012dc33 100644 --- a/src/share/classes/sun/reflect/generics/scope/DummyScope.java +++ b/src/share/classes/sun/reflect/generics/scope/DummyScope.java @@ -38,7 +38,7 @@ import java.lang.reflect.TypeVariable; public class DummyScope implements Scope { // Caches the unique instance of this class; instances contain no data // so we can use the singleton pattern - private static DummyScope singleton = new DummyScope(); + private static final DummyScope singleton = new DummyScope(); // constructor is private to enforce use of factory method private DummyScope(){} diff --git a/src/share/classes/sun/reflect/generics/tree/ArrayTypeSignature.java b/src/share/classes/sun/reflect/generics/tree/ArrayTypeSignature.java index b6606d2fb..ba0a0d416 100644 --- a/src/share/classes/sun/reflect/generics/tree/ArrayTypeSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/ArrayTypeSignature.java @@ -28,7 +28,7 @@ package sun.reflect.generics.tree; import sun.reflect.generics.visitor.TypeTreeVisitor; public class ArrayTypeSignature implements FieldTypeSignature { - private TypeSignature componentType; + private final TypeSignature componentType; private ArrayTypeSignature(TypeSignature ct) {componentType = ct;} diff --git a/src/share/classes/sun/reflect/generics/tree/BooleanSignature.java b/src/share/classes/sun/reflect/generics/tree/BooleanSignature.java index 5e3b8a3e4..133c7e191 100644 --- a/src/share/classes/sun/reflect/generics/tree/BooleanSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/BooleanSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type boolean. */ public class BooleanSignature implements BaseType { - private static BooleanSignature singleton = new BooleanSignature(); + private static final BooleanSignature singleton = new BooleanSignature(); private BooleanSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/BottomSignature.java b/src/share/classes/sun/reflect/generics/tree/BottomSignature.java index b0aaedb2f..0fbbe2ea5 100644 --- a/src/share/classes/sun/reflect/generics/tree/BottomSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/BottomSignature.java @@ -28,7 +28,7 @@ package sun.reflect.generics.tree; import sun.reflect.generics.visitor.TypeTreeVisitor; public class BottomSignature implements FieldTypeSignature { - private static BottomSignature singleton = new BottomSignature(); + private static final BottomSignature singleton = new BottomSignature(); private BottomSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/ByteSignature.java b/src/share/classes/sun/reflect/generics/tree/ByteSignature.java index 47b64f903..5335782fc 100644 --- a/src/share/classes/sun/reflect/generics/tree/ByteSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/ByteSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type byte. */ public class ByteSignature implements BaseType { - private static ByteSignature singleton = new ByteSignature(); + private static final ByteSignature singleton = new ByteSignature(); private ByteSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/CharSignature.java b/src/share/classes/sun/reflect/generics/tree/CharSignature.java index 365c36108..44766a577 100644 --- a/src/share/classes/sun/reflect/generics/tree/CharSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/CharSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type char. */ public class CharSignature implements BaseType { - private static CharSignature singleton = new CharSignature(); + private static final CharSignature singleton = new CharSignature(); private CharSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/ClassTypeSignature.java b/src/share/classes/sun/reflect/generics/tree/ClassTypeSignature.java index f16622bf6..320764a4f 100644 --- a/src/share/classes/sun/reflect/generics/tree/ClassTypeSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/ClassTypeSignature.java @@ -33,7 +33,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; * AST representing class types. */ public class ClassTypeSignature implements FieldTypeSignature { - private List<SimpleClassTypeSignature> path; + private final List<SimpleClassTypeSignature> path; private ClassTypeSignature(List<SimpleClassTypeSignature> p) { diff --git a/src/share/classes/sun/reflect/generics/tree/DoubleSignature.java b/src/share/classes/sun/reflect/generics/tree/DoubleSignature.java index 533d43e54..a394228eb 100644 --- a/src/share/classes/sun/reflect/generics/tree/DoubleSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/DoubleSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type double. */ public class DoubleSignature implements BaseType { - private static DoubleSignature singleton = new DoubleSignature(); + private static final DoubleSignature singleton = new DoubleSignature(); private DoubleSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/FloatSignature.java b/src/share/classes/sun/reflect/generics/tree/FloatSignature.java index 61f8f45cc..70bf8c5c3 100644 --- a/src/share/classes/sun/reflect/generics/tree/FloatSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/FloatSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type float. */ public class FloatSignature implements BaseType { - private static FloatSignature singleton = new FloatSignature(); + private static final FloatSignature singleton = new FloatSignature(); private FloatSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java b/src/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java index 262cdb3d5..c25c41797 100644 --- a/src/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java +++ b/src/share/classes/sun/reflect/generics/tree/FormalTypeParameter.java @@ -29,8 +29,8 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents a formal type parameter. */ public class FormalTypeParameter implements TypeTree { - private String name; - private FieldTypeSignature[] bounds; + private final String name; + private final FieldTypeSignature[] bounds; private FormalTypeParameter(String n, FieldTypeSignature[] bs) { name = n; diff --git a/src/share/classes/sun/reflect/generics/tree/IntSignature.java b/src/share/classes/sun/reflect/generics/tree/IntSignature.java index e622b2350..e1d3a4439 100644 --- a/src/share/classes/sun/reflect/generics/tree/IntSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/IntSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type int. */ public class IntSignature implements BaseType { - private static IntSignature singleton = new IntSignature(); + private static final IntSignature singleton = new IntSignature(); private IntSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/LongSignature.java b/src/share/classes/sun/reflect/generics/tree/LongSignature.java index a730a983c..13eef0596 100644 --- a/src/share/classes/sun/reflect/generics/tree/LongSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/LongSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type long. */ public class LongSignature implements BaseType { - private static LongSignature singleton = new LongSignature(); + private static final LongSignature singleton = new LongSignature(); private LongSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/MethodTypeSignature.java b/src/share/classes/sun/reflect/generics/tree/MethodTypeSignature.java index 2d4bc1947..efbda03bf 100644 --- a/src/share/classes/sun/reflect/generics/tree/MethodTypeSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/MethodTypeSignature.java @@ -28,10 +28,10 @@ package sun.reflect.generics.tree; import sun.reflect.generics.visitor.Visitor; public class MethodTypeSignature implements Signature { - private FormalTypeParameter[] formalTypeParams; - private TypeSignature[] parameterTypes; - private ReturnType returnType; - private FieldTypeSignature[] exceptionTypes; + private final FormalTypeParameter[] formalTypeParams; + private final TypeSignature[] parameterTypes; + private final ReturnType returnType; + private final FieldTypeSignature[] exceptionTypes; private MethodTypeSignature(FormalTypeParameter[] ftps, TypeSignature[] pts, diff --git a/src/share/classes/sun/reflect/generics/tree/ShortSignature.java b/src/share/classes/sun/reflect/generics/tree/ShortSignature.java index ccdadcf0a..374f6fba8 100644 --- a/src/share/classes/sun/reflect/generics/tree/ShortSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/ShortSignature.java @@ -29,7 +29,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the type short. */ public class ShortSignature implements BaseType { - private static ShortSignature singleton = new ShortSignature(); + private static final ShortSignature singleton = new ShortSignature(); private ShortSignature(){} diff --git a/src/share/classes/sun/reflect/generics/tree/SimpleClassTypeSignature.java b/src/share/classes/sun/reflect/generics/tree/SimpleClassTypeSignature.java index 45ba803cf..8c287018f 100644 --- a/src/share/classes/sun/reflect/generics/tree/SimpleClassTypeSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/SimpleClassTypeSignature.java @@ -28,9 +28,9 @@ package sun.reflect.generics.tree; import sun.reflect.generics.visitor.TypeTreeVisitor; public class SimpleClassTypeSignature implements FieldTypeSignature { - private boolean dollar; - private String name; - private TypeArgument[] typeArgs; + private final boolean dollar; + private final String name; + private final TypeArgument[] typeArgs; private SimpleClassTypeSignature(String n, boolean dollar, TypeArgument[] tas) { name = n; diff --git a/src/share/classes/sun/reflect/generics/tree/TypeVariableSignature.java b/src/share/classes/sun/reflect/generics/tree/TypeVariableSignature.java index 68e46e546..9f1196586 100644 --- a/src/share/classes/sun/reflect/generics/tree/TypeVariableSignature.java +++ b/src/share/classes/sun/reflect/generics/tree/TypeVariableSignature.java @@ -28,7 +28,7 @@ package sun.reflect.generics.tree; import sun.reflect.generics.visitor.TypeTreeVisitor; public class TypeVariableSignature implements FieldTypeSignature { - private String identifier; + private final String identifier; private TypeVariableSignature(String id) {identifier = id;} diff --git a/src/share/classes/sun/reflect/generics/tree/VoidDescriptor.java b/src/share/classes/sun/reflect/generics/tree/VoidDescriptor.java index d685c60c6..5544ebc6b 100644 --- a/src/share/classes/sun/reflect/generics/tree/VoidDescriptor.java +++ b/src/share/classes/sun/reflect/generics/tree/VoidDescriptor.java @@ -30,7 +30,7 @@ import sun.reflect.generics.visitor.TypeTreeVisitor; /** AST that represents the pseudo-type void. */ public class VoidDescriptor implements ReturnType { - private static VoidDescriptor singleton = new VoidDescriptor(); + private static final VoidDescriptor singleton = new VoidDescriptor(); private VoidDescriptor(){} diff --git a/src/share/classes/sun/reflect/misc/MethodUtil.java b/src/share/classes/sun/reflect/misc/MethodUtil.java index b49ed0a65..ebe802b60 100644 --- a/src/share/classes/sun/reflect/misc/MethodUtil.java +++ b/src/share/classes/sun/reflect/misc/MethodUtil.java @@ -76,9 +76,9 @@ class Trampoline { * Create a trampoline class. */ public final class MethodUtil extends SecureClassLoader { - private static String MISC_PKG = "sun.reflect.misc."; - private static String TRAMPOLINE = MISC_PKG + "Trampoline"; - private static Method bounce = getTrampoline(); + private static final String MISC_PKG = "sun.reflect.misc."; + private static final String TRAMPOLINE = MISC_PKG + "Trampoline"; + private static final Method bounce = getTrampoline(); private MethodUtil() { super(); diff --git a/src/solaris/classes/sun/awt/X11/XDataTransferer.java b/src/solaris/classes/sun/awt/X11/XDataTransferer.java index fe8920d8c..3f97e0488 100644 --- a/src/solaris/classes/sun/awt/X11/XDataTransferer.java +++ b/src/solaris/classes/sun/awt/X11/XDataTransferer.java @@ -45,6 +45,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import javax.imageio.ImageIO; @@ -328,8 +329,9 @@ public class XDataTransferer extends DataTransferer { * a valid MIME and return a list of flavors to which the data in this MIME * type can be translated by the Data Transfer subsystem. */ - public List <DataFlavor> getPlatformMappingsForNative(String nat) { - List <DataFlavor> flavors = new ArrayList(); + public LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat) { + LinkedHashSet<DataFlavor> flavors = new LinkedHashSet<>(); + if (nat == null) { return flavors; @@ -389,8 +391,8 @@ public class XDataTransferer extends DataTransferer { * MIME types to which the data in this flavor can be translated by the Data * Transfer subsystem. */ - public List getPlatformMappingsForFlavor(DataFlavor df) { - List natives = new ArrayList(1); + public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) { + LinkedHashSet<String> natives = new LinkedHashSet<>(1); if (df == null) { return natives; diff --git a/src/solaris/classes/sun/awt/X11/XWM.java b/src/solaris/classes/sun/awt/X11/XWM.java index c76892ed0..33776d7b8 100644 --- a/src/solaris/classes/sun/awt/X11/XWM.java +++ b/src/solaris/classes/sun/awt/X11/XWM.java @@ -595,8 +595,13 @@ final class XWM return isNetWMName("Mutter") || isNetWMName("GNOME Shell"); } + static int awtWMNonReparenting = -1; static boolean isNonReparentingWM() { - return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM); + if (awtWMNonReparenting == -1) { + awtWMNonReparenting = (XToolkit.getEnv("_JAVA_AWT_WM_NONREPARENTING") != null) ? 1 : 0; + } + return (awtWMNonReparenting == 1 || XWM.getWMID() == XWM.COMPIZ_WM + || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM); } /* diff --git a/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java b/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java index b7b09e7b6..e66ffbe11 100644 --- a/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java +++ b/src/windows/classes/sun/java2d/d3d/D3DBlitLoops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -48,7 +48,7 @@ import sun.java2d.pipe.RenderQueue; import static sun.java2d.pipe.BufferedOpCodes.*; import sun.java2d.windows.GDIWindowSurfaceData; -class D3DBlitLoops { +final class D3DBlitLoops { static void register() { Blit blitIntArgbPreToSurface = @@ -57,7 +57,9 @@ class D3DBlitLoops { Blit blitIntArgbPreToTexture = new D3DSwToTextureBlit(SurfaceType.IntArgbPre, D3DSurfaceData.ST_INT_ARGB_PRE); - + TransformBlit transformBlitIntArgbPreToSurface = + new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre, + D3DSurfaceData.ST_INT_ARGB_PRE); GraphicsPrimitive[] primitives = { // prevent D3DSurface -> Screen blits new D3DSurfaceToGDIWindowSurfaceBlit(), @@ -123,8 +125,6 @@ class D3DBlitLoops { new D3DSwToSurfaceTransform(SurfaceType.IntArgb, D3DSurfaceData.ST_INT_ARGB), - new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre, - D3DSurfaceData.ST_INT_ARGB_PRE), new D3DSwToSurfaceTransform(SurfaceType.IntRgb, D3DSurfaceData.ST_INT_RGB), new D3DSwToSurfaceTransform(SurfaceType.IntBgr, @@ -140,6 +140,9 @@ class D3DBlitLoops { // REMIND: we don't have a native sw loop to back this loop up // new D3DSwToSurfaceTransform(SurfaceType.ByteIndexedBm, // D3DSurfaceData.ST_BYTE_INDEXED_BM), + transformBlitIntArgbPreToSurface, + + new D3DGeneralTransformedBlit(transformBlitIntArgbPreToSurface), // texture->surface ops new D3DTextureToSurfaceBlit(), @@ -712,11 +715,11 @@ class D3DTextureToSurfaceTransform extends TransformBlit { * This general Blit implementation converts any source surface to an * intermediate IntArgbPre surface, and then uses the more specific * IntArgbPre->D3DSurface/Texture loop to get the intermediate - * (premultiplied) surface down to D3D. + * (premultiplied) surface down to D3D using simple blit. */ class D3DGeneralBlit extends Blit { - private Blit performop; + private final Blit performop; private WeakReference srcTmp; D3DGeneralBlit(SurfaceType dstType, @@ -757,6 +760,49 @@ class D3DGeneralBlit extends Blit { } } +/** + * This general TransformedBlit implementation converts any source surface to an + * intermediate IntArgbPre surface, and then uses the more specific + * IntArgbPre->D3DSurface/Texture loop to get the intermediate + * (premultiplied) surface down to D3D using simple transformBlit. + */ +final class D3DGeneralTransformedBlit extends TransformBlit { + + private final TransformBlit performop; + private WeakReference<SurfaceData> srcTmp; + + D3DGeneralTransformedBlit(final TransformBlit performop) { + super(SurfaceType.Any, CompositeType.AnyAlpha, + D3DSurfaceData.D3DSurface); + this.performop = performop; + } + + @Override + public synchronized void Transform(SurfaceData src, SurfaceData dst, + Composite comp, Region clip, + AffineTransform at, int hint, int srcx, + int srcy, int dstx, int dsty, int width, + int height){ + Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), + CompositeType.SrcNoEa, + SurfaceType.IntArgbPre); + // use cached intermediate surface, if available + final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; + // convert source to IntArgbPre + src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, + BufferedImage.TYPE_INT_ARGB_PRE); + + // transform IntArgbPre intermediate surface to D3D surface + performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, + width, height); + + if (src != cachedSrc) { + // cache the intermediate surface + srcTmp = new WeakReference<>(src); + } + } +} + /* * The following classes prohibit copying D3DSurfaces to the screen * (the D3D->sysmem->GDI path is known to be very very slow). diff --git a/test/java/awt/datatransfer/MappingGenerationTest/MappingGenerationTest.java b/test/java/awt/datatransfer/MappingGenerationTest/MappingGenerationTest.java new file mode 100644 index 000000000..b0d8587af --- /dev/null +++ b/test/java/awt/datatransfer/MappingGenerationTest/MappingGenerationTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.SystemFlavorMap; +import java.util.List; + +/* + @test + @bug 4512530 8027148 + @summary tests that mappings for text flavors are generated properly + @author das@sparc.spb.su area=datatransfer +*/ + +public class MappingGenerationTest { + + private static final SystemFlavorMap fm = + (SystemFlavorMap)SystemFlavorMap.getDefaultFlavorMap(); + + public static void main(String[] args) { + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + } + + /** + * Verifies that Lists returned from getNativesForFlavor() and + * getFlavorsForNative() are not modified with a subsequent call + * to addUnencodedNativeForFlavor() and addFlavorForUnencodedNative() + * respectively. + */ + public static void test1() { + DataFlavor df = new DataFlavor("text/plain-test1", null); + String nat = "native1"; + + List<String> natives = fm.getNativesForFlavor(df); + fm.addUnencodedNativeForFlavor(df, nat); + List<String> nativesNew = fm.getNativesForFlavor(df); + if (natives.equals(nativesNew)) { + System.err.println("orig=" + natives); + System.err.println("new=" + nativesNew); + throw new RuntimeException("Test failed"); + } + + List<DataFlavor> flavors = fm.getFlavorsForNative(nat); + fm.addFlavorForUnencodedNative(nat, df); + List<DataFlavor> flavorsNew = fm.getFlavorsForNative(nat); + if (flavors.equals(flavorsNew)) { + System.err.println("orig=" + flavors); + System.err.println("new=" + flavorsNew); + throw new RuntimeException("Test failed"); + } + } + + /** + * Verifies that SystemFlavorMap is not affected by modification of + * the Lists returned from getNativesForFlavor() and + * getFlavorsForNative(). + */ + public static void test2() { + DataFlavor df = new DataFlavor("text/plain-test2", null); + String nat = "native2"; + DataFlavor extraDf = new DataFlavor("text/test", null); + + List<String> natives = fm.getNativesForFlavor(df); + natives.add("Should not be here"); + java.util.List nativesNew = fm.getNativesForFlavor(df); + if (natives.equals(nativesNew)) { + System.err.println("orig=" + natives); + System.err.println("new=" + nativesNew); + throw new RuntimeException("Test failed"); + } + + List<DataFlavor> flavors = fm.getFlavorsForNative(nat); + flavors.add(extraDf); + java.util.List flavorsNew = fm.getFlavorsForNative(nat); + if (flavors.equals(flavorsNew)) { + System.err.println("orig=" + flavors); + System.err.println("new=" + flavorsNew); + throw new RuntimeException("Test failed"); + } + } + + /** + * Verifies that addUnencodedNativeForFlavor() for a particular text flavor + * doesn't affect mappings for other flavors. + */ + public static void test3() { + DataFlavor df1 = new DataFlavor("text/plain-test3", null); + DataFlavor df2 = new DataFlavor("text/plain-test3; charset=Unicode; class=java.io.Reader", null); + String nat = "native3"; + List<String> natives = fm.getNativesForFlavor(df2); + fm.addUnencodedNativeForFlavor(df1, nat); + List<String> nativesNew = fm.getNativesForFlavor(df2); + if (!natives.equals(nativesNew)) { + System.err.println("orig=" + natives); + System.err.println("new=" + nativesNew); + throw new RuntimeException("Test failed"); + } + } + + /** + * Verifies that addUnencodedNativeForFlavor() really adds the specified + * flavor-to-native mapping to the existing mappings. + */ + public static void test4() { + DataFlavor df = new DataFlavor("text/plain-test4; charset=Unicode; class=java.io.Reader", null); + String nat = "native4"; + List<String> natives = fm.getNativesForFlavor(df); + if (!natives.contains(nat)) { + fm.addUnencodedNativeForFlavor(df, nat); + List<String> nativesNew = fm.getNativesForFlavor(df); + natives.add(nat); + if (!natives.equals(nativesNew)) { + System.err.println("orig=" + natives); + System.err.println("new=" + nativesNew); + throw new RuntimeException("Test failed"); + } + } + } + + /** + * Verifies that a flavor doesn't have any flavor-to-native mappings after + * a call to setNativesForFlavor() with this flavor and an empty native + * array as arguments. + */ + public static void test5() { + final DataFlavor flavor = + new DataFlavor("text/plain-TEST5; charset=Unicode", null); + + fm.getNativesForFlavor(flavor); + + fm.setNativesForFlavor(flavor, new String[0]); + + List<String> natives = fm.getNativesForFlavor(flavor); + + if (!natives.isEmpty()) { + System.err.println("natives=" + natives); + throw new RuntimeException("Test failed"); + } + } + + /** + * Verifies that a native doesn't have any native-to-flavor mappings after + * a call to setFlavorsForNative() with this native and an empty flavor + * array as arguments. + */ + public static void test6() { + final String nat = "STRING"; + fm.getFlavorsForNative(nat); + fm.setFlavorsForNative(nat, new DataFlavor[0]); + + List<DataFlavor> flavors = fm.getFlavorsForNative(nat); + + if (!flavors.isEmpty()) { + System.err.println("flavors=" + flavors); + throw new RuntimeException("Test failed"); + } + } +} diff --git a/test/java/awt/image/DrawImage/IncorrectAlphaConversionBicubic.java b/test/java/awt/image/DrawImage/IncorrectAlphaConversionBicubic.java new file mode 100644 index 000000000..901e6f795 --- /dev/null +++ b/test/java/awt/image/DrawImage/IncorrectAlphaConversionBicubic.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.VolatileImage; + +import static java.awt.Transparency.TRANSLUCENT; + +/** + * @test + * @bug 8062164 + * @summary We should get correct alpha, when we draw to/from VolatileImage and + * bicubic interpolation is enabled + * @author Sergey Bylokhov + */ +public final class IncorrectAlphaConversionBicubic { + + private static final Color RGB = new Color(200, 255, 7, 123); + private static final int SIZE = 100; + + public static void main(final String[] args) { + final GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + final GraphicsDevice gd = ge.getDefaultScreenDevice(); + final GraphicsConfiguration gc = gd.getDefaultConfiguration(); + final VolatileImage vi = + gc.createCompatibleVolatileImage(SIZE, SIZE, TRANSLUCENT); + final BufferedImage bi = makeUnmanagedBI(gc, TRANSLUCENT); + final int expected = bi.getRGB(2, 2); + + int attempt = 0; + BufferedImage snapshot; + while (true) { + if (++attempt > 10) { + throw new RuntimeException("Too many attempts: " + attempt); + } + vi.validate(gc); + final Graphics2D g2d = vi.createGraphics(); + g2d.setComposite(AlphaComposite.Src); + g2d.scale(2, 2); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2d.drawImage(bi, 0, 0, null); + g2d.dispose(); + + snapshot = vi.getSnapshot(); + if (vi.contentsLost()) { + continue; + } + break; + } + final int actual = snapshot.getRGB(2, 2); + if (actual != expected) { + System.err.println("Actual: " + Integer.toHexString(actual)); + System.err.println("Expected: " + Integer.toHexString(expected)); + throw new RuntimeException("Test failed"); + } + } + + private static BufferedImage makeUnmanagedBI(GraphicsConfiguration gc, + int type) { + BufferedImage img = gc.createCompatibleImage(SIZE, SIZE, type); + Graphics2D g2d = img.createGraphics(); + g2d.setColor(RGB); + g2d.fillRect(0, 0, SIZE, SIZE); + g2d.dispose(); + final DataBuffer db = img.getRaster().getDataBuffer(); + if (db instanceof DataBufferInt) { + ((DataBufferInt) db).getData(); + } else if (db instanceof DataBufferShort) { + ((DataBufferShort) db).getData(); + } else if (db instanceof DataBufferByte) { + ((DataBufferByte) db).getData(); + } else { + try { + img.setAccelerationPriority(0.0f); + } catch (final Throwable ignored) { + } + } + return img; + } +} diff --git a/test/java/awt/image/DrawImage/IncorrectClipXorModeSW2Surface.java b/test/java/awt/image/DrawImage/IncorrectClipXorModeSW2Surface.java new file mode 100644 index 000000000..da06f4f08 --- /dev/null +++ b/test/java/awt/image/DrawImage/IncorrectClipXorModeSW2Surface.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.VolatileImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import static java.awt.geom.Rectangle2D.Double; + +/** + * @test + * @bug 8061456 + * @summary Tests drawing BI to volatile image using different clips + xor mode. + * Results of the blit BI to compatibleImage is used for comparison. + * @author Sergey Bylokhov + */ +public final class IncorrectClipXorModeSW2Surface { + + private static int[] SIZES = {2, 10, 100}; + private static final Shape[] SHAPES = { + new Rectangle(0, 0, 0, 0), + new Rectangle(0, 0, 1, 1), + new Rectangle(0, 1, 1, 1), + new Rectangle(1, 0, 1, 1), + new Rectangle(1, 1, 1, 1), + + new Double(0, 0, 0.5, 0.5), + new Double(0, 0.5, 0.5, 0.5), + new Double(0.5, 0, 0.5, 0.5), + new Double(0.5, 0.5, 0.5, 0.5), + new Double(0.25, 0.25, 0.5, 0.5), + new Double(0, 0.25, 1, 0.5), + new Double(0.25, 0, 0.5, 1), + + new Double(.10, .10, .20, .20), + new Double(.75, .75, .20, .20), + new Double(.75, .10, .20, .20), + new Double(.10, .75, .20, .20), + }; + + public static void main(final String[] args) throws IOException { + GraphicsEnvironment ge = GraphicsEnvironment + .getLocalGraphicsEnvironment(); + GraphicsConfiguration gc = ge.getDefaultScreenDevice() + .getDefaultConfiguration(); + AffineTransform at; + for (int size : SIZES) { + at = AffineTransform.getScaleInstance(size, size); + for (Shape clip : SHAPES) { + clip = at.createTransformedShape(clip); + for (Shape to : SHAPES) { + to = at.createTransformedShape(to); + // Prepare test images + BufferedImage snapshot; + BufferedImage bi = getBufferedImage(size); + VolatileImage vi = getVolatileImage(gc, size); + while (true) { + vi.validate(gc); + Graphics2D g2d = vi.createGraphics(); + g2d.setColor(Color.GREEN); + g2d.fillRect(0, 0, size, size); + g2d.dispose(); + if (vi.validate(gc) != VolatileImage.IMAGE_OK) { + continue; + } + draw(clip, to, bi, vi); + snapshot = vi.getSnapshot(); + if (vi.contentsLost()) { + continue; + } + break; + } + // Prepare gold images + BufferedImage goldvi = getCompatibleImage(gc, size); + BufferedImage goldbi = getBufferedImage(size); + draw(clip, to, goldbi, goldvi); + validate(snapshot, goldvi); + vi.flush(); + } + } + } + } + + private static void draw(Shape clip, Shape shape, Image from, Image to) { + Graphics2D g2d = (Graphics2D) to.getGraphics(); + g2d.setXORMode(Color.BLACK); + g2d.setClip(clip); + Rectangle toBounds = shape.getBounds(); + g2d.drawImage(from, toBounds.x, toBounds.y, toBounds.width, + toBounds.height, null); + g2d.dispose(); + } + + private static BufferedImage getBufferedImage(int sw) { + final BufferedImage bi = new BufferedImage(sw, sw, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = bi.createGraphics(); + g2d.setColor(Color.RED); + g2d.fillRect(0, 0, sw, sw); + g2d.dispose(); + + final DataBuffer db = bi.getRaster().getDataBuffer(); + if (db instanceof DataBufferInt) { + ((DataBufferInt) db).getData(); + } else if (db instanceof DataBufferShort) { + ((DataBufferShort) db).getData(); + } else if (db instanceof DataBufferByte) { + ((DataBufferByte) db).getData(); + } else { + try { + bi.setAccelerationPriority(0.0f); + } catch (final Throwable ignored) { + } + } + return bi; + } + + private static VolatileImage getVolatileImage(GraphicsConfiguration gc, + int size) { + return gc.createCompatibleVolatileImage(size, size); + } + + private static BufferedImage getCompatibleImage(GraphicsConfiguration gc, + int size) { + BufferedImage image = gc.createCompatibleImage(size, size); + Graphics2D g2d = image.createGraphics(); + g2d.setColor(Color.GREEN); + g2d.fillRect(0, 0, size, size); + g2d.dispose(); + return image; + } + + private static void validate(BufferedImage bi, BufferedImage goldbi) + throws IOException { + for (int x = 0; x < bi.getWidth(); ++x) { + for (int y = 0; y < bi.getHeight(); ++y) { + if (goldbi.getRGB(x, y) != bi.getRGB(x, y)) { + ImageIO.write(bi, "png", new File("actual.png")); + ImageIO.write(goldbi, "png", new File("expected.png")); + throw new RuntimeException("Test failed."); + } + } + } + } +} diff --git a/test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java b/test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java new file mode 100644 index 000000000..98cbcd44f --- /dev/null +++ b/test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.VolatileImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import static java.awt.Transparency.*; +import static java.awt.image.BufferedImage.*; + +/** + * @test + * @bug 8029253 + * @summary Tests asymmetric source offsets when unmanaged image is drawn to VI. + * Results of the blit to compatibleImage are used for comparison. + * @author Sergey Bylokhov + */ +public final class IncorrectUnmanagedImageSourceOffset { + + private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB, + TYPE_INT_ARGB_PRE, TYPE_INT_BGR, + TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR, + TYPE_4BYTE_ABGR_PRE, + /*TYPE_USHORT_565_RGB, + TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY, + TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY, + TYPE_BYTE_INDEXED}; + private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT}; + + public static void main(final String[] args) throws IOException { + for (final int viType : TRANSPARENCIES) { + for (final int biType : TYPES) { + BufferedImage bi = makeUnmanagedBI(biType); + fill(bi); + test(bi, viType); + } + } + } + + private static void test(BufferedImage bi, int type) + throws IOException { + GraphicsEnvironment ge = GraphicsEnvironment + .getLocalGraphicsEnvironment(); + GraphicsConfiguration gc = ge.getDefaultScreenDevice() + .getDefaultConfiguration(); + VolatileImage vi = gc.createCompatibleVolatileImage(511, 255, type); + BufferedImage gold = gc.createCompatibleImage(511, 255, type); + // draw to compatible Image + Graphics2D big = gold.createGraphics(); + // force scaled blit + big.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null); + big.dispose(); + // draw to volatile image + BufferedImage snapshot; + while (true) { + vi.validate(gc); + if (vi.validate(gc) != VolatileImage.IMAGE_OK) { + try { + Thread.sleep(100); + } catch (final InterruptedException ignored) { + } + continue; + } + Graphics2D vig = vi.createGraphics(); + // force scaled blit + vig.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null); + vig.dispose(); + snapshot = vi.getSnapshot(); + if (vi.contentsLost()) { + try { + Thread.sleep(100); + } catch (final InterruptedException ignored) { + } + continue; + } + break; + } + // validate images + for (int x = 7; x < 127; ++x) { + for (int y = 11; y < 111; ++y) { + if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) { + ImageIO.write(gold, "png", new File("gold.png")); + ImageIO.write(snapshot, "png", new File("bi.png")); + throw new RuntimeException("Test failed."); + } + } + } + } + + private static BufferedImage makeUnmanagedBI(final int type) { + final BufferedImage bi = new BufferedImage(511, 255, type); + final DataBuffer db = bi.getRaster().getDataBuffer(); + if (db instanceof DataBufferInt) { + ((DataBufferInt) db).getData(); + } else if (db instanceof DataBufferShort) { + ((DataBufferShort) db).getData(); + } else if (db instanceof DataBufferByte) { + ((DataBufferByte) db).getData(); + } else { + try { + bi.setAccelerationPriority(0.0f); + } catch (final Throwable ignored) { + } + } + return bi; + } + + private static void fill(final Image image) { + final Graphics2D graphics = (Graphics2D) image.getGraphics(); + graphics.setComposite(AlphaComposite.Src); + for (int i = 0; i < image.getHeight(null); ++i) { + graphics.setColor(new Color(i, 0, 0)); + graphics.fillRect(0, i, image.getWidth(null), 1); + } + graphics.dispose(); + } +} diff --git a/test/java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java b/test/java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java new file mode 100644 index 000000000..e08bb9dec --- /dev/null +++ b/test/java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AlphaComposite; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.Polygon; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.VolatileImage; + +import static java.awt.Transparency.*; +import static java.awt.image.BufferedImage.*; + +/* + * @test + * @bug 8029253 8059941 + * @summary Unmanaged images should be drawn fast. + * @author Sergey Bylokhov + */ +public final class UnmanagedDrawImagePerformance { + + private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB, + TYPE_INT_ARGB_PRE, TYPE_INT_BGR, + TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR, + TYPE_4BYTE_ABGR_PRE, + TYPE_USHORT_565_RGB, + TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY, + TYPE_USHORT_GRAY, TYPE_BYTE_BINARY, + TYPE_BYTE_INDEXED}; + private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT}; + private static final int SIZE = 1000; + private static final AffineTransform[] TRANSFORMS = { + AffineTransform.getScaleInstance(.5, .5), + AffineTransform.getScaleInstance(1, 1), + AffineTransform.getScaleInstance(2, 2), + AffineTransform.getShearInstance(7, 11)}; + + public static void main(final String[] args) { + for (final AffineTransform atfm : TRANSFORMS) { + for (final int viType : TRANSPARENCIES) { + for (final int biType : TYPES) { + final BufferedImage bi = makeUnmanagedBI(biType); + final VolatileImage vi = makeVI(viType); + final long time = test(bi, vi, atfm) / 1000000000; + if (time > 1) { + throw new RuntimeException(String.format( + "drawImage is slow: %d seconds", time)); + } + } + } + } + } + + private static long test(Image bi, Image vi, AffineTransform atfm) { + final Polygon p = new Polygon(); + p.addPoint(0, 0); + p.addPoint(SIZE, 0); + p.addPoint(0, SIZE); + p.addPoint(SIZE, SIZE); + p.addPoint(0, 0); + Graphics2D g2d = (Graphics2D) vi.getGraphics(); + g2d.clip(p); + g2d.transform(atfm); + g2d.setComposite(AlphaComposite.SrcOver); + final long start = System.nanoTime(); + g2d.drawImage(bi, 0, 0, null); + final long time = System.nanoTime() - start; + g2d.dispose(); + return time; + } + + private static VolatileImage makeVI(final int type) { + final GraphicsEnvironment ge = GraphicsEnvironment + .getLocalGraphicsEnvironment(); + final GraphicsDevice gd = ge.getDefaultScreenDevice(); + final GraphicsConfiguration gc = gd.getDefaultConfiguration(); + return gc.createCompatibleVolatileImage(SIZE, SIZE, type); + } + + private static BufferedImage makeUnmanagedBI(final int type) { + final BufferedImage img = new BufferedImage(SIZE, SIZE, type); + final DataBuffer db = img.getRaster().getDataBuffer(); + if (db instanceof DataBufferInt) { + ((DataBufferInt) db).getData(); + } else if (db instanceof DataBufferShort) { + ((DataBufferShort) db).getData(); + } else if (db instanceof DataBufferByte) { + ((DataBufferByte) db).getData(); + } else { + try { + img.setAccelerationPriority(0.0f); + } catch (final Throwable ignored) { + } + } + return img; + } +} diff --git a/test/java/beans/Introspector/Test4168833.java b/test/java/beans/Introspector/Test4168833.java index 26cdb25f9..f3eea2c37 100644 --- a/test/java/beans/Introspector/Test4168833.java +++ b/test/java/beans/Introspector/Test4168833.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,11 @@ /* * @test - * @bug 4168833 + * @bug 4168833 8034085 * @summary Tests that Introspector does not create IndexedPropertyDescriptor * from non-indexed PropertyDescriptor * @author Mark Davidson + * @author Sergey Malenkov */ import java.awt.Color; @@ -42,10 +43,6 @@ import java.beans.PropertyDescriptor; */ public class Test4168833 { public static void main(String[] args) throws Exception { - IndexedPropertyDescriptor ipd = BeanUtils.getIndexedPropertyDescriptor(Base.class, "prop"); - if (!ipd.getIndexedPropertyType().equals(Dimension.class)) { - error(ipd, "Base.prop property should a Dimension"); - } // When the Sub class is introspected, // the property type should be color. // The complete "classic" set of properties diff --git a/test/java/beans/Introspector/Test8034085.java b/test/java/beans/Introspector/Test8034085.java new file mode 100644 index 000000000..25745a923 --- /dev/null +++ b/test/java/beans/Introspector/Test8034085.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Window; +import java.beans.IndexedPropertyDescriptor; +import java.beans.PropertyDescriptor; + +/* + * @test + * @bug 8034085 + * @summary Tests that Introspector ignores indexed getter and setter for incorrect types + * @author Sergey Malenkov + */ + +public class Test8034085 { + public static final StringBuilder ERROR = new StringBuilder(); + + public static void main(String[] args) { + test(Window.class, false, true, false, false); + + test(Bean0000.class, false, false, false, false); + test(Bean0001.class, false, false, false, true); + test(Bean0010.class, false, false, true, false); + test(Bean0011.class, false, false, true, true); + test(Bean0100.class, false, true, false, false); + test(Bean0101.class, false, true, false, false); + test(Bean0110.class, false, true, false, false); + test(Bean0111.class, false, true, false, false); + test(Bean1000.class, true, false, false, false); + test(Bean1001.class, true, false, false, false); + test(Bean1010.class, true, false, false, false); + test(Bean1011.class, true, false, false, false); + test(Bean1100.class, true, true, false, false); + test(Bean1101.class, true, true, false, false); + test(Bean1110.class, true, true, false, false); + test(Bean1111.class, true, true, false, false); + + if (0 < ERROR.length()) { + throw new Error(ERROR.toString()); + } + } + + private static void test(Class<?> type, boolean read, boolean write, boolean readIndexed, boolean writeIndexed) { + PropertyDescriptor pd = BeanUtils.findPropertyDescriptor(type, "size"); + if (pd != null) { + test(type, "read", read, null != pd.getReadMethod()); + test(type, "write", write, null != pd.getWriteMethod()); + if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + test(type, "indexed read", readIndexed, null != ipd.getIndexedReadMethod()); + test(type, "indexed write", writeIndexed, null != ipd.getIndexedWriteMethod()); + } else if (readIndexed || writeIndexed) { + error(type, "indexed property does not exist"); + } + } else if (read || write || readIndexed || writeIndexed) { + error(type, "property does not exist"); + } + } + + private static void test(Class<?> type, String name, boolean expected, boolean actual) { + if (expected && !actual) { + error(type, name + " method does not exist"); + } else if (!expected && actual) { + error(type, name + " method is not expected"); + } + } + + private static void error(Class<?> type, String message) { + ERROR.append("\n\t\t").append(type.getSimpleName()).append(".size: ").append(message); + } + + public static class Bean0000 { + } + + public static class Bean0001 { + public void setSize(int index, int value) { + } + } + + public static class Bean0010 { + public int getSize(int index) { + return 0; + } + } + + public static class Bean0011 { + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean0100 { + public void setSize(int value) { + } + } + + public static class Bean0101 { + public void setSize(int value) { + } + + public void setSize(int index, int value) { + } + } + + public static class Bean0110 { + public void setSize(int value) { + } + + public int getSize(int index) { + return 0; + } + } + + public static class Bean0111 { + public void setSize(int value) { + } + + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1000 { + public int getSize() { + return 0; + } + } + + public static class Bean1001 { + public int getSize() { + return 0; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1010 { + public int getSize() { + return 0; + } + + public int getSize(int index) { + return 0; + } + } + + public static class Bean1011 { + public int getSize() { + return 0; + } + + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1100 { + public int getSize() { + return 0; + } + + public void setSize(int value) { + } + } + + public static class Bean1101 { + public int getSize() { + return 0; + } + + public void setSize(int value) { + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1110 { + public int getSize() { + return 0; + } + + public void setSize(int value) { + } + + public int getSize(int index) { + return 0; + } + } + + public static class Bean1111 { + public int getSize() { + return 0; + } + + public void setSize(int value) { + } + + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } +} diff --git a/test/java/beans/Introspector/Test8034164.java b/test/java/beans/Introspector/Test8034164.java new file mode 100644 index 000000000..d35996053 --- /dev/null +++ b/test/java/beans/Introspector/Test8034164.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.beans.IndexedPropertyDescriptor; +import java.beans.PropertyDescriptor; + +/* + * @test + * @bug 8034164 + * @summary Tests that Introspector does not ignore indexed getter and setter for correct types + * @author Sergey Malenkov + */ + +public class Test8034164 { + public static final StringBuilder ERROR = new StringBuilder(); + + public static void main(String[] args) { + test(Bean0000.class, false, false, false, false); + test(Bean0001.class, false, false, false, true); + test(Bean0010.class, false, false, true, false); + test(Bean0011.class, false, false, true, true); + test(Bean0100.class, false, true, false, false); + test(Bean0101.class, false, true, false, true); + test(Bean0110.class, false, true, true, false); + test(Bean0111.class, false, true, true, true); + test(Bean1000.class, true, false, false, false); + test(Bean1001.class, true, false, false, true); + test(Bean1010.class, true, false, true, false); + test(Bean1011.class, true, false, true, true); + test(Bean1100.class, true, true, false, false); + test(Bean1101.class, true, true, false, true); + test(Bean1110.class, true, true, true, false); + test(Bean1111.class, true, true, true, true); + + if (0 < ERROR.length()) { + throw new Error(ERROR.toString()); + } + } + + private static void test(Class<?> type, boolean read, boolean write, boolean readIndexed, boolean writeIndexed) { + PropertyDescriptor pd = BeanUtils.findPropertyDescriptor(type, "size"); + if (pd != null) { + test(type, "read", read, null != pd.getReadMethod()); + test(type, "write", write, null != pd.getWriteMethod()); + if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + test(type, "indexed read", readIndexed, null != ipd.getIndexedReadMethod()); + test(type, "indexed write", writeIndexed, null != ipd.getIndexedWriteMethod()); + } else if (readIndexed || writeIndexed) { + error(type, "indexed property does not exist"); + } + } else if (read || write || readIndexed || writeIndexed) { + error(type, "property does not exist"); + } + } + + private static void test(Class<?> type, String name, boolean expected, boolean actual) { + if (expected && !actual) { + error(type, name + " method does not exist"); + } else if (!expected && actual) { + error(type, name + " method is not expected"); + } + } + + private static void error(Class<?> type, String message) { + ERROR.append("\n\t\t").append(type.getSimpleName()).append(".size: ").append(message); + } + + public static class Bean0000 { + } + + public static class Bean0001 { + public void setSize(int index, int value) { + } + } + + public static class Bean0010 { + public int getSize(int index) { + return 0; + } + } + + public static class Bean0011 { + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean0100 { + public void setSize(int[] value) { + } + } + + public static class Bean0101 { + public void setSize(int[] value) { + } + + public void setSize(int index, int value) { + } + } + + public static class Bean0110 { + public void setSize(int[] value) { + } + + public int getSize(int index) { + return 0; + } + } + + public static class Bean0111 { + public void setSize(int[] value) { + } + + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1000 { + public int[] getSize() { + return null; + } + } + + public static class Bean1001 { + public int[] getSize() { + return null; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1010 { + public int[] getSize() { + return null; + } + + public int getSize(int index) { + return 0; + } + } + + public static class Bean1011 { + public int[] getSize() { + return null; + } + + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1100 { + public int[] getSize() { + return null; + } + + public void setSize(int[] value) { + } + } + + public static class Bean1101 { + public int[] getSize() { + return null; + } + + public void setSize(int[] value) { + } + + public void setSize(int index, int value) { + } + } + + public static class Bean1110 { + public int[] getSize() { + return null; + } + + public void setSize(int[] value) { + } + + public int getSize(int index) { + return 0; + } + } + + public static class Bean1111 { + public int[] getSize() { + return null; + } + + public void setSize(int[] value) { + } + + public int getSize(int index) { + return 0; + } + + public void setSize(int index, int value) { + } + } +} diff --git a/test/java/lang/instrument/DaemonThread/TestDaemonThread.java b/test/java/lang/instrument/DaemonThread/TestDaemonThread.java index 12246b1a6..5346f73b1 100644 --- a/test/java/lang/instrument/DaemonThread/TestDaemonThread.java +++ b/test/java/lang/instrument/DaemonThread/TestDaemonThread.java @@ -28,7 +28,7 @@ * * @build jdk.testlibrary.* DummyAgent DummyClass TestDaemonThreadLauncher TestDaemonThread * @run shell ../MakeJAR3.sh DummyAgent - * @run main TestDaemonThreadLauncher /timeout=240 + * @run main/timeout=240 TestDaemonThreadLauncher * */ import java.io.File; diff --git a/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java index 3b9ed4dea..451af074b 100644 --- a/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java +++ b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java @@ -31,7 +31,7 @@ * @build TestMethods * @build LambdaFormTestCase * @build LFGarbageCollectedTest - * @run main/othervm/timeout=600 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true -DtestLimit=150 LFGarbageCollectedTest + * @run main/othervm/timeout=600 -DtestLimit=150 LFGarbageCollectedTest */ import java.lang.invoke.MethodHandle; diff --git a/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java index a41647246..21771c1a0 100644 --- a/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java +++ b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java @@ -31,7 +31,7 @@ * @build LambdaFormTestCase * @build LFCachingTestCase * @build LFMultiThreadCachingTest - * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFMultiThreadCachingTest + * @run main/othervm/timeout=300 LFMultiThreadCachingTest */ import java.lang.invoke.MethodHandle; diff --git a/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java index 21221aa7c..bd0ba2bde 100644 --- a/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java +++ b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java @@ -31,7 +31,7 @@ * @build LambdaFormTestCase * @build LFCachingTestCase * @build LFSingleThreadCachingTest - * @run main/othervm/timeout=300 -Djava.lang.invoke.MethodHandle.USE_LF_EDITOR=true LFSingleThreadCachingTest + * @run main/othervm/timeout=300 LFSingleThreadCachingTest */ import java.lang.invoke.MethodHandle; diff --git a/test/java/lang/reflect/Generics/ThreadSafety.java b/test/java/lang/reflect/Generics/ThreadSafety.java new file mode 100644 index 000000000..801bb9c23 --- /dev/null +++ b/test/java/lang/reflect/Generics/ThreadSafety.java @@ -0,0 +1,129 @@ +/* + * Copyright 2014 Google Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8062771 8016236 + * @summary Test publication of Class objects via a data race + * @run testng ThreadSafety + */ + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Collections; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.Callable; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeoutException; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +/** + * A test resulting from an attempt to repro this failure (in guice): + * + * java.lang.NullPointerException + * at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:125) + * at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49) + * at sun.reflect.generics.repository.ClassRepository.getSuperclass(ClassRepository.java:84) + * at java.lang.Class.getGenericSuperclass(Class.java:692) + * at com.google.inject.TypeLiteral.getSuperclassTypeParameter(TypeLiteral.java:99) + * at com.google.inject.TypeLiteral.<init>(TypeLiteral.java:79) + * + * However, as one would expect with thread safety problems in reflection, these + * are very hard to reproduce. This very test has never been observed to fail, + * but a similar test has been observed to fail about once in 2000 executions + * (about once every 6 CPU-hours), in jdk7 only. It appears to be fixed in jdk8+ by: + * + * 8016236: Class.getGenericInterfaces performance improvement. + * (by making Class.genericInfo volatile) + */ +public class ThreadSafety { + public static class EmptyClass { + public static class EmptyGenericSuperclass<T> {} + public static class EmptyGenericSubclass<T> extends EmptyGenericSuperclass<T> {} + } + + /** published via data race */ + private Class<?> racyClass = Object.class; + + private URL[] urls = ((URLClassLoader) ThreadSafety.class.getClassLoader()).getURLs(); + + private Class<?> createNewEmptyGenericSubclassClass() throws Exception { + URLClassLoader ucl = new URLClassLoader(urls, null); + return Class.forName("ThreadSafety$EmptyClass$EmptyGenericSubclass", true, ucl); + } + + @Test + public void testRacy_getGenericSuperclass() throws Exception { + final int nThreads = 10; + final int iterations = 30; + final int timeout = 10; + final CyclicBarrier newCycle = new CyclicBarrier(nThreads); + final Callable<Void> task = new Callable<Void>() { + public Void call() throws Exception { + for (int i = 0; i < iterations; i++) { + final int threadId; + try { + threadId = newCycle.await(timeout, SECONDS); + } catch (BrokenBarrierException e) { + return null; + } + for (int j = 0; j < iterations; j++) { + // one thread publishes the class object via a data + // race, for the other threads to consume. + if (threadId == 0) { + racyClass = createNewEmptyGenericSubclassClass(); + } else { + racyClass.getGenericSuperclass(); + } + } + } + return null; + }}; + + final ExecutorService pool = Executors.newFixedThreadPool(nThreads); + try { + for (Future<Void> future : + pool.invokeAll(Collections.nCopies(nThreads, task))) { + try { + future.get(iterations * timeout, SECONDS); + } catch (ExecutionException e) { + // ignore "collateral damage" + if (!(e.getCause() instanceof BrokenBarrierException) + && + !(e.getCause() instanceof TimeoutException)) { + throw e; + } + } + } + } finally { + pool.shutdownNow(); + assertTrue(pool.awaitTermination(2 * timeout, SECONDS)); + } + } +} diff --git a/test/javax/swing/DataTransfer/8059739/bug8059739.java b/test/javax/swing/DataTransfer/8059739/bug8059739.java new file mode 100644 index 000000000..b2b8bada4 --- /dev/null +++ b/test/javax/swing/DataTransfer/8059739/bug8059739.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 8059739 + @summary Dragged and Dropped data is corrupted for two data types + @author Anton Nashatyrev +*/ + +import javax.swing.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class bug8059739 { + + private static boolean passed = true; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + runTest(); + } catch (Exception e) { + e.printStackTrace(); + passed = false; + } + } + }); + + if (!passed) { + throw new RuntimeException("Test FAILED."); + } else { + System.out.println("Passed."); + } + } + + private static void runTest() throws Exception { + String testString = "my string"; + JTextField tf = new JTextField(testString); + tf.selectAll(); + Clipboard clipboard = new Clipboard("clip"); + tf.getTransferHandler().exportToClipboard(tf, clipboard, TransferHandler.COPY); + DataFlavor[] dfs = clipboard.getAvailableDataFlavors(); + for (DataFlavor df: dfs) { + String charset = df.getParameter("charset"); + if (InputStream.class.isAssignableFrom(df.getRepresentationClass()) && + charset != null) { + BufferedReader br = new BufferedReader(new InputStreamReader( + (InputStream) clipboard.getData(df), charset)); + String s = br.readLine(); + System.out.println("Content: '" + s + "'"); + passed &= s.contains(testString); + } + } + } +} diff --git a/test/javax/swing/JColorChooser/8065098/JColorChooserDnDTest.java b/test/javax/swing/JColorChooser/8065098/JColorChooserDnDTest.java new file mode 100644 index 000000000..fdd66248c --- /dev/null +++ b/test/javax/swing/JColorChooser/8065098/JColorChooserDnDTest.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import javax.swing.BorderFactory; +import javax.swing.JColorChooser; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +/* + * @bug 8065098 + * @summary JColorChooser no longer supports drag and drop + * between two JVM instances + */ +public class JColorChooserDnDTest { + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel panel = new JPanel(); + JColorChooser colorChooser = new JColorChooser(); + colorChooser.setDragEnabled(true); + panel.setBorder(BorderFactory.createTitledBorder("JColorChoosers")); + panel.add(colorChooser); + frame.setContentPane(panel); + frame.pack(); + frame.setVisible(true); + } + }); + } +} diff --git a/test/javax/swing/JColorChooser/8065098/bug8065098.html b/test/javax/swing/JColorChooser/8065098/bug8065098.html new file mode 100644 index 000000000..2543255d0 --- /dev/null +++ b/test/javax/swing/JColorChooser/8065098/bug8065098.html @@ -0,0 +1,40 @@ +<!-- + Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> + +<html> + <body> + 1. Compile the java test JColorChooserDnDTest.java: + > <path-to-the-tested-jdk>/bin/javac JColorChooserDnDTest.java + 2. Run the first instance of the java test: + > <path-to-the-tested-jdk>/bin/java JColorChooserDnDTest + 3. Select a color in the color chooser + 4. Run the second instance of the java test: + > <path-to-the-tested-jdk>/bin/java JColorChooserDnDTest + 5. Drag and drop the selected color from the first color chooser + preview panel to the second color chooser preview panel + 6. If the color is dragged to the second color chooser then the test passes. + + <applet width="500" height="1" code="bug8065098.class"> + </applet> +</body> +</html>
\ No newline at end of file diff --git a/test/javax/swing/JColorChooser/8065098/bug8065098.java b/test/javax/swing/JColorChooser/8065098/bug8065098.java new file mode 100644 index 000000000..0fadffc42 --- /dev/null +++ b/test/javax/swing/JColorChooser/8065098/bug8065098.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import javax.swing.JApplet; + +/* + * @test + * @bug 8065098 + * @summary JColorChooser no longer supports drag and drop + * between two JVM instances + * @run applet/manual=yesno bug8065098.html + */ +public class bug8065098 extends JApplet { + +} diff --git a/test/javax/swing/JComboBox/ConsumedEscTest/ConsumedEscTest.java b/test/javax/swing/JComboBox/ConsumedKeyTest/ConsumedKeyTest.java index 9976730a6..ab283691d 100644 --- a/test/javax/swing/JComboBox/ConsumedEscTest/ConsumedEscTest.java +++ b/test/javax/swing/JComboBox/ConsumedKeyTest/ConsumedKeyTest.java @@ -24,22 +24,28 @@ import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; -import java.awt.Robot; import java.awt.Toolkit; +import java.awt.Robot; import sun.awt.SunToolkit; /* @test - @bug 8031485 + @bug 8031485 8058193 @summary Combo box consuming escape and enter key events @author Petr Pchelko - @run main ConsumedEscTest + @run main ConsumedKeyTest */ -public class ConsumedEscTest { +public class ConsumedKeyTest { private static volatile JFrame frame; - private static volatile boolean passed = false; + private static volatile boolean passed; public static void main(String... args) throws Exception { + test(KeyEvent.VK_ESCAPE); + test(KeyEvent.VK_ENTER); + } + + private static void test(final int key) throws Exception { + passed = false; try { SwingUtilities.invokeAndWait(() -> { frame = new JFrame(); @@ -48,7 +54,7 @@ public class ConsumedEscTest { panel.add(combo); combo.requestFocusInWindow(); frame.setBounds(100, 150, 300, 100); - addAction(panel); + addAction(panel, key); frame.add(panel); frame.setVisible(true); }); @@ -56,24 +62,25 @@ public class ConsumedEscTest { Robot robot = new Robot(); robot.waitForIdle(); ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); - robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyPress(key); robot.waitForIdle(); ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); - robot.keyRelease(KeyEvent.VK_ESCAPE); + robot.keyRelease(key); robot.waitForIdle(); ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); if (!passed) { - throw new RuntimeException("FAILED: ESC was consumed by combo box"); + throw new RuntimeException("FAILED: " + KeyEvent.getKeyText(key) + " was consumed by combo box"); } } finally { if (frame != null) { frame.dispose(); } } + } - private static void addAction(JComponent comp) { - KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); + private static void addAction(JComponent comp, final int key) { + KeyStroke k = KeyStroke.getKeyStroke(key, 0); Object actionKey = "cancel"; comp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(k, actionKey); Action cancelAction = new AbstractAction() { @@ -84,5 +91,4 @@ public class ConsumedEscTest { }; comp.getActionMap().put(actionKey, cancelAction); } - } diff --git a/test/sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java b/test/sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java index 7c323d691..be6c97f4f 100644 --- a/test/sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java +++ b/test/sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -89,8 +89,13 @@ public class OnScreenRenderingResizeTest { public void update(Graphics g) {} }; frame.setBackground(bgColor); + frame.setUndecorated(true); frame.pack(); - frame.setSize(FRAME_W, FRAME_H); + + GraphicsConfiguration gc = frame.getGraphicsConfiguration(); + Rectangle gcBounds = gc.getBounds(); + frame.setBounds(gcBounds.width / 4, gcBounds.height / 4, FRAME_W, FRAME_H); + frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { done = true; @@ -108,9 +113,8 @@ public class OnScreenRenderingResizeTest { ex.printStackTrace(); } - GraphicsConfiguration gc = frame.getGraphicsConfiguration(); - int maxW = gc.getBounds().width /2; - int maxH = gc.getBounds().height/2; + int maxW = gcBounds.width /2; + int maxH = gcBounds.height/2; int minW = frame.getWidth(); int minH = frame.getHeight(); int incW = 10, incH = 10, cnt = 0; @@ -155,6 +159,7 @@ public class OnScreenRenderingResizeTest { Insets in = frame.getInsets(); frame.getGraphics().drawImage(output, in.left, in.top, null); if (cnt == 90 && robot != null) { + robot.waitForIdle(); // area where we blitted to should be either white or green Point p = frame.getLocationOnScreen(); p.translate(in.left+10, in.top+10); @@ -172,7 +177,7 @@ public class OnScreenRenderingResizeTest { frame.getWidth()-in.left-in.right, frame.getHeight()-in.top-in.bottom-5-IMAGE_H)); int accepted2[] = { Color.white.getRGB() }; - checkBI(bi, accepted1); + checkBI(bi, accepted2); } Thread.yield(); diff --git a/test/sun/net/www/http/HttpClient/StreamingRetry.java b/test/sun/net/www/http/HttpClient/StreamingRetry.java index 03c5b503e..35dbc51d2 100644 --- a/test/sun/net/www/http/HttpClient/StreamingRetry.java +++ b/test/sun/net/www/http/HttpClient/StreamingRetry.java @@ -23,8 +23,8 @@ /* * @test - * @bug 6672144 - * @summary HttpURLConnection.getInputStream sends POST request after failed chunked send + * @bug 6672144 8050983 + * @summary Do not retry failed request with a streaming body. */ import java.net.HttpURLConnection; @@ -33,6 +33,7 @@ import java.net.URL; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import static java.lang.System.out; public class StreamingRetry implements Runnable { static final int ACCEPT_TIMEOUT = 20 * 1000; // 20 seconds @@ -43,11 +44,17 @@ public class StreamingRetry implements Runnable { } void instanceMain() throws IOException { - test(); + out.println("Test with default method"); + test(null); + out.println("Test with POST method"); + test("POST"); + out.println("Test with PUT method"); + test("PUT"); + if (failed > 0) throw new RuntimeException("Some tests failed"); } - void test() throws IOException { + void test(String method) throws IOException { ss = new ServerSocket(0); ss.setSoTimeout(ACCEPT_TIMEOUT); int port = ss.getLocalPort(); @@ -58,6 +65,8 @@ public class StreamingRetry implements Runnable { URL url = new URL("http://localhost:" + port + "/"); HttpURLConnection uc = (HttpURLConnection) url.openConnection(); uc.setDoOutput(true); + if (method != null) + uc.setRequestMethod(method); uc.setChunkedStreamingMode(4096); OutputStream os = uc.getOutputStream(); os.write("Hello there".getBytes()); @@ -79,7 +88,7 @@ public class StreamingRetry implements Runnable { ss.close(); fail("The server shouldn't accept a second connection"); } catch (IOException e) { - //OK, the clien will close the server socket if successfull + //OK, the client will close the server socket if successful } } |