diff options
Diffstat (limited to 'src')
60 files changed, 850 insertions, 560 deletions
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). |