This fixes a locking problem in Component.getFont() as stated in the
corresponding bug report. It seems OK to rely on the checks in
getFontImpl(). In the worst case (when the structure is modified in
between) we end up with a font of null, which would be the case anyway.
This seems to avoid a deadlock in IKVM.

Together with this patch goes in the last AWT patch which I obviously
forgot to commit. Sorry for this inconvenience.

2007-01-04  Roman Kennke  <[EMAIL PROTECTED]>

        PR 30122
        * java/awt/Component.java
        (getFont): Don't synchronize on tree lock here. The method is
        thread-safe 'enough' by fetching local variables in getFontImpl().

/Roman

Index: java/awt/AWTEvent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/AWTEvent.java,v
retrieving revision 1.19
diff -u -1 -5 -r1.19 AWTEvent.java
--- java/awt/AWTEvent.java	18 Sep 2006 12:32:31 -0000	1.19
+++ java/awt/AWTEvent.java	5 Jan 2007 22:55:21 -0000
@@ -250,33 +250,41 @@
    * @return the id number of this event
    */
   public int getID()
   {
     return id;
   }
 
   /**
    * Create a string that represents this event in the format
    * <code>classname[eventstring] on sourcecomponentname</code>.
    *
    * @return a string representing this event
    */
   public String toString ()
   {
+    String src;
+    if (source instanceof Component)
+      src = ((Component) source).getName();
+    else if (source instanceof MenuComponent)
+      src = ((MenuComponent) source).getName();
+    else if (source != null)
+      src = source.toString();
+    else
+      src = "null";
     String string = getClass ().getName () + "[" + paramString () + "] on "
-    + source;
-
+                    + src;
     return string;
   }
 
   /**
    * Returns a string representation of the state of this event. It may be
    * empty, but must not be null; it is implementation defined.
    *
    * @return a string representation of this event
    */
   public String paramString()
   {
     return "";
   }
 
   /**
Index: java/awt/Component.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Component.java,v
retrieving revision 1.153
diff -u -1 -5 -r1.153 Component.java
--- java/awt/Component.java	10 Dec 2006 20:25:43 -0000	1.153
+++ java/awt/Component.java	5 Jan 2007 22:55:23 -0000
@@ -811,31 +811,32 @@
   public boolean isVisible()
   {
     return visible;
   }
 
   /**
    * Tests whether or not this component is actually being shown on
    * the screen. This will be true if and only if it this component is
    * visible and its parent components are all visible.
    *
    * @return true if the component is showing on the screen
    * @see #setVisible(boolean)
    */
   public boolean isShowing()
   {
-    return visible && peer != null && (parent == null || parent.isShowing());
+    Component par = parent;
+    return visible && peer != null && (par == null || par.isShowing());
   }
 
   /**
    * Tests whether or not this component is enabled. Components are enabled
    * by default, and must be enabled to receive user input or generate events.
    *
    * @return true if the component is enabled
    * @see #setEnabled(boolean)
    */
   public boolean isEnabled()
   {
     return enabled;
   }
 
   /**
@@ -1167,43 +1168,36 @@
    */
   public boolean isBackgroundSet()
   {
     return background != null;
   }
 
   /**
    * Returns the font in use for this component. If not set, this is inherited
    * from the parent.
    *
    * @return the font for this component
    * @see #setFont(Font)
    */
   public Font getFont()
   {
-    Font f;
-    synchronized (getTreeLock())
-      {
-        f = getFontImpl();
-      }
-    return f;
+    return getFontImpl();
   }
 
   /**
    * Implementation of getFont(). This is pulled out of getFont() to prevent
-   * client programs from overriding this. This method is executed within
-   * a tree lock, so we can assume that the hierarchy doesn't change in
-   * between.
+   * client programs from overriding this.
    *
    * @return the font of this component
    */
   private final Font getFontImpl()
   {
     Font f = font;
     if (f == null)
       {
         Component p = parent;
         if (p != null)
           f = p.getFontImpl();
         else
           f = new Font("Dialog", Font.PLAIN, 12);
       }
     return f;
Index: java/awt/EventDispatchThread.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/EventDispatchThread.java,v
retrieving revision 1.11
diff -u -1 -5 -r1.11 EventDispatchThread.java
--- java/awt/EventDispatchThread.java	26 Jul 2006 19:09:50 -0000	1.11
+++ java/awt/EventDispatchThread.java	5 Jan 2007 22:55:23 -0000
@@ -61,30 +61,33 @@
     int priority = DEFAULT_PRIORITY;
     try
       {
         String priorityString =
           System.getProperty("gnu.awt.dispatchthread.priority");
         if (priorityString != null)
           {
             priority = Integer.parseInt(priorityString); 
           }      
       }
     catch (NumberFormatException ex)
       {
         // Ignore and use default.
       }
     setPriority(priority);
+
+    // Make sure that an event dispatch thread is never a daemon thread.
+    setDaemon(false);
   }
 
   public void run()
   {
     while (true)
       {
         try
 	{
 	  AWTEvent evt = queue.getNextEvent();
           queue.dispatchEvent(evt);
 	}
         catch (ThreadDeath death)
         {
           // If someone wants to kill us, let them.
           return;
Index: java/awt/image/IndexColorModel.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/image/IndexColorModel.java,v
retrieving revision 1.18
diff -u -1 -5 -r1.18 IndexColorModel.java
--- java/awt/image/IndexColorModel.java	22 Nov 2006 15:18:32 -0000	1.18
+++ java/awt/image/IndexColorModel.java	5 Jan 2007 22:55:24 -0000
@@ -122,31 +122,31 @@
   public IndexColorModel(int bits, int size, byte[] reds, byte[] greens,
                          byte[] blues, int trans)
   {
     super(bits, nArray(8, (0 <= trans && trans < size) ? 4 : 3), 
         ColorSpace.getInstance(ColorSpace.CS_sRGB), 
         (0 <= trans && trans < size),  // hasAlpha 
         false, OPAQUE, 
         Buffers.smallestAppropriateTransferType(bits)); 
     if (bits < 1) 
       throw new IllegalArgumentException("bits < 1");
     if (bits > 16)
       throw new IllegalArgumentException("bits > 16");
     if (size < 1)
       throw new IllegalArgumentException("size < 1");
     map_size = size;
-    rgb = new int[size];
+    rgb = createColorMap(bits, size);
     for (int i = 0; i < size; i++)
       {
         rgb[i] = (0xff000000
                   | ((reds[i] & 0xff) << 16)
                   | ((greens[i] & 0xff) << 8)
                   | (blues[i] & 0xff));
       }
 
     setTransparentPixel(trans);
 
     // Generate a bigint with 1's for every pixel
     validBits = validBits.setBit(size).subtract(BigInteger.ONE);
   }
 
   /**
@@ -175,31 +175,31 @@
                          byte[] blues, byte[] alphas)
   {
     super(bits, nArray(8, (alphas == null ? 3 : 4)), 
         ColorSpace.getInstance(ColorSpace.CS_sRGB), 
         (alphas != null), false, TRANSLUCENT, 
         Buffers.smallestAppropriateTransferType(bits)); 
     if (bits < 1) 
       throw new IllegalArgumentException("bits < 1");
     if (bits > 16)
       throw new IllegalArgumentException("bits > 16");
     if (size < 1)
       throw new IllegalArgumentException("size < 1");
     map_size = size;
     opaque = (alphas == null);
 
-    rgb = new int[size];
+    rgb = createColorMap(bits, size);
     if (alphas == null)
       {
         for (int i = 0; i < size; i++)
           {
             rgb[i] = (0xff000000
                       | ((reds[i] & 0xff) << 16)
                       | ((greens[i] & 0xff) << 8)
                       | (blues[i] & 0xff));
           }
         transparency = OPAQUE;
       }
     else
       {
 	byte alphaZero = (byte) 0x00;
         byte alphaOne = (byte) 0xFF;
@@ -263,31 +263,31 @@
                          boolean hasAlpha, int trans)
   {
     super(bits, nArray(8, hasAlpha || (0 <= trans && trans < size) ? 4 : 3), 
         ColorSpace.getInstance(ColorSpace.CS_sRGB),
         hasAlpha || (0 <= trans && trans < size), false, OPAQUE, 
         Buffers.smallestAppropriateTransferType(bits));
     if (bits < 1)
       throw new IllegalArgumentException("bits < 1");
     if (bits > 16)
       throw new IllegalArgumentException("bits > 16");
     if (size < 1)
       throw new IllegalArgumentException("size < 1");
     map_size = size;
     opaque = !hasAlpha;
 
-    rgb = new int[size];
+    rgb = createColorMap(bits, size);
     if (hasAlpha)
     {
       int alpha;
       int alphaZero = 0x00;  // use to detect all zeros
       int alphaOne = 0xff;   // use to detect all ones
       for (int i = 0; i < size; i++) {
 	alpha = cmap[4 * i + 3 + start] & 0xff;  
         alphaZero = alphaZero | alpha;
         alphaOne = alphaOne & alpha;
         rgb[i] =
 	  ( alpha << 24
 	   // red
 	   | ((cmap[4 * i + start] & 0xff) << 16)
 	   // green
 	   | ((cmap[4 * i + 1 + start] & 0xff) << 8)
@@ -348,31 +348,31 @@
     super(bits, 
 	  nArray(8, 4), // bits for each channel
 	  ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB
 	  true, // has alpha
 	  false, // not premultiplied
 	  TRANSLUCENT, transferType);
     if (transferType != DataBuffer.TYPE_BYTE
         && transferType != DataBuffer.TYPE_USHORT)
       throw new IllegalArgumentException();
     if (bits > 16)
       throw new IllegalArgumentException("bits > 16");
     if (size < 1)
       throw new IllegalArgumentException("size < 1");
     map_size = size;
     opaque = !hasAlpha;
-    rgb = new int[size];
+    rgb = createColorMap(bits, size);
     if (!hasAlpha)
       for (int i = 0; i < size; i++)
 	rgb[i] = cmap[i + start] | 0xff000000;
     else
       System.arraycopy(cmap, start, rgb, 0, size);
 
     setTransparentPixel(trans);
 
     // Generate a bigint with 1's for every pixel
     validBits = validBits.setBit(size).subtract(BigInteger.ONE);
   }
 
   /**
    * Construct an IndexColorModel using a colormap with holes.
    * <br><br>
@@ -407,31 +407,31 @@
 	  true, // has alpha
 	  false, // not premultiplied
 	  TRANSLUCENT, transferType);
     if (transferType != DataBuffer.TYPE_BYTE
         && transferType != DataBuffer.TYPE_USHORT)
       throw new IllegalArgumentException();
     if (bits > 16)
       throw new IllegalArgumentException("bits > 16");
     if (size < 1)
       throw new IllegalArgumentException("size < 1");
     map_size = size;
     opaque = false;
     this.trans = -1;
     this.validBits = validBits;
 
-    rgb = new int[size];
+    rgb = createColorMap(bits, size);
     if (!hasAlpha)
       for (int i = 0; i < size; i++)
 	rgb[i] = cmap[i + start] | 0xff000000;
     else
       System.arraycopy(cmap, start, rgb, 0, size);
   }
 
   /**
    * Returns the size of the color lookup table.
    *
    * @return The size of the color lookup table.
    */
   public final int getMapSize()
   {
     return map_size;
@@ -714,16 +714,23 @@
    * @param t the transparent pixel
    */
   private void setTransparentPixel(int t)
   {
     if (t >= 0 && t < map_size)
       {
         rgb[t] &= 0xffffff; // Make the value transparent.
         trans = t;
         if (transparency == OPAQUE)
           {
             transparency = BITMASK;
             hasAlpha = true;
           }
       }
   }
+
+  private int[] createColorMap(int bits, int size)
+  {
+    // According to a Mauve test, the RI allocates at least 256 entries here.
+    int realSize = Math.max(256, Math.max(1 << bits, size));
+    return new int[realSize];
+  }
 }

Reply via email to