提交 8c50098c 编写于 作者: M mullan

Merge

...@@ -117,3 +117,4 @@ d80954a89b49fda47c0c5cace65a17f5a758b8bd jdk7-b139 ...@@ -117,3 +117,4 @@ d80954a89b49fda47c0c5cace65a17f5a758b8bd jdk7-b139
9315c733fb17ddfb9fb44be7e0ffea37bf3c727d jdk7-b140 9315c733fb17ddfb9fb44be7e0ffea37bf3c727d jdk7-b140
63eeefe118da18c75ba3d36266768cd1ccaaca6b jdk7-b141 63eeefe118da18c75ba3d36266768cd1ccaaca6b jdk7-b141
312612e89ece62633f4809706dec00bcd5fe7c2d jdk7-b142 312612e89ece62633f4809706dec00bcd5fe7c2d jdk7-b142
efbf75c24b0f31847c9c403f6dc07dc80551908d jdk7-b143
...@@ -85,16 +85,21 @@ REMOTE_impls = \ ...@@ -85,16 +85,21 @@ REMOTE_impls = \
sun.rmi.registry.RegistryImpl \ sun.rmi.registry.RegistryImpl \
sun.rmi.transport.DGCImpl sun.rmi.transport.DGCImpl
ifeq ($(PLATFORM), windows) #
build: stubs # The java-rmi.cgi script in bin/ only gets delivered in certain situations
else # PLATFORM #
ifneq ($(ARCH_DATA_MODEL), 32) BUILD_TARGETS = stubs
build: stubs ifeq ($(PLATFORM), linux)
else # ARCH_DATA_MODEL BUILD_TARGETS += bin
build: stubs bin
endif endif
ifeq ($(PLATFORM), solaris)
ifeq ($(ARCH_DATA_MODEL), 32)
BUILD_TARGETS += bin
endif
endif endif
build: $(BUILD_TARGETS)
clean clobber:: bin.clean clean clobber:: bin.clean
......
...@@ -158,7 +158,6 @@ SUNWprivate_1.1 { ...@@ -158,7 +158,6 @@ SUNWprivate_1.1 {
Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl; Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl;
Java_sun_awt_X11_XRobotPeer_mouseWheelImpl; Java_sun_awt_X11_XRobotPeer_mouseWheelImpl;
Java_sun_awt_X11_XRobotPeer_setup; Java_sun_awt_X11_XRobotPeer_setup;
Java_sun_awt_X11_XRobotPeer__1dispose;
Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl; Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl;
Java_java_awt_Component_initIDs; Java_java_awt_Component_initIDs;
Java_java_awt_Container_initIDs; Java_java_awt_Container_initIDs;
......
...@@ -2887,11 +2887,12 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -2887,11 +2887,12 @@ public abstract class Component implements ImageObserver, MenuContainer,
/** /**
* Invalidates this component and its ancestors. * Invalidates this component and its ancestors.
* <p> * <p>
* All the ancestors of this component up to the nearest validate root are * By default, all the ancestors of the component up to the top-most
* marked invalid also. If there is no a validate root container for this * container of the hierarchy are marked invalid. If the {@code
* component, all of its ancestors up to the root of the hierarchy are * java.awt.smartInvalidate} system property is set to {@code true},
* marked invalid as well. Marking a container <i>invalid</i> indicates * invalidation stops on the nearest validate root of this component.
* that the container needs to be laid out. * Marking a container <i>invalid</i> indicates that the container needs to
* be laid out.
* <p> * <p>
* This method is called automatically when any layout-related information * This method is called automatically when any layout-related information
* changes (e.g. setting the bounds of the component, or adding the * changes (e.g. setting the bounds of the component, or adding the
......
...@@ -41,6 +41,8 @@ import java.io.ObjectStreamField; ...@@ -41,6 +41,8 @@ import java.io.ObjectStreamField;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.security.AccessController;
import java.util.Arrays; import java.util.Arrays;
import java.util.EventListener; import java.util.EventListener;
import java.util.HashSet; import java.util.HashSet;
...@@ -60,6 +62,8 @@ import sun.awt.dnd.SunDropTargetEvent; ...@@ -60,6 +62,8 @@ import sun.awt.dnd.SunDropTargetEvent;
import sun.java2d.pipe.Region; import sun.java2d.pipe.Region;
import sun.security.action.GetBooleanAction;
/** /**
* A generic Abstract Window Toolkit(AWT) container object is a component * A generic Abstract Window Toolkit(AWT) container object is a component
* that can contain other AWT components. * that can contain other AWT components.
...@@ -1506,12 +1510,18 @@ public class Container extends Component { ...@@ -1506,12 +1510,18 @@ public class Container extends Component {
* Layout-related changes, such as bounds of the validate root descendants, * Layout-related changes, such as bounds of the validate root descendants,
* do not affect the layout of the validate root parent. This peculiarity * do not affect the layout of the validate root parent. This peculiarity
* enables the {@code invalidate()} method to stop invalidating the * enables the {@code invalidate()} method to stop invalidating the
* component hierarchy when the method encounters a validate root. * component hierarchy when the method encounters a validate root. However,
* to preserve backward compatibility this new optimized behavior is
* enabled only when the {@code java.awt.smartInvalidate} system property
* value is set to {@code true}.
* <p> * <p>
* If a component hierarchy contains validate roots, the {@code validate()} * If a component hierarchy contains validate roots and the new optimized
* method must be invoked on the validate root of a previously invalidated * {@code invalidate()} behavior is enabled, the {@code validate()} method
* component, rather than on the top-level container (such as a {@code * must be invoked on the validate root of a previously invalidated
* Frame} object) to restore the validity of the hierarchy later. * component to restore the validity of the hierarchy later. Otherwise,
* calling the {@code validate()} method on the top-level container (such
* as a {@code Frame} object) should be used to restore the validity of the
* component hierarchy.
* <p> * <p>
* The {@code Window} class and the {@code Applet} class are the validate * The {@code Window} class and the {@code Applet} class are the validate
* roots in AWT. Swing introduces more validate roots. * roots in AWT. Swing introduces more validate roots.
...@@ -1527,13 +1537,20 @@ public class Container extends Component { ...@@ -1527,13 +1537,20 @@ public class Container extends Component {
return false; return false;
} }
private static final boolean isJavaAwtSmartInvalidate;
static {
// Don't lazy-read because every app uses invalidate()
isJavaAwtSmartInvalidate = AccessController.doPrivileged(
new GetBooleanAction("java.awt.smartInvalidate"));
}
/** /**
* Invalidates the parent of the container unless the container * Invalidates the parent of the container unless the container
* is a validate root. * is a validate root.
*/ */
@Override @Override
void invalidateParent() { void invalidateParent() {
if (!isValidateRoot()) { if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {
super.invalidateParent(); super.invalidateParent();
} }
} }
...@@ -1572,9 +1589,8 @@ public class Container extends Component { ...@@ -1572,9 +1589,8 @@ public class Container extends Component {
* automatically. Note that the ancestors of the container may be * automatically. Note that the ancestors of the container may be
* invalidated also (see {@link Component#invalidate} for details.) * invalidated also (see {@link Component#invalidate} for details.)
* Therefore, to restore the validity of the hierarchy, the {@code * Therefore, to restore the validity of the hierarchy, the {@code
* validate()} method should be invoked on a validate root of an * validate()} method should be invoked on the top-most invalid
* invalidated component, or on the top-most container if the hierarchy * container of the hierarchy.
* does not contain validate roots.
* <p> * <p>
* Validating the container may be a quite time-consuming operation. For * Validating the container may be a quite time-consuming operation. For
* performance reasons a developer may postpone the validation of the * performance reasons a developer may postpone the validation of the
......
...@@ -466,10 +466,7 @@ public abstract class Toolkit { ...@@ -466,10 +466,7 @@ public abstract class Toolkit {
*/ */
protected void loadSystemColors(int[] systemColors) protected void loadSystemColors(int[] systemColors)
throws HeadlessException { throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
} }
/** /**
...@@ -504,10 +501,7 @@ public abstract class Toolkit { ...@@ -504,10 +501,7 @@ public abstract class Toolkit {
*/ */
public void setDynamicLayout(boolean dynamic) public void setDynamicLayout(boolean dynamic)
throws HeadlessException { throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
} }
/** /**
...@@ -531,9 +525,8 @@ public abstract class Toolkit { ...@@ -531,9 +525,8 @@ public abstract class Toolkit {
*/ */
protected boolean isDynamicLayoutSet() protected boolean isDynamicLayoutSet()
throws HeadlessException { throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
if (this != Toolkit.getDefaultToolkit()) { if (this != Toolkit.getDefaultToolkit()) {
return Toolkit.getDefaultToolkit().isDynamicLayoutSet(); return Toolkit.getDefaultToolkit().isDynamicLayoutSet();
} else { } else {
...@@ -569,9 +562,8 @@ public abstract class Toolkit { ...@@ -569,9 +562,8 @@ public abstract class Toolkit {
*/ */
public boolean isDynamicLayoutActive() public boolean isDynamicLayoutActive()
throws HeadlessException { throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
if (this != Toolkit.getDefaultToolkit()) { if (this != Toolkit.getDefaultToolkit()) {
return Toolkit.getDefaultToolkit().isDynamicLayoutActive(); return Toolkit.getDefaultToolkit().isDynamicLayoutActive();
} else { } else {
...@@ -615,9 +607,7 @@ public abstract class Toolkit { ...@@ -615,9 +607,7 @@ public abstract class Toolkit {
*/ */
public Insets getScreenInsets(GraphicsConfiguration gc) public Insets getScreenInsets(GraphicsConfiguration gc)
throws HeadlessException { throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
if (this != Toolkit.getDefaultToolkit()) { if (this != Toolkit.getDefaultToolkit()) {
return Toolkit.getDefaultToolkit().getScreenInsets(gc); return Toolkit.getDefaultToolkit().getScreenInsets(gc);
} else { } else {
...@@ -1200,10 +1190,7 @@ public abstract class Toolkit { ...@@ -1200,10 +1190,7 @@ public abstract class Toolkit {
* security manager's <code>checkPermission</code> method with a <code> * security manager's <code>checkPermission</code> method with a <code>
* RuntimePermission("queuePrintJob")</code> permission. * RuntimePermission("queuePrintJob")</code> permission.
* *
* @param frame the parent of the print dialog. May be null if and only * @param frame the parent of the print dialog. May not be null.
* if jobAttributes is not null and jobAttributes.getDialog()
* returns JobAttributes.DialogType.NONE or
* JobAttributes.DialogType.COMMON.
* @param jobtitle the title of the PrintJob. A null title is equivalent * @param jobtitle the title of the PrintJob. A null title is equivalent
* to "". * to "".
* @param jobAttributes a set of job attributes which will control the * @param jobAttributes a set of job attributes which will control the
...@@ -1359,9 +1346,8 @@ public abstract class Toolkit { ...@@ -1359,9 +1346,8 @@ public abstract class Toolkit {
* @since 1.4 * @since 1.4
*/ */
public Clipboard getSystemSelection() throws HeadlessException { public Clipboard getSystemSelection() throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
if (this != Toolkit.getDefaultToolkit()) { if (this != Toolkit.getDefaultToolkit()) {
return Toolkit.getDefaultToolkit().getSystemSelection(); return Toolkit.getDefaultToolkit().getSystemSelection();
} else { } else {
...@@ -1391,9 +1377,7 @@ public abstract class Toolkit { ...@@ -1391,9 +1377,7 @@ public abstract class Toolkit {
* @since JDK1.1 * @since JDK1.1
*/ */
public int getMenuShortcutKeyMask() throws HeadlessException { public int getMenuShortcutKeyMask() throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
return Event.CTRL_MASK; return Event.CTRL_MASK;
} }
...@@ -1418,7 +1402,10 @@ public abstract class Toolkit { ...@@ -1418,7 +1402,10 @@ public abstract class Toolkit {
* @since 1.3 * @since 1.3
*/ */
public boolean getLockingKeyState(int keyCode) public boolean getLockingKeyState(int keyCode)
throws UnsupportedOperationException { throws UnsupportedOperationException
{
GraphicsEnvironment.checkHeadless();
if (! (keyCode == KeyEvent.VK_CAPS_LOCK || keyCode == KeyEvent.VK_NUM_LOCK || if (! (keyCode == KeyEvent.VK_CAPS_LOCK || keyCode == KeyEvent.VK_NUM_LOCK ||
keyCode == KeyEvent.VK_SCROLL_LOCK || keyCode == KeyEvent.VK_KANA_LOCK)) { keyCode == KeyEvent.VK_SCROLL_LOCK || keyCode == KeyEvent.VK_KANA_LOCK)) {
throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState"); throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState");
...@@ -1449,7 +1436,10 @@ public abstract class Toolkit { ...@@ -1449,7 +1436,10 @@ public abstract class Toolkit {
* @since 1.3 * @since 1.3
*/ */
public void setLockingKeyState(int keyCode, boolean on) public void setLockingKeyState(int keyCode, boolean on)
throws UnsupportedOperationException { throws UnsupportedOperationException
{
GraphicsEnvironment.checkHeadless();
if (! (keyCode == KeyEvent.VK_CAPS_LOCK || keyCode == KeyEvent.VK_NUM_LOCK || if (! (keyCode == KeyEvent.VK_CAPS_LOCK || keyCode == KeyEvent.VK_NUM_LOCK ||
keyCode == KeyEvent.VK_SCROLL_LOCK || keyCode == KeyEvent.VK_KANA_LOCK)) { keyCode == KeyEvent.VK_SCROLL_LOCK || keyCode == KeyEvent.VK_KANA_LOCK)) {
throw new IllegalArgumentException("invalid key for Toolkit.setLockingKeyState"); throw new IllegalArgumentException("invalid key for Toolkit.setLockingKeyState");
...@@ -1523,9 +1513,8 @@ public abstract class Toolkit { ...@@ -1523,9 +1513,8 @@ public abstract class Toolkit {
*/ */
public Dimension getBestCursorSize(int preferredWidth, public Dimension getBestCursorSize(int preferredWidth,
int preferredHeight) throws HeadlessException { int preferredHeight) throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
// Override to implement custom cursor support. // Override to implement custom cursor support.
if (this != Toolkit.getDefaultToolkit()) { if (this != Toolkit.getDefaultToolkit()) {
return Toolkit.getDefaultToolkit(). return Toolkit.getDefaultToolkit().
...@@ -1553,9 +1542,8 @@ public abstract class Toolkit { ...@@ -1553,9 +1542,8 @@ public abstract class Toolkit {
* @since 1.2 * @since 1.2
*/ */
public int getMaximumCursorColors() throws HeadlessException { public int getMaximumCursorColors() throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
// Override to implement custom cursor support. // Override to implement custom cursor support.
if (this != Toolkit.getDefaultToolkit()) { if (this != Toolkit.getDefaultToolkit()) {
return Toolkit.getDefaultToolkit().getMaximumCursorColors(); return Toolkit.getDefaultToolkit().getMaximumCursorColors();
...@@ -1605,9 +1593,8 @@ public abstract class Toolkit { ...@@ -1605,9 +1593,8 @@ public abstract class Toolkit {
public boolean isFrameStateSupported(int state) public boolean isFrameStateSupported(int state)
throws HeadlessException throws HeadlessException
{ {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
if (this != Toolkit.getDefaultToolkit()) { if (this != Toolkit.getDefaultToolkit()) {
return Toolkit.getDefaultToolkit(). return Toolkit.getDefaultToolkit().
isFrameStateSupported(state); isFrameStateSupported(state);
...@@ -2614,9 +2601,8 @@ public abstract class Toolkit { ...@@ -2614,9 +2601,8 @@ public abstract class Toolkit {
* @since 1.7 * @since 1.7
*/ */
public boolean areExtraMouseButtonsEnabled() throws HeadlessException { public boolean areExtraMouseButtonsEnabled() throws HeadlessException {
if (GraphicsEnvironment.isHeadless()){ GraphicsEnvironment.checkHeadless();
throw new HeadlessException();
}
return Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled(); return Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled();
} }
} }
...@@ -777,7 +777,8 @@ public class Throwable implements Serializable { ...@@ -777,7 +777,8 @@ public class Throwable implements Serializable {
* @see java.lang.Throwable#printStackTrace() * @see java.lang.Throwable#printStackTrace()
*/ */
public synchronized Throwable fillInStackTrace() { public synchronized Throwable fillInStackTrace() {
if (stackTrace != null) { if (stackTrace != null ||
backtrace != null /* Out of protocol state */ ) {
fillInStackTrace(0); fillInStackTrace(0);
stackTrace = UNASSIGNED_STACK; stackTrace = UNASSIGNED_STACK;
} }
...@@ -817,7 +818,8 @@ public class Throwable implements Serializable { ...@@ -817,7 +818,8 @@ public class Throwable implements Serializable {
private synchronized StackTraceElement[] getOurStackTrace() { private synchronized StackTraceElement[] getOurStackTrace() {
// Initialize stack trace field with information from // Initialize stack trace field with information from
// backtrace if this is the first call to this method // backtrace if this is the first call to this method
if (stackTrace == UNASSIGNED_STACK) { if (stackTrace == UNASSIGNED_STACK ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
int depth = getStackTraceDepth(); int depth = getStackTraceDepth();
stackTrace = new StackTraceElement[depth]; stackTrace = new StackTraceElement[depth];
for (int i=0; i < depth; i++) for (int i=0; i < depth; i++)
...@@ -865,7 +867,8 @@ public class Throwable implements Serializable { ...@@ -865,7 +867,8 @@ public class Throwable implements Serializable {
} }
synchronized (this) { synchronized (this) {
if (this.stackTrace == null) // Immutable stack if (this.stackTrace == null && // Immutable stack
backtrace == null) // Test for out of protocol state
return; return;
this.stackTrace = defensiveCopy; this.stackTrace = defensiveCopy;
} }
......
...@@ -273,9 +273,9 @@ public class CallSite { ...@@ -273,9 +273,9 @@ public class CallSite {
Object binding; Object binding;
info = maybeReBox(info); info = maybeReBox(info);
if (info == null) { if (info == null) {
binding = bootstrapMethod.invokeGeneric(caller, name, type); binding = bootstrapMethod.invoke(caller, name, type);
} else if (!info.getClass().isArray()) { } else if (!info.getClass().isArray()) {
binding = bootstrapMethod.invokeGeneric(caller, name, type, info); binding = bootstrapMethod.invoke(caller, name, type, info);
} else { } else {
Object[] argv = (Object[]) info; Object[] argv = (Object[]) info;
maybeReBoxElements(argv); maybeReBoxElements(argv);
...@@ -283,10 +283,10 @@ public class CallSite { ...@@ -283,10 +283,10 @@ public class CallSite {
throw new BootstrapMethodError("too many bootstrap method arguments"); throw new BootstrapMethodError("too many bootstrap method arguments");
MethodType bsmType = bootstrapMethod.type(); MethodType bsmType = bootstrapMethod.type();
if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class) if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
binding = bootstrapMethod.invokeGeneric(caller, name, type, argv); binding = bootstrapMethod.invoke(caller, name, type, argv);
else else
binding = MethodHandles.spreadInvoker(bsmType, 3) binding = MethodHandles.spreadInvoker(bsmType, 3)
.invokeGeneric(bootstrapMethod, caller, name, type, argv); .invoke(bootstrapMethod, caller, name, type, argv);
} }
//System.out.println("BSM for "+name+type+" => "+binding); //System.out.println("BSM for "+name+type+" => "+binding);
if (binding instanceof CallSite) { if (binding instanceof CallSite) {
......
...@@ -61,6 +61,10 @@ class FilterGeneric { ...@@ -61,6 +61,10 @@ class FilterGeneric {
return ad; return ad;
} }
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
Adapter makeInstance(Kind kind, int pos, MethodHandle filter, MethodHandle target) { Adapter makeInstance(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
Adapter ad = getAdapter(kind, pos); Adapter ad = getAdapter(kind, pos);
return ad.makeInstance(ad.prototypeEntryPoint(), filter, target); return ad.makeInstance(ad.prototypeEntryPoint(), filter, target);
......
...@@ -67,6 +67,10 @@ class FilterOneArgument extends BoundMethodHandle { ...@@ -67,6 +67,10 @@ class FilterOneArgument extends BoundMethodHandle {
this.target = target; this.target = target;
} }
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
public static MethodHandle make(MethodHandle filter, MethodHandle target) { public static MethodHandle make(MethodHandle filter, MethodHandle target) {
if (filter == null) return target; if (filter == null) return target;
if (target == null) return filter; if (target == null) return filter;
......
...@@ -98,6 +98,10 @@ class FromGeneric { ...@@ -98,6 +98,10 @@ class FromGeneric {
this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0); this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
} }
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
/** /**
* The typed target will be called according to targetType. * The typed target will be called according to targetType.
* The adapter code will in fact see the raw result from internalType, * The adapter code will in fact see the raw result from internalType,
...@@ -112,10 +116,10 @@ class FromGeneric { ...@@ -112,10 +116,10 @@ class FromGeneric {
assert(iret == Object.class); assert(iret == Object.class);
return ValueConversions.identity(); return ValueConversions.identity();
} else if (wrap.primitiveType() == iret) { } else if (wrap.primitiveType() == iret) {
return ValueConversions.box(wrap, false); return ValueConversions.box(wrap);
} else { } else {
assert(tret == double.class ? iret == long.class : iret == int.class); assert(tret == double.class ? iret == long.class : iret == int.class);
return ValueConversions.boxRaw(wrap, false); return ValueConversions.boxRaw(wrap);
} }
} }
...@@ -135,7 +139,7 @@ class FromGeneric { ...@@ -135,7 +139,7 @@ class FromGeneric {
MethodType fixArgsType = internalType.changeReturnType(targetType.returnType()); MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
MethodHandle fixArgs = MethodHandleImpl.convertArguments( MethodHandle fixArgs = MethodHandleImpl.convertArguments(
invoker, Invokers.invokerType(fixArgsType), invoker, Invokers.invokerType(fixArgsType),
invoker.type(), null); invoker.type(), 0);
if (fixArgs == null) if (fixArgs == null)
throw new InternalError("bad fixArgs"); throw new InternalError("bad fixArgs");
// reinterpret the calling sequence as raw: // reinterpret the calling sequence as raw:
...@@ -160,7 +164,6 @@ class FromGeneric { ...@@ -160,7 +164,6 @@ class FromGeneric {
/** Build an adapter of the given generic type, which invokes typedTarget /** Build an adapter of the given generic type, which invokes typedTarget
* on the incoming arguments, after unboxing as necessary. * on the incoming arguments, after unboxing as necessary.
* The return value is boxed if necessary. * The return value is boxed if necessary.
* @param genericType the required type of the result
* @param typedTarget the target * @param typedTarget the target
* @return an adapter method handle * @return an adapter method handle
*/ */
...@@ -231,7 +234,7 @@ class FromGeneric { ...@@ -231,7 +234,7 @@ class FromGeneric {
} }
static Adapter buildAdapterFromBytecodes(MethodType internalType) { static Adapter buildAdapterFromBytecodes(MethodType internalType) {
throw new UnsupportedOperationException("NYI"); throw new UnsupportedOperationException("NYI "+internalType);
} }
/** /**
......
...@@ -29,12 +29,12 @@ import sun.invoke.util.*; ...@@ -29,12 +29,12 @@ import sun.invoke.util.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/** /**
* Adapters which manage MethodHandle.invokeGeneric calls. * Adapters which manage inexact MethodHandle.invoke calls.
* The JVM calls one of these when the exact type match fails. * The JVM calls one of these when the exact type match fails.
* @author jrose * @author jrose
*/ */
class InvokeGeneric { class InvokeGeneric {
// erased type for the call, which originates from an invokeGeneric site // erased type for the call, which originates from an inexact invoke site
private final MethodType erasedCallerType; private final MethodType erasedCallerType;
// an invoker of type (MT, MH; A...) -> R // an invoker of type (MT, MH; A...) -> R
private final MethodHandle initialInvoker; private final MethodHandle initialInvoker;
...@@ -56,7 +56,7 @@ class InvokeGeneric { ...@@ -56,7 +56,7 @@ class InvokeGeneric {
} }
/** Return the adapter information for this type's erasure. */ /** Return the adapter information for this type's erasure. */
/*non-public*/ static MethodHandle genericInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException { /*non-public*/ static MethodHandle generalInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException {
InvokeGeneric gen = new InvokeGeneric(erasedCallerType); InvokeGeneric gen = new InvokeGeneric(erasedCallerType);
return gen.initialInvoker; return gen.initialInvoker;
} }
......
...@@ -43,10 +43,10 @@ class Invokers { ...@@ -43,10 +43,10 @@ class Invokers {
private /*lazy*/ MethodHandle erasedInvoker; private /*lazy*/ MethodHandle erasedInvoker;
/*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric
// generic (untyped) invoker for the outgoing call // general invoker for the outgoing call
private /*lazy*/ MethodHandle genericInvoker; private /*lazy*/ MethodHandle generalInvoker;
// generic (untyped) invoker for the outgoing call; accepts a single Object[] // general invoker for the outgoing call; accepts a single Object[]
private final /*lazy*/ MethodHandle[] spreadInvokers; private final /*lazy*/ MethodHandle[] spreadInvokers;
// invoker for an unbound callsite // invoker for an unbound callsite
...@@ -77,13 +77,13 @@ class Invokers { ...@@ -77,13 +77,13 @@ class Invokers {
return invoker; return invoker;
} }
/*non-public*/ MethodHandle genericInvoker() { /*non-public*/ MethodHandle generalInvoker() {
MethodHandle invoker1 = exactInvoker(); MethodHandle invoker1 = exactInvoker();
MethodHandle invoker = genericInvoker; MethodHandle invoker = generalInvoker;
if (invoker != null) return invoker; if (invoker != null) return invoker;
MethodType genericType = targetType.generic(); MethodType generalType = targetType.generic();
invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType)); invoker = invoker1.asType(invokerType(generalType));
genericInvoker = invoker; generalInvoker = invoker;
return invoker; return invoker;
} }
...@@ -93,9 +93,9 @@ class Invokers { ...@@ -93,9 +93,9 @@ class Invokers {
if (invoker != null) return invoker; if (invoker != null) return invoker;
MethodType erasedType = targetType.erase(); MethodType erasedType = targetType.erase();
if (erasedType == targetType.generic()) if (erasedType == targetType.generic())
invoker = genericInvoker(); invoker = generalInvoker();
else else
invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType)); invoker = invoker1.asType(invokerType(erasedType));
erasedInvoker = invoker; erasedInvoker = invoker;
return invoker; return invoker;
} }
...@@ -103,7 +103,7 @@ class Invokers { ...@@ -103,7 +103,7 @@ class Invokers {
/*non-public*/ MethodHandle spreadInvoker(int objectArgCount) { /*non-public*/ MethodHandle spreadInvoker(int objectArgCount) {
MethodHandle vaInvoker = spreadInvokers[objectArgCount]; MethodHandle vaInvoker = spreadInvokers[objectArgCount];
if (vaInvoker != null) return vaInvoker; if (vaInvoker != null) return vaInvoker;
MethodHandle gInvoker = genericInvoker(); MethodHandle gInvoker = generalInvoker();
vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount); vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount);
spreadInvokers[objectArgCount] = vaInvoker; spreadInvokers[objectArgCount] = vaInvoker;
return vaInvoker; return vaInvoker;
......
...@@ -525,7 +525,7 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -525,7 +525,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
/** A factory type for resolving member names with the help of the VM. /** A factory type for resolving member names with the help of the VM.
* TBD: Define access-safe public constructors for this factory. * TBD: Define access-safe public constructors for this factory.
*/ */
public static class Factory { /*non-public*/ static class Factory {
private Factory() { } // singleton pattern private Factory() { } // singleton pattern
static Factory INSTANCE = new Factory(); static Factory INSTANCE = new Factory();
......
...@@ -115,6 +115,8 @@ class MethodHandleNatives { ...@@ -115,6 +115,8 @@ class MethodHandleNatives {
/** Which conv-ops are implemented by the JVM? */ /** Which conv-ops are implemented by the JVM? */
static final int CONV_OP_IMPLEMENTED_MASK; static final int CONV_OP_IMPLEMENTED_MASK;
/** Derived mode flag. Only false on some old JVM implementations. */
static final boolean HAVE_RICOCHET_FRAMES;
private static native void registerNatives(); private static native void registerNatives();
static { static {
...@@ -141,6 +143,7 @@ class MethodHandleNatives { ...@@ -141,6 +143,7 @@ class MethodHandleNatives {
if (CONV_OP_IMPLEMENTED_MASK_ == 0) if (CONV_OP_IMPLEMENTED_MASK_ == 0)
CONV_OP_IMPLEMENTED_MASK_ = DEFAULT_CONV_OP_IMPLEMENTED_MASK; CONV_OP_IMPLEMENTED_MASK_ = DEFAULT_CONV_OP_IMPLEMENTED_MASK;
CONV_OP_IMPLEMENTED_MASK = CONV_OP_IMPLEMENTED_MASK_; CONV_OP_IMPLEMENTED_MASK = CONV_OP_IMPLEMENTED_MASK_;
HAVE_RICOCHET_FRAMES = (CONV_OP_IMPLEMENTED_MASK & (1<<OP_COLLECT_ARGS)) != 0;
} }
// All compile-time constants go here. // All compile-time constants go here.
...@@ -186,25 +189,26 @@ class MethodHandleNatives { ...@@ -186,25 +189,26 @@ class MethodHandleNatives {
*/ */
static final int static final int
OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
OP_RETYPE_RAW = 0x1, // no argument changes; straight retype OP_RETYPE_RAW = 0x1, // straight retype, trusted (void->int, Object->T)
OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI) OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper
OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg) OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg) OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS) OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
OP_DROP_ARGS = 0x9, // remove one or more argument slots OP_DROP_ARGS = 0x9, // remove one or more argument slots
OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI) OP_COLLECT_ARGS = 0xA, // combine arguments using an auxiliary function
OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size) OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
OP_FLYBY = 0xC, // operate first on reified argument list (NYI) OP_FOLD_ARGS = 0xC, // combine but do not remove arguments; prepend result
OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI) //OP_UNUSED_13 = 0xD, // unused code, perhaps for reified argument lists
CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration
/** Shift and mask values for decoding the AMH.conversion field. /** Shift and mask values for decoding the AMH.conversion field.
* These numbers are shared with the JVM for creating AMHs. * These numbers are shared with the JVM for creating AMHs.
*/ */
static final int static final int
CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
CONV_TYPE_MASK = 0x0F, // fits T_ADDRESS and below
CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
...@@ -244,8 +248,9 @@ class MethodHandleNatives { ...@@ -244,8 +248,9 @@ class MethodHandleNatives {
T_LONG = 11, T_LONG = 11,
T_OBJECT = 12, T_OBJECT = 12,
//T_ARRAY = 13 //T_ARRAY = 13
T_VOID = 14; T_VOID = 14,
//T_ADDRESS = 15 //T_ADDRESS = 15
T_ILLEGAL = 99;
/** /**
* Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries. * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
...@@ -273,16 +278,29 @@ class MethodHandleNatives { ...@@ -273,16 +278,29 @@ class MethodHandleNatives {
try { try {
Field con = Constants.class.getDeclaredField(name); Field con = Constants.class.getDeclaredField(name);
int jval = con.getInt(null); int jval = con.getInt(null);
if (jval != vmval) if (jval == vmval) continue;
throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval); String err = (name+": JVM has "+vmval+" while Java has "+jval);
if (name.equals("CONV_OP_LIMIT")) {
System.err.println("warning: "+err);
continue;
}
throw new InternalError(err);
} catch (Exception ex) { } catch (Exception ex) {
if (ex instanceof NoSuchFieldException) {
String err = (name+": JVM has "+vmval+" which Java does not define");
// ignore exotic ops the JVM cares about; we just wont issue them
if (name.startsWith("OP_") || name.startsWith("GC_")) {
System.err.println("warning: "+err);
continue;
}
}
throw new InternalError(name+": access failed, got "+ex); throw new InternalError(name+": access failed, got "+ex);
} }
} }
return true; return true;
} }
static { static {
verifyConstants(); assert(verifyConstants());
} }
// Up-calls from the JVM. // Up-calls from the JVM.
...@@ -313,7 +331,7 @@ class MethodHandleNatives { ...@@ -313,7 +331,7 @@ class MethodHandleNatives {
} }
/** /**
* The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning. * The JVM wants to use a MethodType with inexact invoke. Give the runtime fair warning.
*/ */
static void notifyGenericMethodType(MethodType type) { static void notifyGenericMethodType(MethodType type) {
type.form().notifyGenericMethodType(); type.form().notifyGenericMethodType();
...@@ -323,15 +341,39 @@ class MethodHandleNatives { ...@@ -323,15 +341,39 @@ class MethodHandleNatives {
* The JVM wants to raise an exception. Here's the path. * The JVM wants to raise an exception. Here's the path.
*/ */
static void raiseException(int code, Object actual, Object required) { static void raiseException(int code, Object actual, Object required) {
String message; String message = null;
switch (code) {
case 190: // arraylength
try {
String reqLength = "";
if (required instanceof AdapterMethodHandle) {
int conv = ((AdapterMethodHandle)required).getConversion();
int spChange = AdapterMethodHandle.extractStackMove(conv);
reqLength = " of length "+(spChange+1);
}
int actualLength = actual == null ? 0 : java.lang.reflect.Array.getLength(actual);
message = "required array"+reqLength+", but encountered wrong length "+actualLength;
break;
} catch (IllegalArgumentException ex) {
}
required = Object[].class; // should have been an array
code = 192; // checkcast
break;
}
// disregard the identity of the actual object, if it is not a class: // disregard the identity of the actual object, if it is not a class:
if (message == null) {
if (!(actual instanceof Class) && !(actual instanceof MethodType)) if (!(actual instanceof Class) && !(actual instanceof MethodType))
actual = actual.getClass(); actual = actual.getClass();
if (actual != null) if (actual != null)
message = "required "+required+" but encountered "+actual; message = "required "+required+" but encountered "+actual;
else else
message = "required "+required; message = "required "+required;
}
switch (code) { switch (code) {
case 190: // arraylength
throw new ArrayIndexOutOfBoundsException(message);
case 50: //_aaload
throw new ClassCastException(message);
case 192: // checkcast case 192: // checkcast
throw new ClassCastException(message); throw new ClassCastException(message);
default: default:
...@@ -365,4 +407,13 @@ class MethodHandleNatives { ...@@ -365,4 +407,13 @@ class MethodHandleNatives {
throw err; throw err;
} }
} }
/**
* This assertion marks code which was written before ricochet frames were implemented.
* Such code will go away when the ports catch up.
*/
static boolean workaroundWithoutRicochetFrames() {
assert(!HAVE_RICOCHET_FRAMES) : "this code should not be executed if `-XX:+UseRicochetFrames is enabled";
return true;
}
} }
...@@ -63,7 +63,16 @@ package java.lang.invoke; ...@@ -63,7 +63,16 @@ package java.lang.invoke;
} }
static void checkSpreadArgument(Object av, int n) { static void checkSpreadArgument(Object av, int n) {
if (av == null ? n != 0 : ((Object[])av).length != n) if (av == null) {
if (n == 0) return;
} else if (av instanceof Object[]) {
int len = ((Object[])av).length;
if (len == n) return;
} else {
int len = java.lang.reflect.Array.getLength(av);
if (len == n) return;
}
// fall through to error:
throw newIllegalArgumentException("Array is not of length "+n); throw newIllegalArgumentException("Array is not of length "+n);
} }
...@@ -80,6 +89,9 @@ package java.lang.invoke; ...@@ -80,6 +89,9 @@ package java.lang.invoke;
/*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) { /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) {
return new IllegalArgumentException(message(message, obj)); return new IllegalArgumentException(message(message, obj));
} }
/*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj, Object obj2) {
return new IllegalArgumentException(message(message, obj, obj2));
}
/*non-public*/ static Error uncaughtException(Exception ex) { /*non-public*/ static Error uncaughtException(Exception ex) {
Error err = new InternalError("uncaught exception"); Error err = new InternalError("uncaught exception");
err.initCause(ex); err.initCause(ex);
...@@ -89,4 +101,8 @@ package java.lang.invoke; ...@@ -89,4 +101,8 @@ package java.lang.invoke;
if (obj != null) message = message + ": " + obj; if (obj != null) message = message + ": " + obj;
return message; return message;
} }
private static String message(String message, Object obj, Object obj2) {
if (obj != null || obj2 != null) message = message + ": " + obj + ", " + obj2;
return message;
}
} }
...@@ -190,7 +190,7 @@ public class MethodHandles { ...@@ -190,7 +190,7 @@ public class MethodHandles {
* is not symbolically accessible from the lookup class's loader, * is not symbolically accessible from the lookup class's loader,
* the lookup can still succeed. * the lookup can still succeed.
* For example, lookups for {@code MethodHandle.invokeExact} and * For example, lookups for {@code MethodHandle.invokeExact} and
* {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type. * {@code MethodHandle.invoke} will always succeed, regardless of requested type.
* <li>If there is a security manager installed, it can forbid the lookup * <li>If there is a security manager installed, it can forbid the lookup
* on various grounds (<a href="#secmgr">see below</a>). * on various grounds (<a href="#secmgr">see below</a>).
* By contrast, the {@code ldc} instruction is not subject to * By contrast, the {@code ldc} instruction is not subject to
...@@ -590,10 +590,10 @@ public class MethodHandles { ...@@ -590,10 +590,10 @@ public class MethodHandles {
* Because of the general equivalence between {@code invokevirtual} * Because of the general equivalence between {@code invokevirtual}
* instructions and method handles produced by {@code findVirtual}, * instructions and method handles produced by {@code findVirtual},
* if the class is {@code MethodHandle} and the name string is * if the class is {@code MethodHandle} and the name string is
* {@code invokeExact} or {@code invokeGeneric}, the resulting * {@code invokeExact} or {@code invoke}, the resulting
* method handle is equivalent to one produced by * method handle is equivalent to one produced by
* {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
* {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker} * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
* with the same {@code type} argument. * with the same {@code type} argument.
* *
* @param refc the class or interface from which the method is accessed * @param refc the class or interface from which the method is accessed
...@@ -1080,7 +1080,7 @@ return mh1; ...@@ -1080,7 +1080,7 @@ return mh1;
MethodType rawType = mh.type(); MethodType rawType = mh.type();
if (rawType.parameterType(0) == caller) return mh; if (rawType.parameterType(0) == caller) return mh;
MethodType narrowType = rawType.changeParameterType(0, caller); MethodType narrowType = rawType.changeParameterType(0, caller);
MethodHandle narrowMH = MethodHandleImpl.convertArguments(mh, narrowType, rawType, null); MethodHandle narrowMH = MethodHandleImpl.convertArguments(mh, narrowType, rawType, 0);
return fixVarargs(narrowMH, mh); return fixVarargs(narrowMH, mh);
} }
...@@ -1148,7 +1148,7 @@ return mh1; ...@@ -1148,7 +1148,7 @@ return mh1;
* <li>an {@code Object[]} array containing more arguments * <li>an {@code Object[]} array containing more arguments
* </ul> * </ul>
* <p> * <p>
* The invoker will behave like a call to {@link MethodHandle#invokeGeneric invokeGeneric} with * The invoker will behave like a call to {@link MethodHandle#invoke invoke} with
* the indicated {@code type}. * the indicated {@code type}.
* That is, if the target is exactly of the given {@code type}, it will behave * That is, if the target is exactly of the given {@code type}, it will behave
* like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType} * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
...@@ -1166,7 +1166,7 @@ return mh1; ...@@ -1166,7 +1166,7 @@ return mh1;
* <p> * <p>
* This method is equivalent to the following code (though it may be more efficient): * This method is equivalent to the following code (though it may be more efficient):
* <p><blockquote><pre> * <p><blockquote><pre>
MethodHandle invoker = MethodHandles.genericInvoker(type); MethodHandle invoker = MethodHandles.invoker(type);
int spreadArgCount = type.parameterCount - objectArgCount; int spreadArgCount = type.parameterCount - objectArgCount;
invoker = invoker.asSpreader(Object[].class, spreadArgCount); invoker = invoker.asSpreader(Object[].class, spreadArgCount);
return invoker; return invoker;
...@@ -1186,7 +1186,7 @@ return invoker; ...@@ -1186,7 +1186,7 @@ return invoker;
/** /**
* Produces a special <em>invoker method handle</em> which can be used to * Produces a special <em>invoker method handle</em> which can be used to
* invoke any method handle of the given type, as if by {@code invokeExact}. * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}.
* The resulting invoker will have a type which is * The resulting invoker will have a type which is
* exactly equal to the desired type, except that it will accept * exactly equal to the desired type, except that it will accept
* an additional leading argument of type {@code MethodHandle}. * an additional leading argument of type {@code MethodHandle}.
...@@ -1203,7 +1203,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1203,7 +1203,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* For example, to emulate an {@code invokeExact} call to a variable method * For example, to emulate an {@code invokeExact} call to a variable method
* handle {@code M}, extract its type {@code T}, * handle {@code M}, extract its type {@code T},
* look up the invoker method {@code X} for {@code T}, * look up the invoker method {@code X} for {@code T},
* and call the invoker method, as {@code X.invokeGeneric(T, A...)}. * and call the invoker method, as {@code X.invoke(T, A...)}.
* (It would not work to call {@code X.invokeExact}, since the type {@code T} * (It would not work to call {@code X.invokeExact}, since the type {@code T}
* is unknown.) * is unknown.)
* If spreading, collecting, or other argument transformations are required, * If spreading, collecting, or other argument transformations are required,
...@@ -1212,7 +1212,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1212,7 +1212,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
* <p> * <p>
* <em>(Note: The invoker method is not available via the Core Reflection API. * <em>(Note: The invoker method is not available via the Core Reflection API.
* An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke} * An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke}
* on the declared {@code invokeExact} or {@code invokeGeneric} method will raise an * on the declared {@code invokeExact} or {@code invoke} method will raise an
* {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em> * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
* <p> * <p>
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
...@@ -1226,20 +1226,20 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type) ...@@ -1226,20 +1226,20 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
/** /**
* Produces a special <em>invoker method handle</em> which can be used to * Produces a special <em>invoker method handle</em> which can be used to
* invoke any method handle of the given type, as if by {@code invokeGeneric}. * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}.
* The resulting invoker will have a type which is * The resulting invoker will have a type which is
* exactly equal to the desired type, except that it will accept * exactly equal to the desired type, except that it will accept
* an additional leading argument of type {@code MethodHandle}. * an additional leading argument of type {@code MethodHandle}.
* <p> * <p>
* Before invoking its target, the invoker will apply reference casts as * Before invoking its target, the invoker will apply reference casts as
* necessary and unbox and widen primitive arguments, as if by {@link #convertArguments convertArguments}. * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}.
* The return value of the invoker will be an {@code Object} reference, * Similarly, the return value will be converted as necessary.
* boxing a primitive value if the original type returns a primitive, * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle},
* and always null if the original type returns void. * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}.
* <p> * <p>
* This method is equivalent to the following code (though it may be more efficient): * This method is equivalent to the following code (though it may be more efficient):
* <p><blockquote><pre> * <p><blockquote><pre>
publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type) publicLookup().findVirtual(MethodHandle.class, "invoke", type)
* </pre></blockquote> * </pre></blockquote>
* <p> * <p>
* This method throws no reflective or security exceptions. * This method throws no reflective or security exceptions.
...@@ -1247,8 +1247,17 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type) ...@@ -1247,8 +1247,17 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
* @return a method handle suitable for invoking any method handle convertible to the given type * @return a method handle suitable for invoking any method handle convertible to the given type
*/ */
static public static public
MethodHandle invoker(MethodType type) {
return type.invokers().generalInvoker();
}
/**
* <em>Temporary alias</em> for {@link #invoker}, for backward compatibility with some versions of JSR 292.
* @deprecated Will be removed for JSR 292 Proposed Final Draft.
*/
public static
MethodHandle genericInvoker(MethodType type) { MethodHandle genericInvoker(MethodType type) {
return type.invokers().genericInvoker(); return invoker(type);
} }
/** /**
...@@ -1368,18 +1377,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type) ...@@ -1368,18 +1377,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
*/ */
public static public static
MethodHandle convertArguments(MethodHandle target, MethodType newType) { MethodHandle convertArguments(MethodHandle target, MethodType newType) {
MethodType oldType = target.type(); return MethodHandleImpl.convertArguments(target, newType, 1);
if (oldType.equals(newType))
return target;
MethodHandle res = null;
try {
res = MethodHandleImpl.convertArguments(target,
newType, oldType, null);
} catch (IllegalArgumentException ex) {
}
if (res == null)
throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
return res;
} }
/** /**
...@@ -1422,7 +1420,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type) ...@@ -1422,7 +1420,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
*/ */
public static public static
MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) { MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
return convertArguments(target, newType); // FIXME! return MethodHandleImpl.convertArguments(target, newType, 2);
} }
/* /*
...@@ -1517,23 +1515,32 @@ assert((int)twice.invokeExact(21) == 42); ...@@ -1517,23 +1515,32 @@ assert((int)twice.invokeExact(21) == 42);
MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) { MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
MethodType oldType = target.type(); MethodType oldType = target.type();
checkReorder(reorder, newType, oldType); checkReorder(reorder, newType, oldType);
return MethodHandleImpl.convertArguments(target, return MethodHandleImpl.permuteArguments(target,
newType, oldType, newType, oldType,
reorder); reorder);
} }
private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) { private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
if (newType.returnType() != oldType.returnType())
throw newIllegalArgumentException("return types do not match",
oldType, newType);
if (reorder.length == oldType.parameterCount()) { if (reorder.length == oldType.parameterCount()) {
int limit = newType.parameterCount(); int limit = newType.parameterCount();
boolean bad = false; boolean bad = false;
for (int i : reorder) { for (int j = 0; j < reorder.length; j++) {
int i = reorder[j];
if (i < 0 || i >= limit) { if (i < 0 || i >= limit) {
bad = true; break; bad = true; break;
} }
Class<?> src = newType.parameterType(i);
Class<?> dst = oldType.parameterType(j);
if (src != dst)
throw newIllegalArgumentException("parameter types do not match after reorder",
oldType, newType);
} }
if (!bad) return; if (!bad) return;
} }
throw newIllegalArgumentException("bad reorder array"); throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
} }
/** /**
...@@ -1622,7 +1629,7 @@ assert((int)twice.invokeExact(21) == 42); ...@@ -1622,7 +1629,7 @@ assert((int)twice.invokeExact(21) == 42);
if (type == void.class) if (type == void.class)
throw newIllegalArgumentException("void type"); throw newIllegalArgumentException("void type");
Wrapper w = Wrapper.forPrimitiveType(type); Wrapper w = Wrapper.forPrimitiveType(type);
return identity(type).bindTo(w.convert(value, type)); return insertArguments(identity(type), 0, w.convert(value, type));
} else { } else {
return identity(type).bindTo(type.cast(value)); return identity(type).bindTo(type.cast(value));
} }
...@@ -1857,7 +1864,8 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY ...@@ -1857,7 +1864,8 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) { MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
MethodType targetType = target.type(); MethodType targetType = target.type();
MethodHandle adapter = target; MethodHandle adapter = target;
MethodType adapterType = targetType; MethodType adapterType = null;
assert((adapterType = targetType) != null);
int maxPos = targetType.parameterCount(); int maxPos = targetType.parameterCount();
if (pos + filters.length > maxPos) if (pos + filters.length > maxPos)
throw newIllegalArgumentException("too many filters"); throw newIllegalArgumentException("too many filters");
...@@ -1865,17 +1873,21 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY ...@@ -1865,17 +1873,21 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
for (MethodHandle filter : filters) { for (MethodHandle filter : filters) {
curPos += 1; curPos += 1;
if (filter == null) continue; // ignore null elements of filters if (filter == null) continue; // ignore null elements of filters
adapter = filterArgument(adapter, curPos, filter);
assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null);
}
assert(adapterType.equals(adapter.type()));
return adapter;
}
/*non-public*/ static
MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
MethodType targetType = target.type();
MethodType filterType = filter.type(); MethodType filterType = filter.type();
if (filterType.parameterCount() != 1 if (filterType.parameterCount() != 1
|| filterType.returnType() != targetType.parameterType(curPos)) || filterType.returnType() != targetType.parameterType(pos))
throw newIllegalArgumentException("target and filter types do not match"); throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0)); return MethodHandleImpl.filterArgument(target, pos, filter);
adapter = MethodHandleImpl.filterArgument(adapter, curPos, filter);
}
MethodType midType = adapter.type();
if (midType != adapterType)
adapter = MethodHandleImpl.convertArguments(adapter, adapterType, midType, null);
return adapter;
} }
/** /**
...@@ -1913,14 +1925,26 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -1913,14 +1925,26 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) { MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
MethodType targetType = target.type(); MethodType targetType = target.type();
MethodType filterType = filter.type(); MethodType filterType = filter.type();
if (filterType.parameterCount() != 1 Class<?> rtype = targetType.returnType();
|| filterType.parameterType(0) != targetType.returnType()) int filterValues = filterType.parameterCount();
throw newIllegalArgumentException("target and filter types do not match"); if (filterValues == 0
? (rtype != void.class)
: (rtype != filterType.parameterType(0)))
throw newIllegalArgumentException("target and filter types do not match", target, filter);
// result = fold( lambda(retval, arg...) { filter(retval) }, // result = fold( lambda(retval, arg...) { filter(retval) },
// lambda( arg...) { target(arg...) } ) // lambda( arg...) { target(arg...) } )
MethodType newType = targetType.changeReturnType(filterType.returnType());
MethodHandle result = null;
if (AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false)) {
result = AdapterMethodHandle.makeCollectArguments(filter, target, 0, false);
if (result != null) return result;
}
// FIXME: Too many nodes here. // FIXME: Too many nodes here.
MethodHandle returner = dropArguments(filter, 1, targetType.parameterList()); assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
return foldArguments(returner, target); MethodHandle returner = dropArguments(filter, filterValues, targetType.parameterList());
result = foldArguments(returner, target);
assert(result.type().equals(newType));
return result;
} }
/** /**
...@@ -1972,16 +1996,23 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -1972,16 +1996,23 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) { MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
MethodType targetType = target.type(); MethodType targetType = target.type();
MethodType combinerType = combiner.type(); MethodType combinerType = combiner.type();
int foldPos = 0; // always at the head, at present
int foldArgs = combinerType.parameterCount(); int foldArgs = combinerType.parameterCount();
boolean ok = (targetType.parameterCount() >= 1 + foldArgs); int foldVals = combinerType.returnType() == void.class ? 0 : 1;
if (ok && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1))) int afterInsertPos = foldPos + foldVals;
boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
if (ok && !(combinerType.parameterList()
.equals(targetType.parameterList().subList(afterInsertPos,
afterInsertPos + foldArgs))))
ok = false; ok = false;
if (ok && !combinerType.returnType().equals(targetType.parameterType(0))) if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0)))
ok = false; ok = false;
if (!ok) if (!ok)
throw misMatchedTypes("target and combiner types", targetType, combinerType); throw misMatchedTypes("target and combiner types", targetType, combinerType);
MethodType newType = targetType.dropParameterTypes(0, 1); MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos);
return MethodHandleImpl.foldArguments(target, newType, combiner); MethodHandle res = MethodHandleImpl.foldArguments(target, newType, foldPos, combiner);
if (res == null) throw newIllegalArgumentException("cannot fold from "+newType+" to " +targetType);
return res;
} }
/** /**
...@@ -2142,7 +2173,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -2142,7 +2173,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
* the given {@code target} on the incoming arguments, * the given {@code target} on the incoming arguments,
* and returning or throwing whatever the {@code target} * and returning or throwing whatever the {@code target}
* returns or throws. The invocation will be as if by * returns or throws. The invocation will be as if by
* {@code target.invokeGeneric}. * {@code target.invoke}.
* The target's type will be checked before the * The target's type will be checked before the
* instance is created, as if by a call to {@code asType}, * instance is created, as if by a call to {@code asType},
* which may result in a {@code WrongMethodTypeException}. * which may result in a {@code WrongMethodTypeException}.
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.lang.invoke; package java.lang.invoke;
import sun.invoke.util.Wrapper;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
...@@ -39,7 +40,7 @@ import static java.lang.invoke.MethodHandleStatics.*; ...@@ -39,7 +40,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* matched between a method handle and all its callers, * matched between a method handle and all its callers,
* and the JVM's operations enforce this matching at, specifically * and the JVM's operations enforce this matching at, specifically
* during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact} * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
* and {@link MethodHandle#invokeGeneric MethodHandle.invokeGeneric}, and during execution * and {@link MethodHandle#invoke MethodHandle.invoke}, and during execution
* of {@code invokedynamic} instructions. * of {@code invokedynamic} instructions.
* <p> * <p>
* The structure is a return type accompanied by any number of parameter types. * The structure is a return type accompanied by any number of parameter types.
...@@ -262,18 +263,18 @@ class MethodType implements java.io.Serializable { ...@@ -262,18 +263,18 @@ class MethodType implements java.io.Serializable {
* Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array. * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* All parameters and the return type will be {@code Object}, * All parameters and the return type will be {@code Object},
* except the final varargs parameter if any, which will be {@code Object[]}. * except the final array parameter if any, which will be {@code Object[]}.
* @param objectArgCount number of parameters (excluding the varargs parameter if any) * @param objectArgCount number of parameters (excluding the final array parameter if any)
* @param varargs whether there will be a varargs parameter, of type {@code Object[]} * @param finalArray whether there will be a trailing array parameter, of type {@code Object[]}
* @return a totally generic method type, given only its count of parameters and varargs * @return a generally applicable method type, for all calls of the given fixed argument count and a collected array of further arguments
* @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 (or 254, if {@code finalArray})
* @see #genericMethodType(int) * @see #genericMethodType(int)
*/ */
public static public static
MethodType genericMethodType(int objectArgCount, boolean varargs) { MethodType genericMethodType(int objectArgCount, boolean finalArray) {
MethodType mt; MethodType mt;
checkSlotCount(objectArgCount); checkSlotCount(objectArgCount);
int ivarargs = (!varargs ? 0 : 1); int ivarargs = (!finalArray ? 0 : 1);
int ootIndex = objectArgCount*2 + ivarargs; int ootIndex = objectArgCount*2 + ivarargs;
if (ootIndex < objectOnlyTypes.length) { if (ootIndex < objectOnlyTypes.length) {
mt = objectOnlyTypes[ootIndex]; mt = objectOnlyTypes[ootIndex];
...@@ -294,7 +295,7 @@ class MethodType implements java.io.Serializable { ...@@ -294,7 +295,7 @@ class MethodType implements java.io.Serializable {
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* All parameters and the return type will be Object. * All parameters and the return type will be Object.
* @param objectArgCount number of parameters * @param objectArgCount number of parameters
* @return a totally generic method type, given only its count of parameters * @return a generally applicable method type, for all calls of the given argument count
* @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
* @see #genericMethodType(int, boolean) * @see #genericMethodType(int, boolean)
*/ */
...@@ -626,6 +627,30 @@ class MethodType implements java.io.Serializable { ...@@ -626,6 +627,30 @@ class MethodType implements java.io.Serializable {
return sb.toString(); return sb.toString();
} }
/*non-public*/
boolean isConvertibleTo(MethodType newType) {
if (!canConvert(returnType(), newType.returnType()))
return false;
int argc = parameterCount();
if (argc != newType.parameterCount())
return false;
for (int i = 0; i < argc; i++) {
if (!canConvert(newType.parameterType(i), parameterType(i)))
return false;
}
return true;
}
private static boolean canConvert(Class<?> src, Class<?> dst) {
if (src == dst || dst == void.class) return true;
if (src.isPrimitive() && dst.isPrimitive()) {
if (!Wrapper.forPrimitiveType(dst)
.isConvertibleFrom(Wrapper.forPrimitiveType(src)))
return false;
}
return true;
}
/// Queries which have to do with the bytecode architecture /// Queries which have to do with the bytecode architecture
/** Reports the number of JVM stack slots required to invoke a method /** Reports the number of JVM stack slots required to invoke a method
......
...@@ -46,6 +46,7 @@ class MethodTypeForm { ...@@ -46,6 +46,7 @@ class MethodTypeForm {
final long argCounts; // packed slot & value counts final long argCounts; // packed slot & value counts
final long primCounts; // packed prim & double counts final long primCounts; // packed prim & double counts
final int vmslots; // total number of parameter slots final int vmslots; // total number of parameter slots
private Object vmlayout; // vm-specific information for calls
final MethodType erasedType; // the canonical erasure final MethodType erasedType; // the canonical erasure
/*lazy*/ MethodType primsAsBoxes; // replace prims by wrappers /*lazy*/ MethodType primsAsBoxes; // replace prims by wrappers
...@@ -59,7 +60,7 @@ class MethodTypeForm { ...@@ -59,7 +60,7 @@ class MethodTypeForm {
/*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with /*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with
/*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many /*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
/*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
/*lazy*/ MethodHandle genericInvoker; // hook for invokeGeneric /*lazy*/ MethodHandle genericInvoker; // hook for inexact invoke
public MethodType erasedType() { public MethodType erasedType() {
return erasedType; return erasedType;
...@@ -460,9 +461,9 @@ class MethodTypeForm { ...@@ -460,9 +461,9 @@ class MethodTypeForm {
if (genericInvoker != null) return; if (genericInvoker != null) return;
try { try {
// Trigger adapter creation. // Trigger adapter creation.
genericInvoker = InvokeGeneric.genericInvokerOf(erasedType); genericInvoker = InvokeGeneric.generalInvokerOf(erasedType);
} catch (Exception ex) { } catch (Exception ex) {
Error err = new InternalError("Exception while resolving invokeGeneric"); Error err = new InternalError("Exception while resolving inexact invoke");
err.initCause(ex); err.initCause(ex);
throw err; throw err;
} }
......
...@@ -66,6 +66,10 @@ class SpreadGeneric { ...@@ -66,6 +66,10 @@ class SpreadGeneric {
this.entryPoint = ep[0]; this.entryPoint = ep[0];
} }
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
/** From targetType remove the last spreadCount arguments, and instead /** From targetType remove the last spreadCount arguments, and instead
* append a simple Object argument. * append a simple Object argument.
*/ */
......
...@@ -96,7 +96,7 @@ class ToGeneric { ...@@ -96,7 +96,7 @@ class ToGeneric {
ToGeneric va2 = ToGeneric.of(primsAtEnd); ToGeneric va2 = ToGeneric.of(primsAtEnd);
this.adapter = va2.adapter; this.adapter = va2.adapter;
if (true) throw new UnsupportedOperationException("NYI: primitive parameters must follow references; entryType = "+entryType); if (true) throw new UnsupportedOperationException("NYI: primitive parameters must follow references; entryType = "+entryType);
this.entryPoint = MethodHandleImpl.convertArguments( this.entryPoint = MethodHandleImpl.permuteArguments(
va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder); va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder);
// example: for entryType of (int,Object,Object), the reordered // example: for entryType of (int,Object,Object), the reordered
// type is (Object,Object,int) and the order is {1,2,0}, // type is (Object,Object,int) and the order is {1,2,0},
...@@ -128,7 +128,7 @@ class ToGeneric { ...@@ -128,7 +128,7 @@ class ToGeneric {
assert(eptWithInts.parameterType(i) == int.class); assert(eptWithInts.parameterType(i) == int.class);
MethodType nextType = midType.changeParameterType(i, int.class); MethodType nextType = midType.changeParameterType(i, int.class);
rawEntryPoint = MethodHandleImpl.convertArguments( rawEntryPoint = MethodHandleImpl.convertArguments(
rawEntryPoint, nextType, midType, null); rawEntryPoint, nextType, midType, 0);
midType = nextType; midType = nextType;
} }
} }
...@@ -152,6 +152,10 @@ class ToGeneric { ...@@ -152,6 +152,10 @@ class ToGeneric {
this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType); this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType);
} }
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
/** A generic argument list will be created by a call of type 'raw'. /** A generic argument list will be created by a call of type 'raw'.
* The values need to be reboxed for to match 'cooked'. * The values need to be reboxed for to match 'cooked'.
* Do this on the fly. * Do this on the fly.
...@@ -171,7 +175,7 @@ class ToGeneric { ...@@ -171,7 +175,7 @@ class ToGeneric {
invoker.type().generic(), invoker, 0, MethodHandle.class); invoker.type().generic(), invoker, 0, MethodHandle.class);
if (filteredInvoker == null) throw new UnsupportedOperationException("NYI"); if (filteredInvoker == null) throw new UnsupportedOperationException("NYI");
} }
MethodHandle reboxer = ValueConversions.rebox(dst, false); MethodHandle reboxer = ValueConversions.rebox(dst);
filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker); filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker);
if (filteredInvoker == null) throw new InternalError(); if (filteredInvoker == null) throw new InternalError();
} }
...@@ -199,13 +203,13 @@ class ToGeneric { ...@@ -199,13 +203,13 @@ class ToGeneric {
assert(!rret.isPrimitive()); assert(!rret.isPrimitive());
if (rret == Object.class && !mustCast) if (rret == Object.class && !mustCast)
return null; return null;
return ValueConversions.cast(tret, false); return ValueConversions.cast(tret);
} else if (tret == rret) { } else if (tret == rret) {
return ValueConversions.unbox(tret, false); return ValueConversions.unbox(tret);
} else { } else {
assert(rret.isPrimitive()); assert(rret.isPrimitive());
assert(tret == double.class ? rret == long.class : rret == int.class); assert(tret == double.class ? rret == long.class : rret == int.class);
return ValueConversions.unboxRaw(tret, false); return ValueConversions.unboxRaw(tret);
} }
} }
...@@ -311,7 +315,7 @@ class ToGeneric { ...@@ -311,7 +315,7 @@ class ToGeneric {
} }
static Adapter buildAdapterFromBytecodes(MethodType entryPointType) { static Adapter buildAdapterFromBytecodes(MethodType entryPointType) {
throw new UnsupportedOperationException("NYI"); throw new UnsupportedOperationException("NYI: "+entryPointType);
} }
/** /**
......
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
* The method handle constant produced for such a method behaves as if * The method handle constant produced for such a method behaves as if
* it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}. * it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}.
* In other words, the constant method handle will exhibit variable arity, * In other words, the constant method handle will exhibit variable arity,
* when invoked via {@code invokeGeneric}. * when invoked via {@code MethodHandle.invoke}.
* On the other hand, its behavior with respect to {@code invokeExact} will be the same * On the other hand, its behavior with respect to {@code invokeExact} will be the same
* as if the {@code varargs} bit were not set. * as if the {@code varargs} bit were not set.
* <p> * <p>
...@@ -243,7 +243,7 @@ ...@@ -243,7 +243,7 @@
* <li>optionally, one or more <a href="#args">additional static arguments</a> </li> * <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
* </ul> * </ul>
* The method handle is then applied to the other values as if by * The method handle is then applied to the other values as if by
* {@link java.lang.invoke.MethodHandle#invokeGeneric invokeGeneric}. * {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}.
* The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass). * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
* The type of the call site's target must be exactly equal to the type * The type of the call site's target must be exactly equal to the type
* derived from the dynamic call site's type descriptor and passed to * derived from the dynamic call site's type descriptor and passed to
...@@ -251,7 +251,7 @@ ...@@ -251,7 +251,7 @@
* The call site then becomes permanently linked to the dynamic call site. * The call site then becomes permanently linked to the dynamic call site.
* <p> * <p>
* As long as each bootstrap method can be correctly invoked * As long as each bootstrap method can be correctly invoked
* by <code>invokeGeneric</code>, its detailed type is arbitrary. * by <code>MethodHandle.invoke</code>, its detailed type is arbitrary.
* For example, the first argument could be {@code Object} * For example, the first argument could be {@code Object}
* instead of {@code MethodHandles.Lookup}, and the return type * instead of {@code MethodHandles.Lookup}, and the return type
* could also be {@code Object} instead of {@code CallSite}. * could also be {@code Object} instead of {@code CallSite}.
...@@ -272,7 +272,7 @@ ...@@ -272,7 +272,7 @@
* (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType}, * (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
* or {@code CONSTANT_MethodHandle} argument cannot be linked) </li> * or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
* <li>the bootstrap method has the wrong arity, * <li>the bootstrap method has the wrong arity,
* causing {@code invokeGeneric} to throw {@code WrongMethodTypeException} </li> * causing {@code MethodHandle.invoke} to throw {@code WrongMethodTypeException} </li>
* <li>the bootstrap method has a wrong argument or return type </li> * <li>the bootstrap method has a wrong argument or return type </li>
* <li>the bootstrap method invocation completes abnormally </li> * <li>the bootstrap method invocation completes abnormally </li>
* <li>the result from the bootstrap invocation is not a reference to * <li>the result from the bootstrap invocation is not a reference to
...@@ -381,10 +381,10 @@ ...@@ -381,10 +381,10 @@
* those values will be passed as additional arguments to the method handle. * those values will be passed as additional arguments to the method handle.
* (Note that because there is a limit of 255 arguments to any method, * (Note that because there is a limit of 255 arguments to any method,
* at most 252 extra arguments can be supplied.) * at most 252 extra arguments can be supplied.)
* The bootstrap method will be invoked as if by either {@code invokeGeneric} * The bootstrap method will be invoked as if by either {@code MethodHandle.invoke}
* or {@code invokeWithArguments}. (There is no way to tell the difference.) * or {@code invokeWithArguments}. (There is no way to tell the difference.)
* <p> * <p>
* The normal argument conversion rules for {@code invokeGeneric} apply to all stacked arguments. * The normal argument conversion rules for {@code MethodHandle.invoke} apply to all stacked arguments.
* For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion. * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
* If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set), * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
* then some or all of the arguments specified here may be collected into a trailing array parameter. * then some or all of the arguments specified here may be collected into a trailing array parameter.
...@@ -419,8 +419,8 @@ ...@@ -419,8 +419,8 @@
* For example, the fourth argument could be {@code MethodHandle}, * For example, the fourth argument could be {@code MethodHandle},
* if that is the type of the corresponding constant in * if that is the type of the corresponding constant in
* the {@code CONSTANT_InvokeDynamic} entry. * the {@code CONSTANT_InvokeDynamic} entry.
* In that case, the {@code invokeGeneric} call will pass the extra method handle * In that case, the {@code MethodHandle.invoke} call will pass the extra method handle
* constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric} * constant as an {@code Object}, but the type matching machinery of {@code MethodHandle.invoke}
* will cast the reference back to {@code MethodHandle} before invoking the bootstrap method. * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
* (If a string constant were passed instead, by badly generated code, that cast would then fail, * (If a string constant were passed instead, by badly generated code, that cast would then fail,
* resulting in a {@code BootstrapMethodError}.) * resulting in a {@code BootstrapMethodError}.)
......
...@@ -211,6 +211,20 @@ to any listeners. ...@@ -211,6 +211,20 @@ to any listeners.
<p> <p>
<a name=optcolor><b>Optional ColorSpace support:</b></a>
Handling of PhotoYCC (YCC), PhotoYCCA (YCCA), RGBA and YCbCrA color spaces
by the standard plugin, as described below, is dependent on capabilities
of the libraries used to interpret the JPEG data. Thus all consequential
behaviors are optional. If the support is not available when decoding,
the color space will be treated as unrecognized and the appropriate
default color space for the specified number of component channels
may be used.
When writing, an Exception may be thrown if no suitable conversion
can be applied before encoding.
But where the support for these color spaces is available, the behavior
must be as documented.
<p>
When reading, the contents of the stream are interpreted by the usual When reading, the contents of the stream are interpreted by the usual
JPEG conventions, as follows: JPEG conventions, as follows:
...@@ -241,8 +255,11 @@ JPEG conventions, as follows: ...@@ -241,8 +255,11 @@ JPEG conventions, as follows:
2-channel images are assumed to be grayscale with an alpha channel. 2-channel images are assumed to be grayscale with an alpha channel.
For 3- and 4-channel images, the component ids are consulted. If these For 3- and 4-channel images, the component ids are consulted. If these
values are 1-3 for a 3-channel image, then the image is assumed to be values are 1-3 for a 3-channel image, then the image is assumed to be
YCbCr. If these values are 1-4 for a 4-channel image, then the image YCbCr. Subject to the availability of the
is assumed to be YCbCrA. If these values are > 4, they are checked <a href=#optcolor>optional color space support</a>
described above, if these values are 1-4 for a 4-channel image,
then the image is assumed to be YCbCrA.
If these values are > 4, they are checked
against the ASCII codes for 'R', 'G', 'B', 'A', 'C', 'c'. These can against the ASCII codes for 'R', 'G', 'B', 'A', 'C', 'c'. These can
encode the following colorspaces: encode the following colorspaces:
<p> <p>
...@@ -346,12 +363,16 @@ If no metadata object is specified, then the following defaults apply: ...@@ -346,12 +363,16 @@ If no metadata object is specified, then the following defaults apply:
component ids in the frame and scan headers are set to 1, 2, and 3. component ids in the frame and scan headers are set to 1, 2, and 3.
<li> RGBA images are converted to YCbCrA, subsampled in the <li> Subject to the <a href=#optcolor>optional library support</a>
described above,
RGBA images are converted to YCbCrA, subsampled in the
chrominance channels by half both vertically and horizontally, and chrominance channels by half both vertically and horizontally, and
written without any special marker segments. The component ids written without any special marker segments. The component ids
in the frame and scan headers are set to 1, 2, 3, and 4. in the frame and scan headers are set to 1, 2, 3, and 4.
<li> PhotoYCC and YCCAimages are subsampled by half in the chrominance <li> Subject to the <a href=#optcolor>optional library support</a>
described above,
PhotoYCC and YCCAimages are subsampled by half in the chrominance
channels both vertically and horizontally and written with an channels both vertically and horizontally and written with an
Adobe <code>APP14</code> marker segment and 'Y','C', and 'c' (and Adobe <code>APP14</code> marker segment and 'Y','C', and 'c' (and
'A' if an alpha channel is present) as component ids in the frame 'A' if an alpha channel is present) as component ids in the frame
...@@ -433,6 +454,8 @@ in the frame header node of the metadata object, regardless of color space.) ...@@ -433,6 +454,8 @@ in the frame header node of the metadata object, regardless of color space.)
</ul> </ul>
<li> RGBA images: <li> RGBA images:
Subject to the <a href=#optcolor>optional library support</a>
described above,
<ul> <ul>
<li> If an <code>app0JFIF</code> node is present in the metadata object, <li> If an <code>app0JFIF</code> node is present in the metadata object,
it is ignored and a warning is sent to listeners, as JFIF does not it is ignored and a warning is sent to listeners, as JFIF does not
...@@ -456,6 +479,8 @@ in the frame header node of the metadata object, regardless of color space.) ...@@ -456,6 +479,8 @@ in the frame header node of the metadata object, regardless of color space.)
</ul> </ul>
<li> PhotoYCC Images: <li> PhotoYCC Images:
Subject to the <a href=#optcolor>optional library support</a>
described above,
<ul> <ul>
<li> If an <code>app0JFIF</code> node is present in the metadata object, <li> If an <code>app0JFIF</code> node is present in the metadata object,
the image is converted to sRGB, and then to YCbCr during encoding, the image is converted to sRGB, and then to YCbCr during encoding,
...@@ -471,6 +496,8 @@ in the frame header node of the metadata object, regardless of color space.) ...@@ -471,6 +496,8 @@ in the frame header node of the metadata object, regardless of color space.)
</ul> </ul>
<li> PhotoYCCA Images: <li> PhotoYCCA Images:
Subject to the <a href=#optcolor>optional library support</a>
described above,
<ul> <ul>
<li> If an <code>app0JFIF</code> node is present in the metadata object, <li> If an <code>app0JFIF</code> node is present in the metadata object,
it is ignored and a warning is sent to listeners, as JFIF does not it is ignored and a warning is sent to listeners, as JFIF does not
......
...@@ -33,9 +33,11 @@ package javax.swing; ...@@ -33,9 +33,11 @@ package javax.swing;
* <code>ListModel</code>. This disjoint behavior allows for the temporary * <code>ListModel</code>. This disjoint behavior allows for the temporary
* storage and retrieval of a selected item in the model. * storage and retrieval of a selected item in the model.
* *
* @param <E> the type of the elements of this model
*
* @author Arnaud Weber * @author Arnaud Weber
*/ */
public interface ComboBoxModel extends ListModel { public interface ComboBoxModel<E> extends ListModel<E> {
/** /**
* Set the selected item. The implementation of this method should notify * Set the selected item. The implementation of this method should notify
......
...@@ -24,39 +24,28 @@ ...@@ -24,39 +24,28 @@
*/ */
package javax.swing; package javax.swing;
import java.beans.*;
import java.util.*; import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.Serializable; import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.border.*;
import javax.accessibility.*;
/** /**
* The default model for combo boxes. * The default model for combo boxes.
* *
* @param <E> the type of the elements of this model
*
* @author Arnaud Weber * @author Arnaud Weber
* @author Tom Santos * @author Tom Santos
*/ */
public class DefaultComboBoxModel extends AbstractListModel implements MutableComboBoxModel, Serializable { public class DefaultComboBoxModel<E> extends AbstractListModel<E> implements MutableComboBoxModel<E>, Serializable {
Vector objects; Vector<E> objects;
Object selectedObject; Object selectedObject;
/** /**
* Constructs an empty DefaultComboBoxModel object. * Constructs an empty DefaultComboBoxModel object.
*/ */
public DefaultComboBoxModel() { public DefaultComboBoxModel() {
objects = new Vector(); objects = new Vector<E>();
} }
/** /**
...@@ -65,8 +54,8 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo ...@@ -65,8 +54,8 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo
* *
* @param items an array of Object objects * @param items an array of Object objects
*/ */
public DefaultComboBoxModel(final Object items[]) { public DefaultComboBoxModel(final E items[]) {
objects = new Vector(); objects = new Vector<E>();
objects.ensureCapacity( items.length ); objects.ensureCapacity( items.length );
int i,c; int i,c;
...@@ -84,7 +73,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo ...@@ -84,7 +73,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo
* *
* @param v a Vector object ... * @param v a Vector object ...
*/ */
public DefaultComboBoxModel(Vector<?> v) { public DefaultComboBoxModel(Vector<E> v) {
objects = v; objects = v;
if ( getSize() > 0 ) { if ( getSize() > 0 ) {
...@@ -117,7 +106,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo ...@@ -117,7 +106,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo
} }
// implements javax.swing.ListModel // implements javax.swing.ListModel
public Object getElementAt(int index) { public E getElementAt(int index) {
if ( index >= 0 && index < objects.size() ) if ( index >= 0 && index < objects.size() )
return objects.elementAt(index); return objects.elementAt(index);
else else
...@@ -136,7 +125,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo ...@@ -136,7 +125,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo
} }
// implements javax.swing.MutableComboBoxModel // implements javax.swing.MutableComboBoxModel
public void addElement(Object anObject) { public void addElement(E anObject) {
objects.addElement(anObject); objects.addElement(anObject);
fireIntervalAdded(this,objects.size()-1, objects.size()-1); fireIntervalAdded(this,objects.size()-1, objects.size()-1);
if ( objects.size() == 1 && selectedObject == null && anObject != null ) { if ( objects.size() == 1 && selectedObject == null && anObject != null ) {
...@@ -145,7 +134,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo ...@@ -145,7 +134,7 @@ public class DefaultComboBoxModel extends AbstractListModel implements MutableCo
} }
// implements javax.swing.MutableComboBoxModel // implements javax.swing.MutableComboBoxModel
public void insertElementAt(Object anObject,int index) { public void insertElementAt(E anObject,int index) {
objects.insertElementAt(anObject,index); objects.insertElementAt(anObject,index);
fireIntervalAdded(this, index, index); fireIntervalAdded(this, index, index);
} }
......
...@@ -69,6 +69,8 @@ import javax.accessibility.*; ...@@ -69,6 +69,8 @@ import javax.accessibility.*;
* @see ComboBoxModel * @see ComboBoxModel
* @see DefaultComboBoxModel * @see DefaultComboBoxModel
* *
* @param <E> the type of the elements of this combo box
*
* @beaninfo * @beaninfo
* attribute: isContainer false * attribute: isContainer false
* description: A combination of a text field and a drop-down list. * description: A combination of a text field and a drop-down list.
...@@ -76,7 +78,7 @@ import javax.accessibility.*; ...@@ -76,7 +78,7 @@ import javax.accessibility.*;
* @author Arnaud Weber * @author Arnaud Weber
* @author Mark Davidson * @author Mark Davidson
*/ */
public class JComboBox extends JComponent public class JComboBox<E> extends JComponent
implements ItemSelectable,ListDataListener,ActionListener, Accessible { implements ItemSelectable,ListDataListener,ActionListener, Accessible {
/** /**
* @see #getUIClassID * @see #getUIClassID
...@@ -91,7 +93,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -91,7 +93,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* @see #getModel * @see #getModel
* @see #setModel * @see #setModel
*/ */
protected ComboBoxModel dataModel; protected ComboBoxModel<E> dataModel;
/** /**
* This protected field is implementation specific. Do not access directly * This protected field is implementation specific. Do not access directly
* or override. Use the accessor methods instead. * or override. Use the accessor methods instead.
...@@ -99,7 +101,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -99,7 +101,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* @see #getRenderer * @see #getRenderer
* @see #setRenderer * @see #setRenderer
*/ */
protected ListCellRenderer renderer; protected ListCellRenderer<? super E> renderer;
/** /**
* This protected field is implementation specific. Do not access directly * This protected field is implementation specific. Do not access directly
* or override. Use the accessor methods instead. * or override. Use the accessor methods instead.
...@@ -156,7 +158,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -156,7 +158,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
*/ */
protected Object selectedItemReminder = null; protected Object selectedItemReminder = null;
private Object prototypeDisplayValue; private E prototypeDisplayValue;
// Flag to ensure that infinite loops do not occur with ActionEvents. // Flag to ensure that infinite loops do not occur with ActionEvents.
private boolean firingActionEvent = false; private boolean firingActionEvent = false;
...@@ -175,7 +177,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -175,7 +177,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* displayed list of items * displayed list of items
* @see DefaultComboBoxModel * @see DefaultComboBoxModel
*/ */
public JComboBox(ComboBoxModel aModel) { public JComboBox(ComboBoxModel<E> aModel) {
super(); super();
setModel(aModel); setModel(aModel);
init(); init();
...@@ -189,9 +191,9 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -189,9 +191,9 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* @param items an array of objects to insert into the combo box * @param items an array of objects to insert into the combo box
* @see DefaultComboBoxModel * @see DefaultComboBoxModel
*/ */
public JComboBox(final Object items[]) { public JComboBox(E[] items) {
super(); super();
setModel(new DefaultComboBoxModel(items)); setModel(new DefaultComboBoxModel<E>(items));
init(); init();
} }
...@@ -203,9 +205,9 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -203,9 +205,9 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* @param items an array of vectors to insert into the combo box * @param items an array of vectors to insert into the combo box
* @see DefaultComboBoxModel * @see DefaultComboBoxModel
*/ */
public JComboBox(Vector<?> items) { public JComboBox(Vector<E> items) {
super(); super();
setModel(new DefaultComboBoxModel(items)); setModel(new DefaultComboBoxModel<E>(items));
init(); init();
} }
...@@ -219,7 +221,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -219,7 +221,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
*/ */
public JComboBox() { public JComboBox() {
super(); super();
setModel(new DefaultComboBoxModel()); setModel(new DefaultComboBoxModel<E>());
init(); init();
} }
...@@ -263,7 +265,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -263,7 +265,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
public void updateUI() { public void updateUI() {
setUI((ComboBoxUI)UIManager.getUI(this)); setUI((ComboBoxUI)UIManager.getUI(this));
ListCellRenderer renderer = getRenderer(); ListCellRenderer<? super E> renderer = getRenderer();
if (renderer instanceof Component) { if (renderer instanceof Component) {
SwingUtilities.updateComponentTreeUI((Component)renderer); SwingUtilities.updateComponentTreeUI((Component)renderer);
} }
...@@ -302,8 +304,8 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -302,8 +304,8 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* bound: true * bound: true
* description: Model that the combo box uses to get data to display. * description: Model that the combo box uses to get data to display.
*/ */
public void setModel(ComboBoxModel aModel) { public void setModel(ComboBoxModel<E> aModel) {
ComboBoxModel oldModel = dataModel; ComboBoxModel<E> oldModel = dataModel;
if (oldModel != null) { if (oldModel != null) {
oldModel.removeListDataListener(this); oldModel.removeListDataListener(this);
} }
...@@ -322,7 +324,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -322,7 +324,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* @return the <code>ComboBoxModel</code> that provides the displayed * @return the <code>ComboBoxModel</code> that provides the displayed
* list of items * list of items
*/ */
public ComboBoxModel getModel() { public ComboBoxModel<E> getModel() {
return dataModel; return dataModel;
} }
...@@ -461,8 +463,8 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -461,8 +463,8 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* expert: true * expert: true
* description: The renderer that paints the item selected in the list. * description: The renderer that paints the item selected in the list.
*/ */
public void setRenderer(ListCellRenderer aRenderer) { public void setRenderer(ListCellRenderer<? super E> aRenderer) {
ListCellRenderer oldRenderer = renderer; ListCellRenderer<? super E> oldRenderer = renderer;
renderer = aRenderer; renderer = aRenderer;
firePropertyChange( "renderer", oldRenderer, renderer ); firePropertyChange( "renderer", oldRenderer, renderer );
invalidate(); invalidate();
...@@ -475,7 +477,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -475,7 +477,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* @return the <code>ListCellRenderer</code> that displays * @return the <code>ListCellRenderer</code> that displays
* the selected item. * the selected item.
*/ */
public ListCellRenderer getRenderer() { public ListCellRenderer<? super E> getRenderer() {
return renderer; return renderer;
} }
...@@ -558,7 +560,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -558,7 +560,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
// will be rejected. // will be rejected.
boolean found = false; boolean found = false;
for (int i = 0; i < dataModel.getSize(); i++) { for (int i = 0; i < dataModel.getSize(); i++) {
Object element = dataModel.getElementAt(i); E element = dataModel.getElementAt(i);
if (anObject.equals(element)) { if (anObject.equals(element)) {
found = true; found = true;
objectToSelect = element; objectToSelect = element;
...@@ -640,7 +642,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -640,7 +642,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
public int getSelectedIndex() { public int getSelectedIndex() {
Object sObject = dataModel.getSelectedItem(); Object sObject = dataModel.getSelectedItem();
int i,c; int i,c;
Object obj; E obj;
for ( i=0,c=dataModel.getSize();i<c;i++ ) { for ( i=0,c=dataModel.getSize();i<c;i++ ) {
obj = dataModel.getElementAt(i); obj = dataModel.getElementAt(i);
...@@ -658,7 +660,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -658,7 +660,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* @see #setPrototypeDisplayValue * @see #setPrototypeDisplayValue
* @since 1.4 * @since 1.4
*/ */
public Object getPrototypeDisplayValue() { public E getPrototypeDisplayValue() {
return prototypeDisplayValue; return prototypeDisplayValue;
} }
...@@ -683,7 +685,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -683,7 +685,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* attribute: visualUpdate true * attribute: visualUpdate true
* description: The display prototype value, used to compute display width and height. * description: The display prototype value, used to compute display width and height.
*/ */
public void setPrototypeDisplayValue(Object prototypeDisplayValue) { public void setPrototypeDisplayValue(E prototypeDisplayValue) {
Object oldValue = this.prototypeDisplayValue; Object oldValue = this.prototypeDisplayValue;
this.prototypeDisplayValue = prototypeDisplayValue; this.prototypeDisplayValue = prototypeDisplayValue;
firePropertyChange("prototypeDisplayValue", oldValue, prototypeDisplayValue); firePropertyChange("prototypeDisplayValue", oldValue, prototypeDisplayValue);
...@@ -708,12 +710,12 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -708,12 +710,12 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* } * }
* </pre> * </pre>
* *
* @param anObject the Object to add to the list * @param item the item to add to the list
* @see MutableComboBoxModel * @see MutableComboBoxModel
*/ */
public void addItem(Object anObject) { public void addItem(E item) {
checkMutableComboBoxModel(); checkMutableComboBoxModel();
((MutableComboBoxModel)dataModel).addElement(anObject); ((MutableComboBoxModel<E>)dataModel).addElement(item);
} }
/** /**
...@@ -721,14 +723,14 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -721,14 +723,14 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* This method works only if the <code>JComboBox</code> uses a * This method works only if the <code>JComboBox</code> uses a
* mutable data model. * mutable data model.
* *
* @param anObject the <code>Object</code> to add to the list * @param item the item to add to the list
* @param index an integer specifying the position at which * @param index an integer specifying the position at which
* to add the item * to add the item
* @see MutableComboBoxModel * @see MutableComboBoxModel
*/ */
public void insertItemAt(Object anObject, int index) { public void insertItemAt(E item, int index) {
checkMutableComboBoxModel(); checkMutableComboBoxModel();
((MutableComboBoxModel)dataModel).insertElementAt(anObject,index); ((MutableComboBoxModel<E>)dataModel).insertElementAt(item,index);
} }
/** /**
...@@ -756,7 +758,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -756,7 +758,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
*/ */
public void removeItemAt(int anIndex) { public void removeItemAt(int anIndex) {
checkMutableComboBoxModel(); checkMutableComboBoxModel();
((MutableComboBoxModel)dataModel).removeElementAt( anIndex ); ((MutableComboBoxModel<E>)dataModel).removeElementAt( anIndex );
} }
/** /**
...@@ -764,7 +766,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -764,7 +766,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
*/ */
public void removeAllItems() { public void removeAllItems() {
checkMutableComboBoxModel(); checkMutableComboBoxModel();
MutableComboBoxModel model = (MutableComboBoxModel)dataModel; MutableComboBoxModel<E> model = (MutableComboBoxModel<E>)dataModel;
int size = model.getSize(); int size = model.getSize();
if ( model instanceof DefaultComboBoxModel ) { if ( model instanceof DefaultComboBoxModel ) {
...@@ -772,7 +774,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -772,7 +774,7 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
} }
else { else {
for ( int i = 0; i < size; ++i ) { for ( int i = 0; i < size; ++i ) {
Object element = model.getElementAt( 0 ); E element = model.getElementAt( 0 );
model.removeElement( element ); model.removeElement( element );
} }
} }
...@@ -1188,11 +1190,11 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -1188,11 +1190,11 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
private static class ComboBoxActionPropertyChangeListener private static class ComboBoxActionPropertyChangeListener
extends ActionPropertyChangeListener<JComboBox> { extends ActionPropertyChangeListener<JComboBox<?>> {
ComboBoxActionPropertyChangeListener(JComboBox b, Action a) { ComboBoxActionPropertyChangeListener(JComboBox<?> b, Action a) {
super(b, a); super(b, a);
} }
protected void actionPropertyChanged(JComboBox cb, protected void actionPropertyChanged(JComboBox<?> cb,
Action action, Action action,
PropertyChangeEvent e) { PropertyChangeEvent e) {
if (AbstractAction.shouldReconfigure(e)) { if (AbstractAction.shouldReconfigure(e)) {
...@@ -1454,10 +1456,10 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible { ...@@ -1454,10 +1456,10 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
* *
* @param index an integer indicating the list position, where the first * @param index an integer indicating the list position, where the first
* item starts at zero * item starts at zero
* @return the <code>Object</code> at that list position; or * @return the item at that list position; or
* <code>null</code> if out of range * <code>null</code> if out of range
*/ */
public Object getItemAt(int index) { public E getItemAt(int index) {
return dataModel.getElementAt(index); return dataModel.getElementAt(index);
} }
......
...@@ -27,19 +27,21 @@ package javax.swing; ...@@ -27,19 +27,21 @@ package javax.swing;
/** /**
* A mutable version of <code>ComboBoxModel</code>. * A mutable version of <code>ComboBoxModel</code>.
* *
* @param <E> the type of the elements of this model
*
* @author Tom Santos * @author Tom Santos
*/ */
public interface MutableComboBoxModel extends ComboBoxModel { public interface MutableComboBoxModel<E> extends ComboBoxModel<E> {
/** /**
* Adds an item at the end of the model. The implementation of this method * Adds an item at the end of the model. The implementation of this method
* should notify all registered <code>ListDataListener</code>s that the * should notify all registered <code>ListDataListener</code>s that the
* item has been added. * item has been added.
* *
* @param obj the <code>Object</code> to be added * @param item the item to be added
*/ */
public void addElement( Object obj ); public void addElement( E item );
/** /**
* Removes an item from the model. The implementation of this method should * Removes an item from the model. The implementation of this method should
...@@ -55,17 +57,17 @@ public interface MutableComboBoxModel extends ComboBoxModel { ...@@ -55,17 +57,17 @@ public interface MutableComboBoxModel extends ComboBoxModel {
* should notify all registered <code>ListDataListener</code>s that the * should notify all registered <code>ListDataListener</code>s that the
* item has been added. * item has been added.
* *
* @param obj the <code>Object</code> to be added * @param item the item to be added
* @param index location to add the object * @param index location to add the object
*/ */
public void insertElementAt( Object obj, int index ); public void insertElementAt( E item, int index );
/** /**
* Removes an item at a specific index. The implementation of this method * Removes an item at a specific index. The implementation of this method
* should notify all registered <code>ListDataListener</code>s that the * should notify all registered <code>ListDataListener</code>s that the
* item has been removed. * item has been removed.
* *
* @param index location of object to be removed * @param index location of the item to be removed
*/ */
public void removeElementAt( int index ); public void removeElementAt( int index );
} }
...@@ -40,7 +40,7 @@ import sun.awt.shell.ShellFolder; ...@@ -40,7 +40,7 @@ import sun.awt.shell.ShellFolder;
* *
* @author Jeff Dinkins * @author Jeff Dinkins
*/ */
public class BasicDirectoryModel extends AbstractListModel implements PropertyChangeListener { public class BasicDirectoryModel extends AbstractListModel<Object> implements PropertyChangeListener {
private JFileChooser filechooser = null; private JFileChooser filechooser = null;
// PENDING(jeff) pick the size more sensibly // PENDING(jeff) pick the size more sensibly
......
...@@ -906,7 +906,7 @@ public class MetalFileChooserUI extends BasicFileChooserUI { ...@@ -906,7 +906,7 @@ public class MetalFileChooserUI extends BasicFileChooserUI {
/** /**
* Data model for a type-face selection combo-box. * Data model for a type-face selection combo-box.
*/ */
protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { protected class DirectoryComboBoxModel extends AbstractListModel<Object> implements ComboBoxModel<Object> {
Vector<File> directories = new Vector<File>(); Vector<File> directories = new Vector<File>();
int[] depths = null; int[] depths = null;
File selectedDirectory = null; File selectedDirectory = null;
...@@ -1063,7 +1063,7 @@ public class MetalFileChooserUI extends BasicFileChooserUI { ...@@ -1063,7 +1063,7 @@ public class MetalFileChooserUI extends BasicFileChooserUI {
/** /**
* Data model for a type-face selection combo-box. * Data model for a type-face selection combo-box.
*/ */
protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, PropertyChangeListener { protected class FilterComboBoxModel extends AbstractListModel<Object> implements ComboBoxModel<Object>, PropertyChangeListener {
protected FileFilter[] filters; protected FileFilter[] filters;
protected FilterComboBoxModel() { protected FilterComboBoxModel() {
super(); super();
......
...@@ -488,6 +488,18 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI ...@@ -488,6 +488,18 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI
paintContentBorder(tabContentContext, g, tabPlacement, selectedIndex); paintContentBorder(tabContentContext, g, tabPlacement, selectedIndex);
} }
protected void paintTabArea(Graphics g, int tabPlacement,
int selectedIndex) {
// This can be invoked from ScrollabeTabPanel
Insets insets = tabPane.getInsets();
int x = insets.left;
int y = insets.top;
int width = tabPane.getWidth() - insets.left - insets.right;
int height = tabPane.getHeight() - insets.top - insets.bottom;
paintTabArea(tabAreaContext, g, tabPlacement, selectedIndex,
new Rectangle(x, y, width, height));
}
private void paintTabArea(SynthContext ss, Graphics g, private void paintTabArea(SynthContext ss, Graphics g,
int tabPlacement, int selectedIndex, int tabPlacement, int selectedIndex,
......
...@@ -54,9 +54,15 @@ public class VerifyType { ...@@ -54,9 +54,15 @@ public class VerifyType {
if (dst == void.class) return true; // drop any return value if (dst == void.class) return true; // drop any return value
if (isNullType(src)) return !dst.isPrimitive(); if (isNullType(src)) return !dst.isPrimitive();
if (!src.isPrimitive()) return dst.isAssignableFrom(src); if (!src.isPrimitive()) return dst.isAssignableFrom(src);
if (!dst.isPrimitive()) return false;
// Verifier allows an int to carry byte, short, char, or even boolean: // Verifier allows an int to carry byte, short, char, or even boolean:
if (dst == int.class) return Wrapper.forPrimitiveType(src).isSubwordOrInt(); Wrapper sw = Wrapper.forPrimitiveType(src);
return false; if (dst == int.class) return sw.isSubwordOrInt();
Wrapper dw = Wrapper.forPrimitiveType(dst);
if (!sw.isSubwordOrInt()) return false;
if (!dw.isSubwordOrInt()) return false;
if (!dw.isSigned() && sw.isSigned()) return false;
return dw.bitWidth() > sw.bitWidth();
} }
/** /**
...@@ -155,6 +161,7 @@ public class VerifyType { ...@@ -155,6 +161,7 @@ public class VerifyType {
return -1; // truncation may be required return -1; // truncation may be required
if (!dw.isSigned() && sw.isSigned()) if (!dw.isSigned() && sw.isSigned())
return -1; // sign elimination may be required return -1; // sign elimination may be required
return 1;
} }
if (src == float.class || dst == float.class) { if (src == float.class || dst == float.class) {
if (src == double.class || dst == double.class) if (src == double.class || dst == double.class)
......
...@@ -26,37 +26,47 @@ ...@@ -26,37 +26,47 @@
package sun.invoke.util; package sun.invoke.util;
public enum Wrapper { public enum Wrapper {
BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)), BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, new boolean[0], Format.unsigned(1)),
// These must be in the order defined for widening primitive conversions in JLS 5.1.2 // These must be in the order defined for widening primitive conversions in JLS 5.1.2
BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)), BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed(8)),
SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)), SHORT(Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed(16)),
CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)), CHAR(Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)),
INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)), INT(Integer.class, int.class, 'I', (Integer)(int)0, new int[0], Format.signed(32)),
LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)), LONG(Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed(64)),
FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)), FLOAT(Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)),
DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)), DOUBLE(Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)),
//NULL(Null.class, null.class, 'N', null, Format.other(1)), //NULL(Null.class, null.class, 'N', null, null, Format.other(1)),
OBJECT(Object.class, Object.class, 'L', null, Format.other(1)), OBJECT(Object.class, Object.class, 'L', null, new Object[0], Format.other(1)),
// VOID must be the last type, since it is "assignable" from any other type: // VOID must be the last type, since it is "assignable" from any other type:
VOID(Void.class, void.class, 'V', null, Format.other(0)), VOID(Void.class, void.class, 'V', null, null, Format.other(0)),
; ;
private final Class<?> wrapperType; private final Class<?> wrapperType;
private final Class<?> primitiveType; private final Class<?> primitiveType;
private final char basicTypeChar; private final char basicTypeChar;
private final Object zero; private final Object zero;
private final Object emptyArray;
private final int format; private final int format;
private final String simpleName; private final String simpleName;
private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, int format) { private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) {
this.wrapperType = wtype; this.wrapperType = wtype;
this.primitiveType = ptype; this.primitiveType = ptype;
this.basicTypeChar = tchar; this.basicTypeChar = tchar;
this.zero = zero; this.zero = zero;
this.emptyArray = emptyArray;
this.format = format; this.format = format;
this.simpleName = wtype.getSimpleName(); this.simpleName = wtype.getSimpleName();
} }
/** For debugging, give the details of this wrapper. */
public String detailString() {
return simpleName+
java.util.Arrays.asList(wrapperType, primitiveType,
basicTypeChar, zero,
"0x"+Integer.toHexString(format));
}
private static abstract class Format { private static abstract class Format {
static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12; static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
static final int static final int
...@@ -114,16 +124,18 @@ public enum Wrapper { ...@@ -114,16 +124,18 @@ public enum Wrapper {
public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; } public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; }
/** Is the wrapped type either float or double? */ /** Is the wrapped type either float or double? */
public boolean isFloating() { return format >= Format.FLOAT; } public boolean isFloating() { return format >= Format.FLOAT; }
/** Is the wrapped type either void or a reference? */
public boolean isOther() { return (format & ~Format.SLOT_MASK) == 0; }
/** Does the JVM verifier allow a variable of this wrapper's /** Does the JLS 5.1.2 allow a variable of this wrapper's
* primitive type to be assigned from a value of the given wrapper's primitive type? * primitive type to be assigned from a value of the given wrapper's primitive type?
* Cases: * Cases:
* <ul> * <ul>
* <li>unboxing followed by widening primitive conversion * <li>unboxing followed by widening primitive conversion
* <li>any type converted to {@code void} * <li>any type converted to {@code void} (i.e., dropping a method call's value)
* <li>boxing conversion followed by widening reference conversion to {@code Object} * <li>boxing conversion followed by widening reference conversion to {@code Object}
* <li>conversion of {@code boolean} to any type
* </ul> * </ul>
* These are the cases allowed by MethodHandle.asType and convertArguments.
*/ */
public boolean isConvertibleFrom(Wrapper source) { public boolean isConvertibleFrom(Wrapper source) {
if (this == source) return true; if (this == source) return true;
...@@ -131,13 +143,75 @@ public enum Wrapper { ...@@ -131,13 +143,75 @@ public enum Wrapper {
// At best, this is a narrowing conversion. // At best, this is a narrowing conversion.
return false; return false;
} }
if ((this.format ^ source.format) == (Format.SHORT ^ Format.CHAR)) { // All conversions are allowed in the enum order between floats and signed ints.
assert (this == SHORT && source == CHAR) || (this == CHAR && source == SHORT); // First detect non-signed non-float types (boolean, char, Object, void).
boolean floatOrSigned = (((this.format & source.format) & Format.SIGNED) != 0);
if (!floatOrSigned) {
if (this.isOther()) return true;
// can convert char to int or wider, but nothing else
if (source.format == Format.CHAR) return true;
// no other conversions are classified as widening
return false; return false;
} }
// All signed and float conversions in the enum order are widening.
assert(this.isFloating() || this.isSigned());
assert(source.isFloating() || source.isSigned());
return true; return true;
} }
static { assert(checkConvertibleFrom()); }
private static boolean checkConvertibleFrom() {
// Check the matrix for correct classification of widening conversions.
for (Wrapper w : values()) {
assert(w.isConvertibleFrom(w));
assert(VOID.isConvertibleFrom(w));
if (w != VOID) {
assert(OBJECT.isConvertibleFrom(w));
assert(!w.isConvertibleFrom(VOID));
}
// check relations with unsigned integral types:
if (w != CHAR) {
assert(!CHAR.isConvertibleFrom(w));
if (!w.isConvertibleFrom(INT))
assert(!w.isConvertibleFrom(CHAR));
}
if (w != BOOLEAN) {
assert(!BOOLEAN.isConvertibleFrom(w));
if (w != VOID && w != OBJECT)
assert(!w.isConvertibleFrom(BOOLEAN));
}
// check relations with signed integral types:
if (w.isSigned()) {
for (Wrapper x : values()) {
if (w == x) continue;
if (x.isFloating())
assert(!w.isConvertibleFrom(x));
else if (x.isSigned()) {
if (w.compareTo(x) < 0)
assert(!w.isConvertibleFrom(x));
else
assert(w.isConvertibleFrom(x));
}
}
}
// check relations with floating types:
if (w.isFloating()) {
for (Wrapper x : values()) {
if (w == x) continue;
if (x.isSigned())
assert(w.isConvertibleFrom(x));
else if (x.isFloating()) {
if (w.compareTo(x) < 0)
assert(!w.isConvertibleFrom(x));
else
assert(w.isConvertibleFrom(x));
}
}
}
}
return true; // i.e., assert(true)
}
/** Produce a zero value for the given wrapper type. /** Produce a zero value for the given wrapper type.
* This will be a numeric zero for a number or character, * This will be a numeric zero for a number or character,
* false for a boolean, and null for a reference or void. * false for a boolean, and null for a reference or void.
...@@ -549,7 +623,7 @@ public enum Wrapper { ...@@ -549,7 +623,7 @@ public enum Wrapper {
} }
private static boolean boolValue(long bits) { private static boolean boolValue(long bits) {
//bits &= 1; // simple 31-bit zero extension bits &= 1; // simple 31-bit zero extension
return (bits != 0); return (bits != 0);
} }
...@@ -559,4 +633,31 @@ public enum Wrapper { ...@@ -559,4 +633,31 @@ public enum Wrapper {
private static RuntimeException newIllegalArgumentException(String message) { private static RuntimeException newIllegalArgumentException(String message) {
return new IllegalArgumentException(message); return new IllegalArgumentException(message);
} }
// primitive array support
public Object makeArray(int len) {
return java.lang.reflect.Array.newInstance(primitiveType, len);
}
public Class<?> arrayType() {
return emptyArray.getClass();
}
public void copyArrayUnboxing(Object[] values, int vpos, Object a, int apos, int length) {
if (a.getClass() != arrayType())
arrayType().cast(a); // throw NPE or CCE if bad type
for (int i = 0; i < length; i++) {
Object value = values[i+vpos];
value = convert(value, primitiveType);
java.lang.reflect.Array.set(a, i+apos, value);
}
}
public void copyArrayBoxing(Object a, int apos, Object[] values, int vpos, int length) {
if (a.getClass() != arrayType())
arrayType().cast(a); // throw NPE or CCE if bad type
for (int i = 0; i < length; i++) {
Object value = java.lang.reflect.Array.get(a, i+apos);
//Already done: value = convert(value, primitiveType);
assert(value.getClass() == wrapperType);
values[i+vpos] = value;
}
}
} }
...@@ -102,15 +102,20 @@ class OGLRenderer extends BufferedRenderPipe { ...@@ -102,15 +102,20 @@ class OGLRenderer extends BufferedRenderPipe {
final ParallelogramPipe realpipe = oglr.getAAParallelogramPipe(); final ParallelogramPipe realpipe = oglr.getAAParallelogramPipe();
return new ParallelogramPipe() { return new ParallelogramPipe() {
public void fillParallelogram(SunGraphics2D sg2d, public void fillParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
{ {
GraphicsPrimitive.tracePrimitive("OGLFillAAParallelogram"); GraphicsPrimitive.tracePrimitive("OGLFillAAParallelogram");
realpipe.fillParallelogram(sg2d, realpipe.fillParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2); x, y, dx1, dy1, dx2, dy2);
} }
public void drawParallelogram(SunGraphics2D sg2d, public void drawParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
...@@ -118,6 +123,7 @@ class OGLRenderer extends BufferedRenderPipe { ...@@ -118,6 +123,7 @@ class OGLRenderer extends BufferedRenderPipe {
{ {
GraphicsPrimitive.tracePrimitive("OGLDrawAAParallelogram"); GraphicsPrimitive.tracePrimitive("OGLDrawAAParallelogram");
realpipe.drawParallelogram(sg2d, realpipe.drawParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2, x, y, dx1, dy1, dx2, dy2,
lw1, lw2); lw1, lw2);
} }
...@@ -166,21 +172,29 @@ class OGLRenderer extends BufferedRenderPipe { ...@@ -166,21 +172,29 @@ class OGLRenderer extends BufferedRenderPipe {
oglr.fillSpans(sg2d, si, transx, transy); oglr.fillSpans(sg2d, si, transx, transy);
} }
public void fillParallelogram(SunGraphics2D sg2d, public void fillParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
{ {
GraphicsPrimitive.tracePrimitive("OGLFillParallelogram"); GraphicsPrimitive.tracePrimitive("OGLFillParallelogram");
oglr.fillParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2); oglr.fillParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2);
} }
public void drawParallelogram(SunGraphics2D sg2d, public void drawParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
double lw1, double lw2) double lw1, double lw2)
{ {
GraphicsPrimitive.tracePrimitive("OGLDrawParallelogram"); GraphicsPrimitive.tracePrimitive("OGLDrawParallelogram");
oglr.drawParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2, lw1, lw2); oglr.drawParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
} }
public void copyArea(SunGraphics2D sg2d, public void copyArea(SunGraphics2D sg2d,
int x, int y, int w, int h, int dx, int dy) int x, int y, int w, int h, int dx, int dy)
......
...@@ -68,21 +68,23 @@ public class AAShapePipe ...@@ -68,21 +68,23 @@ public class AAShapePipe
renderPath(sg, s, null); renderPath(sg, s, null);
} }
private static Rectangle2D computeBBox(double x, double y, private static Rectangle2D computeBBox(double ux1, double uy1,
double dx1, double dy1, double ux2, double uy2)
double dx2, double dy2)
{ {
double lox, loy, hix, hiy; if ((ux2 -= ux1) < 0) {
lox = hix = x; ux1 += ux2;
loy = hiy = y; ux2 = -ux2;
if (dx1 < 0) { lox += dx1; } else { hix += dx1; } }
if (dy1 < 0) { loy += dy1; } else { hiy += dy1; } if ((uy2 -= uy1) < 0) {
if (dx2 < 0) { lox += dx2; } else { hix += dx2; } uy1 += uy2;
if (dy2 < 0) { loy += dy2; } else { hiy += dy2; } uy2 = -uy2;
return new Rectangle2D.Double(lox, loy, hix-lox, hiy-loy); }
return new Rectangle2D.Double(ux1, uy1, ux2, uy2);
} }
public void fillParallelogram(SunGraphics2D sg, public void fillParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
...@@ -97,10 +99,12 @@ public class AAShapePipe ...@@ -97,10 +99,12 @@ public class AAShapePipe
return; return;
} }
renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox); renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
} }
public void drawParallelogram(SunGraphics2D sg, public void drawParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
...@@ -118,7 +122,7 @@ public class AAShapePipe ...@@ -118,7 +122,7 @@ public class AAShapePipe
// Note that bbox is of the original shape, not the wide path. // Note that bbox is of the original shape, not the wide path.
// This is appropriate for handing to Paint methods... // This is appropriate for handing to Paint methods...
renderTiles(sg, computeBBox(x, y, dx1, dy1, dx2, dy2), aatg, abox); renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
} }
private static byte[] theTile; private static byte[] theTile;
......
...@@ -66,6 +66,8 @@ public class AlphaColorPipe implements CompositePipe, ParallelogramPipe { ...@@ -66,6 +66,8 @@ public class AlphaColorPipe implements CompositePipe, ParallelogramPipe {
} }
public void fillParallelogram(SunGraphics2D sg, public void fillParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
...@@ -75,6 +77,8 @@ public class AlphaColorPipe implements CompositePipe, ParallelogramPipe { ...@@ -75,6 +77,8 @@ public class AlphaColorPipe implements CompositePipe, ParallelogramPipe {
} }
public void drawParallelogram(SunGraphics2D sg, public void drawParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
......
...@@ -408,6 +408,8 @@ public abstract class BufferedRenderPipe ...@@ -408,6 +408,8 @@ public abstract class BufferedRenderPipe
} }
public void fillParallelogram(SunGraphics2D sg2d, public void fillParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
...@@ -429,6 +431,8 @@ public abstract class BufferedRenderPipe ...@@ -429,6 +431,8 @@ public abstract class BufferedRenderPipe
} }
public void drawParallelogram(SunGraphics2D sg2d, public void drawParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
...@@ -454,6 +458,8 @@ public abstract class BufferedRenderPipe ...@@ -454,6 +458,8 @@ public abstract class BufferedRenderPipe
private class AAParallelogramPipe implements ParallelogramPipe { private class AAParallelogramPipe implements ParallelogramPipe {
public void fillParallelogram(SunGraphics2D sg2d, public void fillParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
...@@ -475,6 +481,8 @@ public abstract class BufferedRenderPipe ...@@ -475,6 +481,8 @@ public abstract class BufferedRenderPipe
} }
public void drawParallelogram(SunGraphics2D sg2d, public void drawParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
......
...@@ -352,6 +352,8 @@ public class LoopPipe ...@@ -352,6 +352,8 @@ public class LoopPipe
} }
public void fillParallelogram(SunGraphics2D sg2d, public void fillParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
...@@ -362,6 +364,8 @@ public class LoopPipe ...@@ -362,6 +364,8 @@ public class LoopPipe
} }
public void drawParallelogram(SunGraphics2D sg2d, public void drawParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
......
/* /*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2011 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -40,9 +40,17 @@ import sun.java2d.SunGraphics2D; ...@@ -40,9 +40,17 @@ import sun.java2d.SunGraphics2D;
* => (x+dx2, y+dy2) * => (x+dx2, y+dy2)
* => origin * => origin
* </pre> * </pre>
* The four u[xy][12] parameters are the unsorted extreme coordinates
* of the primitive in user space. They may have been generated by a
* line or a rectangle so they could have u[xy]2 < u[xy]1 in some cases.
* They should be sorted before calculating the bounds of the original
* primitive (such as for calculating the user space bounds for the
* Paint.createContext() method).
*/ */
public interface ParallelogramPipe { public interface ParallelogramPipe {
public void fillParallelogram(SunGraphics2D sg, public void fillParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2); double dx2, double dy2);
...@@ -59,6 +67,8 @@ public interface ParallelogramPipe { ...@@ -59,6 +67,8 @@ public interface ParallelogramPipe {
* difference between the outer and inner parallelograms. * difference between the outer and inner parallelograms.
*/ */
public void drawParallelogram(SunGraphics2D sg, public void drawParallelogram(SunGraphics2D sg,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
......
...@@ -175,8 +175,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -175,8 +175,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
} }
public boolean drawGeneralLine(SunGraphics2D sg2d, public boolean drawGeneralLine(SunGraphics2D sg2d,
double x1, double y1, double ux1, double uy1,
double x2, double y2) double ux2, double uy2)
{ {
if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM || if (sg2d.strokeState == SunGraphics2D.STROKE_CUSTOM ||
sg2d.strokeState == SunGraphics2D.STROKE_THINDASHED) sg2d.strokeState == SunGraphics2D.STROKE_THINDASHED)
...@@ -194,13 +194,14 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -194,13 +194,14 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
double lw = bs.getLineWidth(); double lw = bs.getLineWidth();
// Save the original dx, dy in case we need it to transform // Save the original dx, dy in case we need it to transform
// the linewidth as a perpendicular vector below // the linewidth as a perpendicular vector below
double dx = x2 - x1; double dx = ux2 - ux1;
double dy = y2 - y1; double dy = uy2 - uy1;
double x1, y1, x2, y2;
switch (sg2d.transformState) { switch (sg2d.transformState) {
case SunGraphics2D.TRANSFORM_GENERIC: case SunGraphics2D.TRANSFORM_GENERIC:
case SunGraphics2D.TRANSFORM_TRANSLATESCALE: case SunGraphics2D.TRANSFORM_TRANSLATESCALE:
{ {
double coords[] = {x1, y1, x2, y2}; double coords[] = {ux1, uy1, ux2, uy2};
sg2d.transform.transform(coords, 0, coords, 0, 2); sg2d.transform.transform(coords, 0, coords, 0, 2);
x1 = coords[0]; x1 = coords[0];
y1 = coords[1]; y1 = coords[1];
...@@ -213,13 +214,17 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -213,13 +214,17 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
{ {
double tx = sg2d.transform.getTranslateX(); double tx = sg2d.transform.getTranslateX();
double ty = sg2d.transform.getTranslateY(); double ty = sg2d.transform.getTranslateY();
x1 += tx; x1 = ux1 + tx;
y1 += ty; y1 = uy1 + ty;
x2 += tx; x2 = ux2 + tx;
y2 += ty; y2 = uy2 + ty;
} }
break; break;
case SunGraphics2D.TRANSFORM_ISIDENT: case SunGraphics2D.TRANSFORM_ISIDENT:
x1 = ux1;
y1 = uy1;
x2 = ux2;
y2 = uy2;
break; break;
default: default:
throw new InternalError("unknown TRANSFORM state..."); throw new InternalError("unknown TRANSFORM state...");
...@@ -279,7 +284,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -279,7 +284,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
dx += udx; dx += udx;
dy += udy; dy += udy;
} }
outrenderer.fillParallelogram(sg2d, px, py, -udy, udx, dx, dy); outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
px, py, -udy, udx, dx, dy);
return true; return true;
} }
...@@ -313,7 +319,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -313,7 +319,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
px = newx; px = newx;
py = newy; py = newy;
} }
outrenderer.fillParallelogram(sg2d, px, py, dx1, dy1, dx2, dy2); outrenderer.fillParallelogram(sg2d, rx, ry, rx+rw, ry+rh,
px, py, dx1, dy1, dx2, dy2);
} }
public void drawRectangle(SunGraphics2D sg2d, public void drawRectangle(SunGraphics2D sg2d,
...@@ -360,10 +367,12 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -360,10 +367,12 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
// entire hole in the middle of the parallelogram // entire hole in the middle of the parallelogram
// so we can just fill the outer parallelogram. // so we can just fill the outer parallelogram.
fillOuterParallelogram(sg2d, fillOuterParallelogram(sg2d,
rx, ry, rx+rw, ry+rh,
px, py, dx1, dy1, dx2, dy2, px, py, dx1, dy1, dx2, dy2,
len1, len2, lw1, lw2); len1, len2, lw1, lw2);
} else { } else {
outrenderer.drawParallelogram(sg2d, outrenderer.drawParallelogram(sg2d,
rx, ry, rx+rw, ry+rh,
px, py, dx1, dy1, dx2, dy2, px, py, dx1, dy1, dx2, dy2,
lw1 / len1, lw2 / len2); lw1 / len1, lw2 / len2);
} }
...@@ -377,6 +386,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -377,6 +386,8 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
* and issues a single fillParallelogram request to fill it. * and issues a single fillParallelogram request to fill it.
*/ */
public void fillOuterParallelogram(SunGraphics2D sg2d, public void fillOuterParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double px, double py, double px, double py,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
...@@ -412,6 +423,7 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter ...@@ -412,6 +423,7 @@ public class PixelToParallelogramConverter extends PixelToShapeConverter
dx2 += udx2; dx2 += udx2;
dy2 += udy2; dy2 += udy2;
outrenderer.fillParallelogram(sg2d, px, py, dx1, dy1, dx2, dy2); outrenderer.fillParallelogram(sg2d, ux1, uy1, ux2, uy2,
px, py, dx1, dy1, dx2, dy2);
} }
} }
...@@ -2889,10 +2889,6 @@ public class BidiBase { ...@@ -2889,10 +2889,6 @@ public class BidiBase {
verifyValidPara(); verifyValidPara();
verifyRange(start, 0, limit); verifyRange(start, 0, limit);
verifyRange(limit, 0, length+1); verifyRange(limit, 0, length+1);
if (getParagraphIndex(start) != getParagraphIndex(limit - 1)) {
/* the line crosses a paragraph boundary */
throw new IllegalArgumentException();
}
return BidiLine.setLine(bidi, this, newBidi, newBidiBase, start, limit); return BidiLine.setLine(bidi, this, newBidi, newBidiBase, start, limit);
} }
......
...@@ -48,7 +48,7 @@ class XRobotPeer implements RobotPeer { ...@@ -48,7 +48,7 @@ class XRobotPeer implements RobotPeer {
} }
public void dispose() { public void dispose() {
_dispose(); // does nothing
} }
public void mouseMove(int x, int y) { public void mouseMove(int x, int y) {
...@@ -88,7 +88,6 @@ class XRobotPeer implements RobotPeer { ...@@ -88,7 +88,6 @@ class XRobotPeer implements RobotPeer {
} }
private static native synchronized void setup(int numberOfButtons, int[] buttonDownMasks); private static native synchronized void setup(int numberOfButtons, int[] buttonDownMasks);
private static native synchronized void _dispose();
private static native synchronized void mouseMoveImpl(X11GraphicsConfig xgc, int x, int y); private static native synchronized void mouseMoveImpl(X11GraphicsConfig xgc, int x, int y);
private static native synchronized void mousePressImpl(int buttons); private static native synchronized void mousePressImpl(int buttons);
......
...@@ -48,28 +48,12 @@ ...@@ -48,28 +48,12 @@
#ifdef __linux__ #ifdef __linux__
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#include <dlfcn.h>
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
static jint * masks; static jint * masks;
static jint num_buttons; static jint num_buttons;
static unsigned int s_robotInstanceCounter = 0;
static void* xcompositeLibHandle = NULL;
static Bool xcompositeExtAvailable = False;
static Bool xcompositeExtTested = False;
typedef Status (*T_XCompositeQueryVersion)(Display *dpy, int *major_versionp, int *minor_versionp);
typedef Window (*T_XCompositeGetOverlayWindow)(Display *dpy, Window window);
typedef void (*T_XCompositeReleaseOverlayWindow)(Display *dpy, Window window);
static T_XCompositeQueryVersion XCompositeQueryVersion = NULL;
static T_XCompositeGetOverlayWindow XCompositeGetOverlayWindow = NULL;
static T_XCompositeReleaseOverlayWindow XCompositeReleaseOverlayWindow = NULL;
static int32_t isXTestAvailable() { static int32_t isXTestAvailable() {
int32_t major_opcode, first_event, first_error; int32_t major_opcode, first_event, first_error;
int32_t event_basep, error_basep, majorp, minorp; int32_t event_basep, error_basep, majorp, minorp;
...@@ -210,80 +194,8 @@ Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButton ...@@ -210,80 +194,8 @@ Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButton
} }
AWT_UNLOCK(); AWT_UNLOCK();
s_robotInstanceCounter++;
} }
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer__1dispose (JNIEnv * env, jclass cls)
{
if (--s_robotInstanceCounter) {
return;
}
// This is the last instance of the XRobotPeer being released
if (xcompositeExtTested && xcompositeExtAvailable && xcompositeLibHandle) {
// The lib is loaded in IsXCompositeAvailable(). Unload under AWT_LOCK
// so that the shutdown function of the lib behaves correctly.
AWT_LOCK();
dlclose(xcompositeLibHandle);
AWT_UNLOCK();
}
xcompositeExtTested = False;
xcompositeExtAvailable = False;
xcompositeLibHandle = NULL;
}
/*
* Returns True only if XCOMPOSITE is of version 0.3 or higher.
* The functions that we need are available since that version.
*
* Must be invoked under AWT_LOCK.
*
* Leaves the library loaded if the version is correct.
*/
static Bool IsXCompositeAvailable()
{
if (!xcompositeExtTested) {
int opcode, eventb, errorb;
if (XQueryExtension(awt_display, "Composite", &opcode, &eventb, &errorb)) {
xcompositeLibHandle = dlopen("libXcomposite.so.1", RTLD_LAZY | RTLD_GLOBAL);
#ifndef __linux__ /* SOLARIS */
if (xcompositeLibHandle == NULL) {
xcompositeLibHandle = dlopen("/usr/sfw/lib/libXcomposite.so.1",
RTLD_LAZY | RTLD_GLOBAL);
}
#endif
if (xcompositeLibHandle) {
int major, minor;
XCompositeQueryVersion = (T_XCompositeQueryVersion)dlsym(xcompositeLibHandle, "XCompositeQueryVersion");
if (XCompositeQueryVersion && XCompositeQueryVersion(awt_display, &major, &minor)) {
if (major >= 0 && minor >= 3) {
XCompositeGetOverlayWindow = (T_XCompositeGetOverlayWindow)dlsym(xcompositeLibHandle, "XCompositeGetOverlayWindow");
XCompositeReleaseOverlayWindow = (T_XCompositeReleaseOverlayWindow)dlsym(xcompositeLibHandle, "XCompositeReleaseOverlayWindow");
if (XCompositeGetOverlayWindow && XCompositeReleaseOverlayWindow) {
xcompositeExtAvailable = True;
}
}
}
if (!xcompositeExtAvailable) {
dlclose(xcompositeLibHandle);
} /* else the lib is unloaded in _dispose() */
}
}
xcompositeExtTested = True;
}
return xcompositeExtAvailable;
}
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
...@@ -299,7 +211,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, ...@@ -299,7 +211,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
jint *ary; /* Array of jints for sending pixel values back jint *ary; /* Array of jints for sending pixel values back
* to parent process. * to parent process.
*/ */
Window window; Window rootWindow;
AwtGraphicsConfigDataPtr adata; AwtGraphicsConfigDataPtr adata;
DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray); DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray);
...@@ -316,24 +228,14 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, ...@@ -316,24 +228,14 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData); adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
DASSERT(adata != NULL); DASSERT(adata != NULL);
window = XRootWindow(awt_display, adata->awt_visInfo.screen); rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
image = getWindowImage(awt_display, rootWindow, x, y, width, height);
if (IsXCompositeAvailable()) {
// Use 'composite overlay window' instead of the root window.
// See 6903034 for details.
window = XCompositeGetOverlayWindow(awt_display, window);
}
image = getWindowImage(awt_display, window, x, y, width, height);
/* Array to use to crunch around the pixel values */ /* Array to use to crunch around the pixel values */
ary = (jint *) malloc(width * height * sizeof (jint)); ary = (jint *) malloc(width * height * sizeof (jint));
if (ary == NULL) { if (ary == NULL) {
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
XDestroyImage(image); XDestroyImage(image);
if (IsXCompositeAvailable()) {
XCompositeReleaseOverlayWindow(awt_display, window);
}
AWT_UNLOCK(); AWT_UNLOCK();
return; return;
} }
...@@ -354,9 +256,6 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, ...@@ -354,9 +256,6 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
free(ary); free(ary);
XDestroyImage(image); XDestroyImage(image);
if (IsXCompositeAvailable()) {
XCompositeReleaseOverlayWindow(awt_display, window);
}
AWT_UNLOCK(); AWT_UNLOCK();
} }
......
...@@ -107,10 +107,18 @@ class WFramePeer extends WWindowPeer implements FramePeer { ...@@ -107,10 +107,18 @@ class WFramePeer extends WWindowPeer implements FramePeer {
Rectangle currentDevBounds = currentDevGC.getBounds(); Rectangle currentDevBounds = currentDevGC.getBounds();
Rectangle primaryDevBounds = primaryDevGC.getBounds(); Rectangle primaryDevBounds = primaryDevGC.getBounds();
boolean isCurrentDevLarger =
((currentDevBounds.width - primaryDevBounds.width > 0) ||
(currentDevBounds.height - primaryDevBounds.height > 0));
// the window manager doesn't seem to compensate for differences when
// the primary monitor is larger than the monitor that display the window
if (isCurrentDevLarger) {
b.width -= (currentDevBounds.width - primaryDevBounds.width); b.width -= (currentDevBounds.width - primaryDevBounds.width);
b.height -= (currentDevBounds.height - primaryDevBounds.height); b.height -= (currentDevBounds.height - primaryDevBounds.height);
} }
} }
}
@Override @Override
public boolean updateGraphicsData(GraphicsConfiguration gc) { public boolean updateGraphicsData(GraphicsConfiguration gc) {
......
...@@ -102,15 +102,20 @@ class D3DRenderer extends BufferedRenderPipe { ...@@ -102,15 +102,20 @@ class D3DRenderer extends BufferedRenderPipe {
final ParallelogramPipe realpipe = d3dr.getAAParallelogramPipe(); final ParallelogramPipe realpipe = d3dr.getAAParallelogramPipe();
return new ParallelogramPipe() { return new ParallelogramPipe() {
public void fillParallelogram(SunGraphics2D sg2d, public void fillParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
{ {
GraphicsPrimitive.tracePrimitive("D3DFillAAParallelogram"); GraphicsPrimitive.tracePrimitive("D3DFillAAParallelogram");
realpipe.fillParallelogram(sg2d, realpipe.fillParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2); x, y, dx1, dy1, dx2, dy2);
} }
public void drawParallelogram(SunGraphics2D sg2d, public void drawParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
...@@ -118,6 +123,7 @@ class D3DRenderer extends BufferedRenderPipe { ...@@ -118,6 +123,7 @@ class D3DRenderer extends BufferedRenderPipe {
{ {
GraphicsPrimitive.tracePrimitive("D3DDrawAAParallelogram"); GraphicsPrimitive.tracePrimitive("D3DDrawAAParallelogram");
realpipe.drawParallelogram(sg2d, realpipe.drawParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2, x, y, dx1, dy1, dx2, dy2,
lw1, lw2); lw1, lw2);
} }
...@@ -167,21 +173,29 @@ class D3DRenderer extends BufferedRenderPipe { ...@@ -167,21 +173,29 @@ class D3DRenderer extends BufferedRenderPipe {
d3dr.fillSpans(sg2d, si, transx, transy); d3dr.fillSpans(sg2d, si, transx, transy);
} }
public void fillParallelogram(SunGraphics2D sg2d, public void fillParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2) double dx2, double dy2)
{ {
GraphicsPrimitive.tracePrimitive("D3DFillParallelogram"); GraphicsPrimitive.tracePrimitive("D3DFillParallelogram");
d3dr.fillParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2); d3dr.fillParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2);
} }
public void drawParallelogram(SunGraphics2D sg2d, public void drawParallelogram(SunGraphics2D sg2d,
double ux1, double uy1,
double ux2, double uy2,
double x, double y, double x, double y,
double dx1, double dy1, double dx1, double dy1,
double dx2, double dy2, double dx2, double dy2,
double lw1, double lw2) double lw1, double lw2)
{ {
GraphicsPrimitive.tracePrimitive("D3DDrawParallelogram"); GraphicsPrimitive.tracePrimitive("D3DDrawParallelogram");
d3dr.drawParallelogram(sg2d, x, y, dx1, dy1, dx2, dy2, lw1, lw2); d3dr.drawParallelogram(sg2d,
ux1, uy1, ux2, uy2,
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
} }
public void copyArea(SunGraphics2D sg2d, public void copyArea(SunGraphics2D sg2d,
int x, int y, int w, int h, int dx, int dy) int x, int y, int w, int h, int dx, int dy)
......
...@@ -192,6 +192,14 @@ void D3DPipelineManager::NotifyAdapterEventListeners(UINT adapter, ...@@ -192,6 +192,14 @@ void D3DPipelineManager::NotifyAdapterEventListeners(UINT adapter,
pMgr = D3DPipelineManager::GetInstance(); pMgr = D3DPipelineManager::GetInstance();
RETURN_IF_NULL(pMgr); RETURN_IF_NULL(pMgr);
hMon = pMgr->pd3d9->GetAdapterMonitor(adapter); hMon = pMgr->pd3d9->GetAdapterMonitor(adapter);
/*
* If we don't have devices initialized yet, no sense to clear them.
*/
if (!Devices::GetInstance()){
return;
}
gdiScreen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hMon); gdiScreen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hMon);
JNU_CallStaticMethodByName(env, NULL, JNU_CallStaticMethodByName(env, NULL,
......
...@@ -36,6 +36,7 @@ class AwtWin32GraphicsDevice; ...@@ -36,6 +36,7 @@ class AwtWin32GraphicsDevice;
class Devices { class Devices {
public: public:
static Devices* GetInstance();
static BOOL UpdateInstance(JNIEnv *env); static BOOL UpdateInstance(JNIEnv *env);
int GetNumDevices() { return numDevices; } int GetNumDevices() { return numDevices; }
AwtWin32GraphicsDevice* GetDeviceReference(int index, BOOL adjust = TRUE); AwtWin32GraphicsDevice* GetDeviceReference(int index, BOOL adjust = TRUE);
...@@ -59,7 +60,6 @@ friend class InstanceAccess; ...@@ -59,7 +60,6 @@ friend class InstanceAccess;
private: private:
Devices(int numElements); Devices(int numElements);
void AddReference(); void AddReference();
static Devices* GetInstance();
AwtWin32GraphicsDevice** devices; AwtWin32GraphicsDevice** devices;
int refCount; int refCount;
......
...@@ -396,6 +396,12 @@ LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message, ...@@ -396,6 +396,12 @@ LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message,
DASSERT(::IsWindow(hwnd)); DASSERT(::IsWindow(hwnd));
// This branch is required for the proper work of AwtComponent::GetComponent() method
// while hovering drop-down list
if (message == WmAwtIsComponent) {
return (LRESULT)TRUE;
}
switch (message) { switch (message) {
case WM_LBUTTONDOWN: { case WM_LBUTTONDOWN: {
DWORD curPos = ::GetMessagePos(); DWORD curPos = ::GetMessagePos();
......
...@@ -364,7 +364,6 @@ AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) { ...@@ -364,7 +364,6 @@ AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) {
AwtComponent *component = AwtComponent *component =
(AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA); (AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) ); DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) );
DASSERT(!component || component->GetHWnd() == hWnd );
return component; return component;
} }
......
...@@ -344,17 +344,6 @@ LRESULT AwtFrame::ProxyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, Ms ...@@ -344,17 +344,6 @@ LRESULT AwtFrame::ProxyWindowProc(UINT message, WPARAM wParam, LPARAM lParam, Ms
SetImeTargetComponent(NULL); SetImeTargetComponent(NULL);
} }
break; break;
// TODO: when a Choice's list is dropped down and we're scrolling in
// the list WM_MOUSEWHEEL messages come to the poxy, not to the list. Why?
case WM_MOUSEWHEEL:
focusOwner = AwtComponent::GetComponent(sm_focusOwner);
if (focusOwner != NULL &&
focusOwner != this) // avoid recursive calls
{
retValue = focusOwner->WindowProc(message, wParam, lParam);
mr = mrConsume;
}
break;
case WM_SETFOCUS: case WM_SETFOCUS:
if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain if (sm_inSynthesizeFocus) break; // pass it up the WindowProc chain
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
@bug 7036669 @bug 7036669
@summary Test Component.revalidate() method @summary Test Component.revalidate() method
@author anthony.petrov@oracle.com: area=awt.component @author anthony.petrov@oracle.com: area=awt.component
@run main Revalidate @run main/othervm -Djava.awt.smartInvalidate=true Revalidate
*/ */
import java.awt.*; import java.awt.*;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
@bug 6852592 @bug 6852592
@summary invalidate() must stop when it encounters a validate root @summary invalidate() must stop when it encounters a validate root
@author anthony.petrov@sun.com @author anthony.petrov@sun.com
@run main InvalidateMustRespectValidateRoots @run main/othervm -Djava.awt.smartInvalidate=true InvalidateMustRespectValidateRoots
*/ */
import javax.swing.*; import javax.swing.*;
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 7043054
* @summary Verifies that Paint objects receive the appropriate user space
* bounds in their createContext() method
* @run main PgramUserBoundsTest
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.RenderingHints;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
public class PgramUserBoundsTest {
static final int MinX = 10;
static final int MinY = 20;
static final int MaxX = 30;
static final int MaxY = 50;
static AffineTransform identity = new AffineTransform();
public static void main(String argv[]) {
BufferedImage bimg =
new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bimg.createGraphics();
g2d.setPaint(new BoundsCheckerPaint(MinX, MinY, MaxX, MaxY));
testAll(g2d);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
testAll(g2d);
}
static void testAll(Graphics2D g2d) {
g2d.setTransform(identity);
g2d.translate(100, 100);
testPrimitives(g2d);
g2d.setTransform(identity);
g2d.scale(10, 10);
testPrimitives(g2d);
g2d.setTransform(identity);
g2d.rotate(Math.PI/6);
testPrimitives(g2d);
}
static void testPrimitives(Graphics2D g2d) {
testLine(g2d);
testRect(g2d);
}
static void testLine(Graphics2D g2d) {
testLine(g2d, MinX, MinY, MaxX, MaxY);
testLine(g2d, MaxX, MinY, MinX, MaxY);
testLine(g2d, MinX, MaxY, MaxX, MinY);
testLine(g2d, MaxX, MaxY, MinX, MinY);
}
static void testRect(Graphics2D g2d) {
g2d.fillRect(MinX, MinY, MaxX - MinX, MaxY - MinY);
g2d.fill(new Rectangle(MinX, MinY, MaxX - MinX, MaxY - MinY));
}
static void testLine(Graphics2D g2d, int x1, int y1, int x2, int y2) {
g2d.drawLine(x1, y1, x2, y2);
g2d.draw(new Line2D.Double(x1, y1, x2, y2));
}
static class BoundsCheckerPaint implements Paint {
private Color c = Color.WHITE;
private Rectangle2D expectedBounds;
public BoundsCheckerPaint(double x1, double y1,
double x2, double y2)
{
expectedBounds = new Rectangle2D.Double();
expectedBounds.setFrameFromDiagonal(x1, y1, x2, y2);
}
public int getTransparency() {
return c.getTransparency();
}
public PaintContext createContext(ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform xform,
RenderingHints hints)
{
System.out.println("user bounds = "+userBounds);
if (!userBounds.equals(expectedBounds)) {
throw new RuntimeException("bounds fail to match");
}
return c.createContext(cm, deviceBounds, userBounds, xform, hints);
}
}
}
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 7040717 6522514
* @summary Verifies that subclasses of Arc2D can be serialized.
* @run main SerializationTest
*/
import java.awt.geom.Rectangle2D;
import java.awt.geom.Arc2D;
import java.io.Serializable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializationTest {
static boolean failed;
public static void main(String args[]) {
test(new Arc());
test(new ArcF());
test(new ArcD());
if (failed) throw new RuntimeException("some tests failed");
}
public static void test(Object a) {
try {
File objectbin = new File("object.bin");
FileOutputStream fos = new FileOutputStream(objectbin);
ObjectOutputStream out = new ObjectOutputStream(fos);
out.writeObject(a);
fos.close();
FileInputStream fis = new FileInputStream(objectbin);
ObjectInputStream in = new ObjectInputStream(fis);
Object o = in.readObject();
fis.close();
System.err.println(o);
} catch (Throwable ex) {
ex.printStackTrace();
failed = true;
}
}
static class Arc extends Arc2D implements Serializable {
public Arc() {
super(Arc2D.OPEN);
}
public Rectangle2D makeBounds(double x, double y, double w, double h) {
return new Rectangle2D.Double(x, y, w, h);
}
public double getX() { return 0; }
public double getY() { return 0; }
public double getWidth() { return 0; }
public double getHeight() { return 0; }
public double getAngleExtent() { return 0; }
public double getAngleStart() { return 0; }
public void setAngleExtent(double angExt) { }
public void setAngleStart(double angExt) { }
public void setFrame(double x, double y, double w, double h) {}
public void setArc(double x, double y, double w, double h,
double s, double e, int c)
{
}
public boolean isEmpty() { return false; };
}
static class ArcF extends Arc2D.Float implements Serializable {
public ArcF() {
}
}
static class ArcD extends Arc2D.Double implements Serializable {
public ArcD() {
}
}
}
此差异已折叠。
...@@ -170,8 +170,8 @@ assert(s.equals("savvy")); ...@@ -170,8 +170,8 @@ assert(s.equals("savvy"));
mt = MethodType.methodType(java.util.List.class, Object[].class); mt = MethodType.methodType(java.util.List.class, Object[].class);
mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
assert(mh.isVarargsCollector()); assert(mh.isVarargsCollector());
x = mh.invokeGeneric("one", "two"); x = mh.invoke("one", "two");
// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; // invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
assert(x.equals(java.util.Arrays.asList("one","two"))); assert(x.equals(java.util.Arrays.asList("one","two")));
// mt is (Object,Object,Object)Object // mt is (Object,Object,Object)Object
mt = MethodType.genericMethodType(3); mt = MethodType.genericMethodType(3);
...@@ -199,12 +199,12 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -199,12 +199,12 @@ mh.invokeExact(System.out, "Hello, world.");
MethodHandle asList = publicLookup() MethodHandle asList = publicLookup()
.findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)) .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
.asVarargsCollector(Object[].class); .asVarargsCollector(Object[].class);
assertEquals("[]", asList.invokeGeneric().toString()); assertEquals("[]", asList.invoke().toString());
assertEquals("[1]", asList.invokeGeneric(1).toString()); assertEquals("[1]", asList.invoke(1).toString());
assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString()); assertEquals("[two, too]", asList.invoke("two", "too").toString());
Object[] argv = { "three", "thee", "tee" }; Object[] argv = { "three", "thee", "tee" };
assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString()); assertEquals("[three, thee, tee]", asList.invoke(argv).toString());
List ls = (List) asList.invokeGeneric((Object)argv); List ls = (List) asList.invoke((Object)argv);
assertEquals(1, ls.size()); assertEquals(1, ls.size());
assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0))); assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
}} }}
...@@ -218,9 +218,9 @@ MethodHandle vamh = publicLookup() ...@@ -218,9 +218,9 @@ MethodHandle vamh = publicLookup()
.asVarargsCollector(Object[].class); .asVarargsCollector(Object[].class);
MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh); MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
assert(vamh.type().equals(mh.type())); assert(vamh.type().equals(mh.type()));
assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString()); assertEquals("[1, 2, 3]", vamh.invoke(1,2,3).toString());
boolean failed = false; boolean failed = false;
try { mh.invokeGeneric(1,2,3); } try { mh.invoke(1,2,3); }
catch (WrongMethodTypeException ex) { failed = true; } catch (WrongMethodTypeException ex) { failed = true; }
assert(failed); assert(failed);
{} {}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
/* /*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2011 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,9 +24,17 @@ ...@@ -24,9 +24,17 @@
/* @test /* @test
@bug 6788484 @bug 6788484
@summary NPE in DefaultTableCellHeaderRenderer.getColumnSortOrder() with null table @summary NPE in DefaultTableCellHeaderRenderer.getColumnSortOrder() with null table
@compile -XDignore.symbol.file=true bug6788484.java
@author Alexander Potochkin @author Alexander Potochkin
@run main bug6788484 @run main bug6788484
*/ */
/*
* Compile with -XDignore.symbol.file=true option as a workaround for
* specific behaviour described in 6380059 which restricts proprietary
* package loading
*/
import sun.swing.table.DefaultTableCellHeaderRenderer; import sun.swing.table.DefaultTableCellHeaderRenderer;
import javax.swing.*; import javax.swing.*;
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册