From 7690c18be2a1fb727805ef0e520ba992b040268a Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 19 Jun 2008 18:03:43 +0400 Subject: [PATCH 001/289] 4114658: DOC: Unspecified behaviour for java.beans.PropertyEditorSupport Reviewed-by: peterz, loneid --- .../classes/java/beans/PropertyEditor.java | 17 ++++++------ .../java/beans/PropertyEditorSupport.java | 26 ++++++++++++++----- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/jdk/src/share/classes/java/beans/PropertyEditor.java b/jdk/src/share/classes/java/beans/PropertyEditor.java index b6ddf415354..965775898a8 100644 --- a/jdk/src/share/classes/java/beans/PropertyEditor.java +++ b/jdk/src/share/classes/java/beans/PropertyEditor.java @@ -204,20 +204,21 @@ public interface PropertyEditor { //---------------------------------------------------------------------- /** - * Register a listener for the PropertyChange event. When a - * PropertyEditor changes its value it should fire a PropertyChange - * event on all registered PropertyChangeListeners, specifying the - * null value for the property name and itself as the source. + * Adds a listener for the value change. + * When the property editor changes its value + * it should fire a {@link PropertyChangeEvent} + * on all registered {@link PropertyChangeListener}s, + * specifying the {@code null} value for the property name + * and itself as the source. * - * @param listener An object to be invoked when a PropertyChange - * event is fired. + * @param listener the {@link PropertyChangeListener} to add */ void addPropertyChangeListener(PropertyChangeListener listener); /** - * Remove a listener for the PropertyChange event. + * Removes a listener for the value change. * - * @param listener The PropertyChange listener to be removed. + * @param listener the {@link PropertyChangeListener} to remove */ void removePropertyChangeListener(PropertyChangeListener listener); diff --git a/jdk/src/share/classes/java/beans/PropertyEditorSupport.java b/jdk/src/share/classes/java/beans/PropertyEditorSupport.java index 12f07c06bb1..57fddf04365 100644 --- a/jdk/src/share/classes/java/beans/PropertyEditorSupport.java +++ b/jdk/src/share/classes/java/beans/PropertyEditorSupport.java @@ -233,11 +233,20 @@ public class PropertyEditorSupport implements PropertyEditor { //---------------------------------------------------------------------- /** - * Register a listener for the PropertyChange event. The class will - * fire a PropertyChange value whenever the value is updated. + * Adds a listener for the value change. + * When the property editor changes its value + * it should fire a {@link PropertyChangeEvent} + * on all registered {@link PropertyChangeListener}s, + * specifying the {@code null} value for the property name. + * If the source property is set, + * it should be used as the source of the event. + *

+ * The same listener object may be added more than once, + * and will be called as many times as it is added. + * If {@code listener} is {@code null}, + * no exception is thrown and no action is taken. * - * @param listener An object to be invoked when a PropertyChange - * event is fired. + * @param listener the {@link PropertyChangeListener} to add */ public synchronized void addPropertyChangeListener( PropertyChangeListener listener) { @@ -248,9 +257,14 @@ public class PropertyEditorSupport implements PropertyEditor { } /** - * Remove a listener for the PropertyChange event. + * Removes a listener for the value change. + *

+ * If the same listener was added more than once, + * it will be notified one less time after being removed. + * If {@code listener} is {@code null}, or was never added, + * no exception is thrown and no action is taken. * - * @param listener The PropertyChange listener to be removed. + * @param listener the {@link PropertyChangeListener} to remove */ public synchronized void removePropertyChangeListener( PropertyChangeListener listener) { From 762ea5875b8d38a67aa2e524b4756fdfb02c115e Mon Sep 17 00:00:00 2001 From: Igor Kushnirskiy Date: Mon, 23 Jun 2008 15:21:37 -0400 Subject: [PATCH 002/289] 6623943: javax.swing.TimerQueue's thread occasionally fails to start Reviewed-by: alexp --- .../share/classes/javax/swing/JApplet.java | 5 +- .../share/classes/javax/swing/TimerQueue.java | 67 ++++++++++--------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/JApplet.java b/jdk/src/share/classes/javax/swing/JApplet.java index b9b5b2506b9..47f792a942d 100644 --- a/jdk/src/share/classes/javax/swing/JApplet.java +++ b/jdk/src/share/classes/javax/swing/JApplet.java @@ -131,10 +131,7 @@ public class JApplet extends Applet implements Accessible, // Check the timerQ and restart if necessary. TimerQueue q = TimerQueue.sharedInstance(); if(q != null) { - synchronized(q) { - if(!q.running) - q.start(); - } + q.startIfNeeded(); } /* Workaround for bug 4155072. The shared double buffer image diff --git a/jdk/src/share/classes/javax/swing/TimerQueue.java b/jdk/src/share/classes/javax/swing/TimerQueue.java index 2121939011f..1f694d1c820 100644 --- a/jdk/src/share/classes/javax/swing/TimerQueue.java +++ b/jdk/src/share/classes/javax/swing/TimerQueue.java @@ -31,6 +31,7 @@ package javax.swing; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.locks.*; import java.util.concurrent.atomic.AtomicLong; import sun.awt.AppContext; @@ -52,7 +53,8 @@ class TimerQueue implements Runnable new StringBuffer("TimerQueue.expiredTimersKey"); private final DelayQueue queue; - volatile boolean running; + private volatile boolean running; + private final Lock runningLock; /* Lock object used in place of class object for synchronization. * (4187686) @@ -69,7 +71,8 @@ class TimerQueue implements Runnable super(); queue = new DelayQueue(); // Now start the TimerQueue thread. - start(); + runningLock = new ReentrantLock(); + startIfNeeded(); } @@ -87,33 +90,30 @@ class TimerQueue implements Runnable } - synchronized void start() { - if (running) { - throw new RuntimeException("Can't start a TimerQueue " + - "that is already running"); - } - else { - final ThreadGroup threadGroup = - AppContext.getAppContext().getThreadGroup(); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - Thread timerThread = new Thread(threadGroup, TimerQueue.this, - "TimerQueue"); - timerThread.setDaemon(true); - timerThread.setPriority(Thread.NORM_PRIORITY); - timerThread.start(); - return null; - } - }); - running = true; + void startIfNeeded() { + if (! running) { + runningLock.lock(); + try { + final ThreadGroup threadGroup = + AppContext.getAppContext().getThreadGroup(); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + Thread timerThread = new Thread(threadGroup, TimerQueue.this, + "TimerQueue"); + timerThread.setDaemon(true); + timerThread.setPriority(Thread.NORM_PRIORITY); + timerThread.start(); + return null; + } + }); + running = true; + } finally { + runningLock.unlock(); + } } } - synchronized void stop() { - running = false; - } - void addTimer(Timer timer, long delayMillis) { timer.getLock().lock(); try { @@ -164,6 +164,7 @@ class TimerQueue implements Runnable public void run() { + runningLock.lock(); try { while (running) { try { @@ -195,14 +196,14 @@ class TimerQueue implements Runnable } } catch (ThreadDeath td) { - synchronized (this) { - running = false; - // Mark all the timers we contain as not being queued. - for (DelayedTimer delayedTimer : queue) { - delayedTimer.getTimer().cancelEvent(); - } - throw td; + // Mark all the timers we contain as not being queued. + for (DelayedTimer delayedTimer : queue) { + delayedTimer.getTimer().cancelEvent(); } + throw td; + } finally { + running = false; + runningLock.unlock(); } } From 9d7b3f41e04e5a8d75d948e22b79c49b45fde494 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 26 Jun 2008 15:11:04 +0400 Subject: [PATCH 003/289] 6718964: Swing border tests should be open source Reviewed-by: peterz --- jdk/test/javax/swing/border/Test4120351.java | 43 ++++++++++++ jdk/test/javax/swing/border/Test4124729.java | 38 ++++++++++ jdk/test/javax/swing/border/Test4243289.html | 9 +++ jdk/test/javax/swing/border/Test4243289.java | 52 ++++++++++++++ jdk/test/javax/swing/border/Test4247606.html | 10 +++ jdk/test/javax/swing/border/Test4247606.java | 62 +++++++++++++++++ jdk/test/javax/swing/border/Test4252164.html | 10 +++ jdk/test/javax/swing/border/Test4252164.java | 73 ++++++++++++++++++++ jdk/test/javax/swing/border/Test6461042.java | 57 +++++++++++++++ 9 files changed, 354 insertions(+) create mode 100644 jdk/test/javax/swing/border/Test4120351.java create mode 100644 jdk/test/javax/swing/border/Test4124729.java create mode 100644 jdk/test/javax/swing/border/Test4243289.html create mode 100644 jdk/test/javax/swing/border/Test4243289.java create mode 100644 jdk/test/javax/swing/border/Test4247606.html create mode 100644 jdk/test/javax/swing/border/Test4247606.java create mode 100644 jdk/test/javax/swing/border/Test4252164.html create mode 100644 jdk/test/javax/swing/border/Test4252164.java create mode 100644 jdk/test/javax/swing/border/Test6461042.java diff --git a/jdk/test/javax/swing/border/Test4120351.java b/jdk/test/javax/swing/border/Test4120351.java new file mode 100644 index 00000000000..1253e638a0e --- /dev/null +++ b/jdk/test/javax/swing/border/Test4120351.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4120351 + * @summary Tests that the methods createEtchedBorder(int type) and + * createEtchedBorder(int type, Color highlight, Color shadows) are added + * @author Andrey Pikalev + */ + +import java.awt.Color; +import javax.swing.BorderFactory; +import javax.swing.border.EtchedBorder; + +public class Test4120351 { + public static void main(String[] args) { + BorderFactory.createEtchedBorder(EtchedBorder.RAISED); + BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.BLACK, Color.WHITE); + BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.WHITE, Color.BLACK); + } +} diff --git a/jdk/test/javax/swing/border/Test4124729.java b/jdk/test/javax/swing/border/Test4124729.java new file mode 100644 index 00000000000..d48ce9d1d5f --- /dev/null +++ b/jdk/test/javax/swing/border/Test4124729.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4124729 + * @summary Test that constrtructor LineBorder(?,?,?) is public + * @author Andrey Pikalev + */ + +import java.awt.Color; +import javax.swing.border.LineBorder; + +public class Test4124729 { + public static void main(String[] args) { + new LineBorder(Color.BLUE, 3, true); + } +} diff --git a/jdk/test/javax/swing/border/Test4243289.html b/jdk/test/javax/swing/border/Test4243289.html new file mode 100644 index 00000000000..9133d99c582 --- /dev/null +++ b/jdk/test/javax/swing/border/Test4243289.html @@ -0,0 +1,9 @@ + + +When applet starts, you'll see a panel with a TitledBorder with title "Panel Title". +If this title is overstriken with the border line, test fails, otherwise it passes. + + + + + diff --git a/jdk/test/javax/swing/border/Test4243289.java b/jdk/test/javax/swing/border/Test4243289.java new file mode 100644 index 00000000000..1c462a85973 --- /dev/null +++ b/jdk/test/javax/swing/border/Test4243289.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4243289 + * @summary Tests that TitledBorder do not draw line through its caption + * @author Peter Zhelezniakov + * @run applet/manual=yesno Test4243289.html + */ + +import java.awt.Font; +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JPanel; +import javax.swing.border.TitledBorder; + +public class Test4243289 extends JApplet { + public void init() { + Font font = new Font("Dialog", Font.PLAIN, 12); // NON-NLS: the font name + TitledBorder border = BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(), + "Panel Title", // NON-NLS: the title of the border + TitledBorder.DEFAULT_JUSTIFICATION, + TitledBorder.DEFAULT_POSITION, + font); + + JPanel panel = new JPanel(); + panel.setBorder(border); + getContentPane().add(panel); + } +} diff --git a/jdk/test/javax/swing/border/Test4247606.html b/jdk/test/javax/swing/border/Test4247606.html new file mode 100644 index 00000000000..d501ab221d6 --- /dev/null +++ b/jdk/test/javax/swing/border/Test4247606.html @@ -0,0 +1,10 @@ + + +If the button do not fit into the titled border bounds +and cover the bottom border's line then test fails. +Otherwise test passes. + + + + + diff --git a/jdk/test/javax/swing/border/Test4247606.java b/jdk/test/javax/swing/border/Test4247606.java new file mode 100644 index 00000000000..b598d4a1b9e --- /dev/null +++ b/jdk/test/javax/swing/border/Test4247606.java @@ -0,0 +1,62 @@ +/* + * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4247606 + * @summary BorderedPane appears wrong with Title Position Below Bottom + * @author Andrey Pikalev + * @run applet/manual=yesno Test4247606.html + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + +public class Test4247606 extends JApplet { + public void init() { + JButton button = new JButton("Button"); // NON-NLS: the button text + button.setBorder(BorderFactory.createLineBorder(Color.red, 1)); + + TitledBorder border = new TitledBorder("Bordered Pane"); // NON-NLS: the panel title + border.setTitlePosition(TitledBorder.BELOW_BOTTOM); + + JPanel panel = create(button, border); + panel.setBackground(Color.green); + + getContentPane().add(create(panel, BorderFactory.createEmptyBorder(10, 10, 10, 10))); + } + + private static JPanel create(JComponent component, Border border) { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(border); + panel.add(component); + return panel; + } +} diff --git a/jdk/test/javax/swing/border/Test4252164.html b/jdk/test/javax/swing/border/Test4252164.html new file mode 100644 index 00000000000..eb436c53fe3 --- /dev/null +++ b/jdk/test/javax/swing/border/Test4252164.html @@ -0,0 +1,10 @@ + + +Please, ensure that rounded border is filled completely. +It should not contain white points inside. +Use Mouse Wheel to change thickness of the border. + + + + + diff --git a/jdk/test/javax/swing/border/Test4252164.java b/jdk/test/javax/swing/border/Test4252164.java new file mode 100644 index 00000000000..a39193fc6f9 --- /dev/null +++ b/jdk/test/javax/swing/border/Test4252164.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4252164 + * @summary Tests rounded LineBorder for components + * @author Sergey Malenkov + * @run applet/manual=yesno Test4252164.html + */ + +import java.awt.Color; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import javax.swing.JApplet; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.LineBorder; + +public class Test4252164 extends JApplet implements MouseWheelListener { + private int thickness; + private JLabel rounded; + private JLabel straight; + + public void mouseWheelMoved(MouseWheelEvent event) { + update(event.getWheelRotation()); + } + + public void init() { + add(createUI()); + addMouseWheelListener(this); + } + + private JPanel createUI() { + this.rounded = new JLabel("ROUNDED"); // NON-NLS: the label for rounded border + this.straight = new JLabel("STRAIGHT"); // NON-NLS: the label for straight border + + JPanel panel = new JPanel(); + panel.add(this.rounded); + panel.add(this.straight); + + update(10); + + return panel; + } + + private void update(int thickness) { + this.thickness += thickness; + + this.rounded.setBorder(new LineBorder(Color.RED, this.thickness, true)); + this.straight.setBorder(new LineBorder(Color.RED, this.thickness, false)); + } +} diff --git a/jdk/test/javax/swing/border/Test6461042.java b/jdk/test/javax/swing/border/Test6461042.java new file mode 100644 index 00000000000..3224b1db83e --- /dev/null +++ b/jdk/test/javax/swing/border/Test6461042.java @@ -0,0 +1,57 @@ +/* + * Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6461042 + * @summary Tests that toString() doesn't cause StackOverflowException + * when a JComponent is its own border + * @author Shannon Hickey + */ + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; +import javax.swing.JComponent; +import javax.swing.border.Border; + +public class Test6461042 extends JComponent implements Border { + public static void main(String[] args) { + new Test6461042().toString(); + } + + public Test6461042() { + setBorder(this); + } + + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + } + + public Insets getBorderInsets(Component c) { + return null; + } + + public boolean isBorderOpaque() { + return false; + } +} From ef9b3891fc4b83e611765fbc187e6ceb8510cb57 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 26 Jun 2008 15:39:12 +0400 Subject: [PATCH 004/289] 6718965: Swing color chooser tests should be open source Reviewed-by: peterz --- .../swing/JColorChooser/Test4165217.java | 78 +++++++++++++++ .../swing/JColorChooser/Test4177735.java | 95 +++++++++++++++++++ .../swing/JColorChooser/Test4193384.java | 70 ++++++++++++++ .../swing/JColorChooser/Test4234761.java | 60 ++++++++++++ .../swing/JColorChooser/Test4380468.html | 17 ++++ .../swing/JColorChooser/Test4380468.java | 40 ++++++++ .../swing/JColorChooser/Test4461329.java | 46 +++++++++ .../swing/JColorChooser/Test4711996.java | 41 ++++++++ .../swing/JColorChooser/Test4759306.html | 8 ++ .../swing/JColorChooser/Test4759306.java | 42 ++++++++ .../swing/JColorChooser/Test4759934.html | 14 +++ .../swing/JColorChooser/Test4759934.java | 80 ++++++++++++++++ .../swing/JColorChooser/Test4887836.html | 9 ++ .../swing/JColorChooser/Test4887836.java | 43 +++++++++ 14 files changed, 643 insertions(+) create mode 100644 jdk/test/javax/swing/JColorChooser/Test4165217.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4177735.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4193384.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4234761.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4380468.html create mode 100644 jdk/test/javax/swing/JColorChooser/Test4380468.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4461329.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4711996.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4759306.html create mode 100644 jdk/test/javax/swing/JColorChooser/Test4759306.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4759934.html create mode 100644 jdk/test/javax/swing/JColorChooser/Test4759934.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test4887836.html create mode 100644 jdk/test/javax/swing/JColorChooser/Test4887836.java diff --git a/jdk/test/javax/swing/JColorChooser/Test4165217.java b/jdk/test/javax/swing/JColorChooser/Test4165217.java new file mode 100644 index 00000000000..59a80e89848 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4165217.java @@ -0,0 +1,78 @@ +/* + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4165217 + * @summary Tests JColorChooser serialization + * @author Ilya Boyandin + */ + +import java.awt.Color; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Random; +import javax.swing.JColorChooser; + +public class Test4165217 { + public static void main(String[] args) { + JColorChooser chooser = new JColorChooser(); + chooser.setColor(new Color(new Random().nextInt())); + + Color before = chooser.getColor(); + Color after = copy(chooser).getColor(); + + if (!after.equals(before)) { + throw new Error("color is changed after serialization"); + } + } + + private static JColorChooser copy(JColorChooser chooser) { + try { + return (JColorChooser) deserialize(serialize(chooser)); + } + catch (ClassNotFoundException exception) { + throw new Error("unexpected exception during class creation", exception); + } + catch (IOException exception) { + throw new Error("unexpected exception during serialization", exception); + } + } + + private static byte[] serialize(Object object) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(object); + oos.flush(); + return baos.toByteArray(); + } + + private static Object deserialize(byte[] array) throws IOException, ClassNotFoundException { + ByteArrayInputStream bais = new ByteArrayInputStream(array); + ObjectInputStream ois = new ObjectInputStream(bais); + return ois.readObject(); + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4177735.java b/jdk/test/javax/swing/JColorChooser/Test4177735.java new file mode 100644 index 00000000000..b8b2d93f47e --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4177735.java @@ -0,0 +1,95 @@ +/* + * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4177735 + * @summary Tests that JColorChooser leaves no threads when disposed + * @author Shannon Hickey + */ + +import java.awt.Point; +import javax.swing.JColorChooser; +import javax.swing.JDialog; +import javax.swing.SwingUtilities; +import javax.swing.colorchooser.AbstractColorChooserPanel; + +public class Test4177735 implements Runnable { + private static final long DELAY = 1000L; + + public static void main(String[] args) throws Exception { + JColorChooser chooser = new JColorChooser(); + AbstractColorChooserPanel[] panels = chooser.getChooserPanels(); + chooser.setChooserPanels(new AbstractColorChooserPanel[] { panels[1] }); + + JDialog dialog = show(chooser); + pause(DELAY); + + dialog.dispose(); + pause(DELAY); + + Test4177735 test = new Test4177735(); + SwingUtilities.invokeAndWait(test); + if (test.count != 0) { + throw new Error("JColorChooser leaves " + test.count + " threads running"); + } + } + + static JDialog show(JColorChooser chooser) { + JDialog dialog = JColorChooser.createDialog(null, null, false, chooser, null, null); + dialog.setVisible(true); + // block till displayed + Point point = null; + while (point == null) { + try { + point = dialog.getLocationOnScreen(); + } + catch (IllegalStateException exception) { + pause(DELAY); + } + } + return dialog; + } + + private static void pause(long delay) { + try { + Thread.sleep(delay); + } + catch (InterruptedException exception) { + } + } + + private int count; + + public void run() { + ThreadGroup group = Thread.currentThread().getThreadGroup(); + Thread[] threads = new Thread[group.activeCount()]; + int count = group.enumerate(threads, false); + for (int i = 0; i < count; i++) { + String name = threads[i].getName(); + if ("SyntheticImageGenerator".equals(name)) { // NON-NLS: thread name + this.count++; + } + } + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4193384.java b/jdk/test/javax/swing/JColorChooser/Test4193384.java new file mode 100644 index 00000000000..e9ed74728a4 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4193384.java @@ -0,0 +1,70 @@ +/* + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4193384 4200976 + * @summary Tests the color conversions and the preview panel foreground color + * @author Mark Davidson + */ + +import java.awt.Color; +import javax.swing.JColorChooser; +import javax.swing.JLabel; + +public class Test4193384 { + public static void main(String[] args) { + test(new Color[] { + new Color(11, 12, 13), + new Color(204, 0, 204), + new Color(0, 51, 51) + }); + } + + private static void test(Color[] colors) { + JLabel label = new JLabel("Preview Panel"); // NON-NLS: simple label + + JColorChooser chooser = new JColorChooser(); + chooser.setPreviewPanel(label); + + float[] hsb = new float[3]; + for (int i = 0; i < colors.length; i++) { + Color color = colors[i]; + // Make sure sure that there wasn't a regression + // in java.awt.Color and the conversion methods + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb); + if (!color.equals(Color.getHSBColor(hsb[0], hsb[1], hsb[2]))) { + throw new Error("color conversion is failed"); + } + // 4193384 regression test + if (!color.equals(new JColorChooser(color).getColor())) { + throw new Error("constructor sets incorrect initial color"); + } + // 4200976 regression test + chooser.setColor(color); + if (!color.equals(label.getForeground())) { + throw new Error("a custom preview panel doesn't handle colors"); + } + } + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4234761.java b/jdk/test/javax/swing/JColorChooser/Test4234761.java new file mode 100644 index 00000000000..aa3d972a642 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4234761.java @@ -0,0 +1,60 @@ +/* + * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4234761 + * @summary RGB values sholdn't be changed in transition to HSB tab + * @author Oleg Mokhovikov + */ + +import java.awt.Color; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JColorChooser; +import javax.swing.JDialog; +import javax.swing.JTabbedPane; + +public class Test4234761 implements PropertyChangeListener { + private static final Color COLOR = new Color(51, 51, 51); + + public static void main(String[] args) { + JColorChooser chooser = new JColorChooser(COLOR); + JDialog dialog = Test4177735.show(chooser); + + PropertyChangeListener listener = new Test4234761(); + chooser.addPropertyChangeListener("color", listener); // NON-NLS: property name + + JTabbedPane tabbedPane = (JTabbedPane) chooser.getComponent(0); + tabbedPane.setSelectedIndex(1); // HSB tab index + + if (!chooser.getColor().equals(COLOR)) { + listener.propertyChange(null); + } + dialog.dispose(); + } + + public void propertyChange(PropertyChangeEvent event) { + throw new Error("RGB value is changed after transition to HSB tab"); + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4380468.html b/jdk/test/javax/swing/JColorChooser/Test4380468.html new file mode 100644 index 00000000000..fbbba0d2e64 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4380468.html @@ -0,0 +1,17 @@ + + +1. Click the HSB tab at the ColorChooser. +2. Click in the lower left corner of the gradient palette + in order to select a color such that all three RGB values + are single digit colors (such as 0, 0, 0 or 5, 3, 1). +3. Click another tab, then click back to the HSB tab. +4. Now click the lighter colors that should have + 2 and 3 digit RGB values (in the upper right corner). + +If all digits of each RGB value are shown then test passes. +If only the last digit of their values are shown then test fails. + + + + + diff --git a/jdk/test/javax/swing/JColorChooser/Test4380468.java b/jdk/test/javax/swing/JColorChooser/Test4380468.java new file mode 100644 index 00000000000..7e903317121 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4380468.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4380468 + * @summary JColorChooser's HSB panel should display all RGB digits + * @author Andrey Pikalev + * @run applet/manual=yesno Test4380468.html + */ + +import java.awt.Color; +import javax.swing.JApplet; +import javax.swing.JColorChooser; + +public class Test4380468 extends JApplet { + public void init() { + add(new JColorChooser(Color.GREEN)); + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4461329.java b/jdk/test/javax/swing/JColorChooser/Test4461329.java new file mode 100644 index 00000000000..2f23bc1ec6c --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4461329.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4461329 + * @summary Tests getPreviewPanel() and setPreviewPanel() methods + * @author Leif Samuelsson + */ + +import javax.swing.JButton; +import javax.swing.JColorChooser; + +public class Test4461329 { + public static void main(String[] args) { + JColorChooser chooser = new JColorChooser(); + if (null == chooser.getPreviewPanel()) { + throw new Error("Failed: getPreviewPanel() returned null"); + } + JButton button = new JButton("Color"); // NON-NLS: simple label + chooser.setPreviewPanel(button); + if (button != chooser.getPreviewPanel()) { + throw new Error("Failed in setPreviewPanel()"); + } + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4711996.java b/jdk/test/javax/swing/JColorChooser/Test4711996.java new file mode 100644 index 00000000000..fb6007712cf --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4711996.java @@ -0,0 +1,41 @@ +/* + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4711996 + * @summary Checks if IllegalArgumentException is thrown when updating JColorChooserUI + * @author Konstantin Eremin + */ + +import javax.swing.JColorChooser; +import javax.swing.colorchooser.AbstractColorChooserPanel; + +public class Test4711996 { + public static void main(String[] args) { + JColorChooser chooser = new JColorChooser(); + AbstractColorChooserPanel[] panels = chooser.getChooserPanels(); + chooser.removeChooserPanel(panels[0]); + chooser.updateUI(); + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4759306.html b/jdk/test/javax/swing/JColorChooser/Test4759306.html new file mode 100644 index 00000000000..8a4d53f00e9 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4759306.html @@ -0,0 +1,8 @@ + + +If you see the preview panel, then test failed, otherwise it passed. + + + + + diff --git a/jdk/test/javax/swing/JColorChooser/Test4759306.java b/jdk/test/javax/swing/JColorChooser/Test4759306.java new file mode 100644 index 00000000000..726ed798f0e --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4759306.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4759306 + * @summary Checks if JColorChooser.setPreviewPanel removes the old one + * @author Konstantin Eremin + @run applet/manual=yesno Test4759306.html + */ + +import javax.swing.JApplet; +import javax.swing.JColorChooser; +import javax.swing.JPanel; + +public class Test4759306 extends JApplet { + public void init() { + JColorChooser chooser = new JColorChooser(); + chooser.setPreviewPanel(new JPanel()); + getContentPane().add(chooser); + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4759934.html b/jdk/test/javax/swing/JColorChooser/Test4759934.html new file mode 100644 index 00000000000..0441b67ac66 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4759934.html @@ -0,0 +1,14 @@ + + +1. Press button "Show Dialog" at the frame "Test" and + the dialog with button "Show ColorChooser" should appears. +2. Press button "Show ColorChooser" at the dialog "Dialog" and + the colorchooser should appears. +3. Press the button "Cancel" of colorchooser. + If the focus will come to the frame "Test" then test fails. + If the focus will come to the dialog "Dialog" then test passes. + + + + + diff --git a/jdk/test/javax/swing/JColorChooser/Test4759934.java b/jdk/test/javax/swing/JColorChooser/Test4759934.java new file mode 100644 index 00000000000..27137726ea0 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4759934.java @@ -0,0 +1,80 @@ +/* + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4759934 + * @summary Tests windows activation problem + * @author Andrey Pikalev + * @run applet/manual=yesno Test4759934.html + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JDialog; +import javax.swing.JFrame; + +public class Test4759934 extends JApplet implements ActionListener { + private static final String CMD_DIALOG = "Show Dialog"; // NON-NLS: first button + private static final String CMD_CHOOSER = "Show ColorChooser"; // NON-NLS: second button + + private final JFrame frame = new JFrame("Test"); // NON-NLS: frame title + + public void init() { + show(this.frame, CMD_DIALOG); + } + + public void actionPerformed(ActionEvent event) { + String command = event.getActionCommand(); + if (CMD_DIALOG.equals(command)) { + JDialog dialog = new JDialog(this.frame, "Dialog"); // NON-NLS: dialog title + dialog.setLocation(200, 0); + show(dialog, CMD_CHOOSER); + } + else if (CMD_CHOOSER.equals(command)) { + Object source = event.getSource(); + Component component = (source instanceof Component) + ? (Component) source + : null; + + JColorChooser.showDialog(component, "ColorChooser", Color.BLUE); // NON-NLS: title + } + } + + private void show(Window window, String command) { + JButton button = new JButton(command); + button.setActionCommand(command); + button.addActionListener(this); + button.setFont(button.getFont().deriveFont(64.0f)); + + window.add(button); + window.pack(); + window.setVisible(true); + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4887836.html b/jdk/test/javax/swing/JColorChooser/Test4887836.html new file mode 100644 index 00000000000..324d5afe368 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4887836.html @@ -0,0 +1,9 @@ + + +If you do not see white area under swatches, +then test passed, otherwise it failed. + + + + + diff --git a/jdk/test/javax/swing/JColorChooser/Test4887836.java b/jdk/test/javax/swing/JColorChooser/Test4887836.java new file mode 100644 index 00000000000..3c6bb3832de --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4887836.java @@ -0,0 +1,43 @@ +/* + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4887836 + * @summary Checks if no tooltip modification when no KeyStroke modifier + * @author Konstantin Eremin + * @run applet/manual=yesno Test4887836.html + */ + +import java.awt.Color; +import java.awt.Font; +import javax.swing.JApplet; +import javax.swing.JColorChooser; +import javax.swing.UIManager; + +public class Test4887836 extends JApplet { + public void init() { + UIManager.put("Label.font", new Font("Perpetua", 0, 36)); // NON-NLS: property and font names + add(new JColorChooser(Color.LIGHT_GRAY)); + } +} From 3f961d60620c36044759732d87d32f7d22ebeff6 Mon Sep 17 00:00:00 2001 From: Mikhail Lapshin Date: Wed, 2 Jul 2008 18:17:56 +0400 Subject: [PATCH 005/289] 6618401: Input method cannot be selected from System menu Lock.wait() added in sun.awt.im.InputMethodManager.showInputMethodMenuOnRequesterEDT() Reviewed-by: alexp --- jdk/src/share/classes/sun/awt/im/InputMethodManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/share/classes/sun/awt/im/InputMethodManager.java b/jdk/src/share/classes/sun/awt/im/InputMethodManager.java index f95b13c63ab..caba8d6a152 100644 --- a/jdk/src/share/classes/sun/awt/im/InputMethodManager.java +++ b/jdk/src/share/classes/sun/awt/im/InputMethodManager.java @@ -358,6 +358,7 @@ class ExecutableInputMethodManager extends InputMethodManager AppContext requesterAppContext = SunToolkit.targetToAppContext(requester); synchronized (lock) { SunToolkit.postEvent(requesterAppContext, event); + lock.wait(); } Throwable eventThrowable = event.getThrowable(); From 696e17c0ba6b44d02c806a89ff537f09f4b7f925 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 3 Jul 2008 18:02:47 -0700 Subject: [PATCH 006/289] 6684714: Optimize EA Connection Graph build performance Switch on EA by default, optimize Connection Graph construction Reviewed-by: rasbold, never --- hotspot/src/share/vm/compiler/oopMap.cpp | 21 +- hotspot/src/share/vm/compiler/oopMap.hpp | 8 +- hotspot/src/share/vm/opto/bytecodeInfo.cpp | 2 +- hotspot/src/share/vm/opto/c2_globals.hpp | 2 +- hotspot/src/share/vm/opto/compile.cpp | 16 +- hotspot/src/share/vm/opto/escape.cpp | 474 +++++++++++---------- hotspot/src/share/vm/opto/escape.hpp | 52 ++- 7 files changed, 290 insertions(+), 285 deletions(-) diff --git a/hotspot/src/share/vm/compiler/oopMap.cpp b/hotspot/src/share/vm/compiler/oopMap.cpp index 2984d647ea8..78bef1836c8 100644 --- a/hotspot/src/share/vm/compiler/oopMap.cpp +++ b/hotspot/src/share/vm/compiler/oopMap.cpp @@ -188,10 +188,6 @@ void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) { } } -void OopMap::set_stack_obj(VMReg reg) { - set_xxx(reg, OopMapValue::stack_obj, VMRegImpl::Bad()); -} - // OopMapSet OopMapSet::OopMapSet() { @@ -399,8 +395,7 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, if ( loc != NULL ) { if ( omv.type() == OopMapValue::oop_value ) { #ifdef ASSERT - if (COMPILER2_PRESENT(!DoEscapeAnalysis &&) - (((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || + if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || !Universe::heap()->is_in_or_null(*loc)) { tty->print_cr("# Found non oop pointer. Dumping state at failure"); // try to dump out some helpful debugging information @@ -431,17 +426,6 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, } } } - -#ifdef COMPILER2 - if (DoEscapeAnalysis) { - for (OopMapStream oms(map, OopMapValue::stack_obj); !oms.is_done(); oms.next()) { - omv = oms.current(); - assert(omv.is_stack_loc(), "should refer to stack location"); - oop loc = (oop) fr->oopmapreg_to_location(omv.reg(),reg_map); - oop_fn->do_oop(&loc); - } - } -#endif // COMPILER2 } @@ -540,9 +524,6 @@ void print_register_type(OopMapValue::oop_types x, VMReg optional, st->print("Derived_oop_" ); optional->print_on(st); break; - case OopMapValue::stack_obj: - st->print("Stack"); - break; default: ShouldNotReachHere(); } diff --git a/hotspot/src/share/vm/compiler/oopMap.hpp b/hotspot/src/share/vm/compiler/oopMap.hpp index ac05d570c04..bce97de176c 100644 --- a/hotspot/src/share/vm/compiler/oopMap.hpp +++ b/hotspot/src/share/vm/compiler/oopMap.hpp @@ -46,7 +46,7 @@ private: public: // Constants - enum { type_bits = 6, + enum { type_bits = 5, register_bits = BitsPerShort - type_bits }; enum { type_shift = 0, @@ -63,8 +63,7 @@ public: value_value = 2, narrowoop_value = 4, callee_saved_value = 8, - derived_oop_value= 16, - stack_obj = 32 }; + derived_oop_value= 16 }; // Constructors OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); } @@ -93,14 +92,12 @@ public: bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; } bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; } bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; } - bool is_stack_obj() { return mask_bits(value(), type_mask_in_place) == stack_obj; } void set_oop() { set_value((value() & register_mask_in_place) | oop_value); } void set_value() { set_value((value() & register_mask_in_place) | value_value); } void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); } void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); } void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); } - void set_stack_obj() { set_value((value() & register_mask_in_place) | stack_obj); } VMReg reg() const { return VMRegImpl::as_VMReg(mask_bits(value(), register_mask_in_place) >> register_shift); } oop_types type() const { return (oop_types)mask_bits(value(), type_mask_in_place); } @@ -180,7 +177,6 @@ class OopMap: public ResourceObj { void set_dead ( VMReg local); void set_callee_saved( VMReg local, VMReg caller_machine_register ); void set_derived_oop ( VMReg local, VMReg derived_from_local_register ); - void set_stack_obj( VMReg local); void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional); int heap_size() const; diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 1b12ee877ad..b1fe31aed2e 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -83,7 +83,7 @@ static bool is_init_with_ea(ciMethod* callee_method, ciMethod* caller_method, Compile* C) { // True when EA is ON and a java constructor is called or // a super constructor is called from an inlined java constructor. - return DoEscapeAnalysis && EliminateAllocations && + return C->do_escape_analysis() && EliminateAllocations && ( callee_method->is_initializer() || (caller_method->is_initializer() && caller_method != C->method() && diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 691914e2b0a..7cdf24bdc23 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -373,7 +373,7 @@ product(intx, AutoBoxCacheMax, 128, \ "Sets max value cached by the java.lang.Integer autobox cache") \ \ - product(bool, DoEscapeAnalysis, false, \ + product(bool, DoEscapeAnalysis, true, \ "Perform escape analysis") \ \ notproduct(bool, PrintEscapeAnalysis, false, \ diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 019ca50ae59..f193d5d2d11 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -583,18 +583,22 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr NOT_PRODUCT( verify_graph_edges(); ) // Perform escape analysis - if (_do_escape_analysis) - _congraph = new ConnectionGraph(this); - if (_congraph != NULL) { - NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); ) - _congraph->compute_escape(); - if (failing()) return; + if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { + TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true); + + _congraph = new(comp_arena()) ConnectionGraph(this); + bool has_non_escaping_obj = _congraph->compute_escape(); #ifndef PRODUCT if (PrintEscapeAnalysis) { _congraph->dump(); } #endif + if (!has_non_escaping_obj) { + _congraph = NULL; + } + + if (failing()) return; } // Now optimize Optimize(); diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index ad6c8826270..7fee3d3d44f 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -25,16 +25,6 @@ #include "incls/_precompiled.incl" #include "incls/_escape.cpp.incl" -uint PointsToNode::edge_target(uint e) const { - assert(_edges != NULL && e < (uint)_edges->length(), "valid edge index"); - return (_edges->at(e) >> EdgeShift); -} - -PointsToNode::EdgeType PointsToNode::edge_type(uint e) const { - assert(_edges != NULL && e < (uint)_edges->length(), "valid edge index"); - return (EdgeType) (_edges->at(e) & EdgeMask); -} - void PointsToNode::add_edge(uint targIdx, PointsToNode::EdgeType et) { uint v = (targIdx << EdgeShift) + ((uint) et); if (_edges == NULL) { @@ -87,12 +77,13 @@ void PointsToNode::dump() const { } #endif -ConnectionGraph::ConnectionGraph(Compile * C) : _processed(C->comp_arena()), _node_map(C->comp_arena()) { - _collecting = true; - this->_compile = C; - const PointsToNode &dummy = PointsToNode(); - int sz = C->unique(); - _nodes = new(C->comp_arena()) GrowableArray(C->comp_arena(), sz, sz, dummy); +ConnectionGraph::ConnectionGraph(Compile * C) : + _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), + _processed(C->comp_arena()), + _collecting(true), + _compile(C), + _node_map(C->comp_arena()) { + _phantom_object = C->top()->_idx; PointsToNode *phn = ptnode_adr(_phantom_object); phn->_node = C->top(); @@ -182,32 +173,36 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform // If we are still collecting or there were no non-escaping allocations // we don't know the answer yet - if (_collecting || !_has_allocations) + if (_collecting) return PointsToNode::UnknownEscape; // if the node was created after the escape computation, return // UnknownEscape - if (idx >= (uint)_nodes->length()) + if (idx >= nodes_size()) return PointsToNode::UnknownEscape; - es = _nodes->at_grow(idx).escape_state(); + es = ptnode_adr(idx)->escape_state(); // if we have already computed a value, return it if (es != PointsToNode::UnknownEscape) return es; + // PointsTo() calls n->uncast() which can return a new ideal node. + if (n->uncast()->_idx >= nodes_size()) + return PointsToNode::UnknownEscape; + // compute max escape state of anything this node could point to VectorSet ptset(Thread::current()->resource_area()); PointsTo(ptset, n, phase); for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) { uint pt = i.elem; - PointsToNode::EscapeState pes = _nodes->adr_at(pt)->escape_state(); + PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); if (pes > es) es = pes; } // cache the computed escape state assert(es != PointsToNode::UnknownEscape, "should have computed an escape state"); - _nodes->adr_at(idx)->set_escape_state(es); + ptnode_adr(idx)->set_escape_state(es); return es; } @@ -220,49 +215,51 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase #endif n = n->uncast(); - PointsToNode npt = _nodes->at_grow(n->_idx); + PointsToNode* npt = ptnode_adr(n->_idx); // If we have a JavaObject, return just that object - if (npt.node_type() == PointsToNode::JavaObject) { + if (npt->node_type() == PointsToNode::JavaObject) { ptset.set(n->_idx); return; } #ifdef ASSERT - if (npt._node == NULL) { + if (npt->_node == NULL) { if (orig_n != n) orig_n->dump(); n->dump(); - assert(npt._node != NULL, "unregistered node"); + assert(npt->_node != NULL, "unregistered node"); } #endif worklist.push(n->_idx); while(worklist.length() > 0) { int ni = worklist.pop(); - PointsToNode pn = _nodes->at_grow(ni); - if (!visited.test_set(ni)) { - // ensure that all inputs of a Phi have been processed - assert(!_collecting || !pn._node->is_Phi() || _processed.test(ni),""); + if (visited.test_set(ni)) + continue; - int edges_processed = 0; - for (uint e = 0; e < pn.edge_count(); e++) { - uint etgt = pn.edge_target(e); - PointsToNode::EdgeType et = pn.edge_type(e); - if (et == PointsToNode::PointsToEdge) { - ptset.set(etgt); - edges_processed++; - } else if (et == PointsToNode::DeferredEdge) { - worklist.push(etgt); - edges_processed++; - } else { - assert(false,"neither PointsToEdge or DeferredEdge"); - } - } - if (edges_processed == 0) { - // no deferred or pointsto edges found. Assume the value was set - // outside this method. Add the phantom object to the pointsto set. - ptset.set(_phantom_object); + PointsToNode* pn = ptnode_adr(ni); + // ensure that all inputs of a Phi have been processed + assert(!_collecting || !pn->_node->is_Phi() || _processed.test(ni),""); + + int edges_processed = 0; + uint e_cnt = pn->edge_count(); + for (uint e = 0; e < e_cnt; e++) { + uint etgt = pn->edge_target(e); + PointsToNode::EdgeType et = pn->edge_type(e); + if (et == PointsToNode::PointsToEdge) { + ptset.set(etgt); + edges_processed++; + } else if (et == PointsToNode::DeferredEdge) { + worklist.push(etgt); + edges_processed++; + } else { + assert(false,"neither PointsToEdge or DeferredEdge"); } } + if (edges_processed == 0) { + // no deferred or pointsto edges found. Assume the value was set + // outside this method. Add the phantom object to the pointsto set. + ptset.set(_phantom_object); + } } } @@ -272,11 +269,11 @@ void ConnectionGraph::remove_deferred(uint ni, GrowableArray* deferred_edg deferred_edges->clear(); visited->Clear(); - uint i = 0; + visited->set(ni); PointsToNode *ptn = ptnode_adr(ni); // Mark current edges as visited and move deferred edges to separate array. - while (i < ptn->edge_count()) { + for (uint i = 0; i < ptn->edge_count(); ) { uint t = ptn->edge_target(i); #ifdef ASSERT assert(!visited->test_set(t), "expecting no duplications"); @@ -293,24 +290,23 @@ void ConnectionGraph::remove_deferred(uint ni, GrowableArray* deferred_edg for (int next = 0; next < deferred_edges->length(); ++next) { uint t = deferred_edges->at(next); PointsToNode *ptt = ptnode_adr(t); - for (uint j = 0; j < ptt->edge_count(); j++) { - uint n1 = ptt->edge_target(j); - if (visited->test_set(n1)) + uint e_cnt = ptt->edge_count(); + for (uint e = 0; e < e_cnt; e++) { + uint etgt = ptt->edge_target(e); + if (visited->test_set(etgt)) continue; - switch(ptt->edge_type(j)) { - case PointsToNode::PointsToEdge: - add_pointsto_edge(ni, n1); - if(n1 == _phantom_object) { - // Special case - field set outside (globally escaping). - ptn->set_escape_state(PointsToNode::GlobalEscape); - } - break; - case PointsToNode::DeferredEdge: - deferred_edges->append(n1); - break; - case PointsToNode::FieldEdge: - assert(false, "invalid connection graph"); - break; + + PointsToNode::EdgeType et = ptt->edge_type(e); + if (et == PointsToNode::PointsToEdge) { + add_pointsto_edge(ni, etgt); + if(etgt == _phantom_object) { + // Special case - field set outside (globally escaping). + ptn->set_escape_state(PointsToNode::GlobalEscape); + } + } else if (et == PointsToNode::DeferredEdge) { + deferred_edges->append(etgt); + } else { + assert(false,"invalid connection graph"); } } } @@ -322,15 +318,15 @@ void ConnectionGraph::remove_deferred(uint ni, GrowableArray* deferred_edg // a pointsto edge is added if it is a JavaObject void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) { - PointsToNode an = _nodes->at_grow(adr_i); - PointsToNode to = _nodes->at_grow(to_i); - bool deferred = (to.node_type() == PointsToNode::LocalVar); + PointsToNode* an = ptnode_adr(adr_i); + PointsToNode* to = ptnode_adr(to_i); + bool deferred = (to->node_type() == PointsToNode::LocalVar); - for (uint fe = 0; fe < an.edge_count(); fe++) { - assert(an.edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); - int fi = an.edge_target(fe); - PointsToNode pf = _nodes->at_grow(fi); - int po = pf.offset(); + for (uint fe = 0; fe < an->edge_count(); fe++) { + assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); + int fi = an->edge_target(fe); + PointsToNode* pf = ptnode_adr(fi); + int po = pf->offset(); if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) { if (deferred) add_deferred_edge(fi, to_i); @@ -343,13 +339,13 @@ void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) { // Add a deferred edge from node given by "from_i" to any field of adr_i // whose offset matches "offset". void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) { - PointsToNode an = _nodes->at_grow(adr_i); - for (uint fe = 0; fe < an.edge_count(); fe++) { - assert(an.edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); - int fi = an.edge_target(fe); - PointsToNode pf = _nodes->at_grow(fi); - int po = pf.offset(); - if (pf.edge_count() == 0) { + PointsToNode* an = ptnode_adr(adr_i); + for (uint fe = 0; fe < an->edge_count(); fe++) { + assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); + int fi = an->edge_target(fe); + PointsToNode* pf = ptnode_adr(fi); + int po = pf->offset(); + if (pf->edge_count() == 0) { // we have not seen any stores to this field, assume it was set outside this method add_pointsto_edge(fi, _phantom_object); } @@ -835,6 +831,11 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) // Phase 1: Process possible allocations from alloc_worklist. // Create instance types for the CheckCastPP for allocations where possible. + // + // (Note: don't forget to change the order of the second AddP node on + // the alloc_worklist if the order of the worklist processing is changed, + // see the comment in find_second_addp().) + // while (alloc_worklist.length() != 0) { Node *n = alloc_worklist.pop(); uint ni = n->_idx; @@ -842,7 +843,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) if (n->is_Call()) { CallNode *alloc = n->as_Call(); // copy escape information to call node - PointsToNode* ptn = _nodes->adr_at(alloc->_idx); + PointsToNode* ptn = ptnode_adr(alloc->_idx); PointsToNode::EscapeState es = escape_state(alloc, igvn); // We have an allocation or call which returns a Java object, // see if it is unescaped. @@ -899,7 +900,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) // First, put on the worklist all Field edges from Connection Graph // which is more accurate then putting immediate users from Ideal Graph. for (uint e = 0; e < ptn->edge_count(); e++) { - Node *use = _nodes->adr_at(ptn->edge_target(e))->_node; + Node *use = ptnode_adr(ptn->edge_target(e))->_node; assert(ptn->edge_type(e) == PointsToNode::FieldEdge && use->is_AddP(), "only AddP nodes are Field edges in CG"); if (use->outcnt() > 0) { // Don't process dead nodes @@ -1062,7 +1063,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) } if (mem != n->in(MemNode::Memory)) { set_map(n->_idx, mem); - _nodes->adr_at(n->_idx)->_node = n; + ptnode_adr(n->_idx)->_node = n; } if (n->is_Load()) { continue; // don't push users @@ -1223,10 +1224,10 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) // Update the memory inputs of MemNodes with the value we computed // in Phase 2. - for (int i = 0; i < _nodes->length(); i++) { + for (uint i = 0; i < nodes_size(); i++) { Node *nmem = get_map(i); if (nmem != NULL) { - Node *n = _nodes->adr_at(i)->_node; + Node *n = ptnode_adr(i)->_node; if (n != NULL && n->is_Mem()) { igvn->hash_delete(n); n->set_req(MemNode::Memory, nmem); @@ -1237,28 +1238,48 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) } } -void ConnectionGraph::compute_escape() { +bool ConnectionGraph::has_candidates(Compile *C) { + // EA brings benefits only when the code has allocations and/or locks which + // are represented by ideal Macro nodes. + int cnt = C->macro_count(); + for( int i=0; i < cnt; i++ ) { + Node *n = C->macro_node(i); + if ( n->is_Allocate() ) + return true; + if( n->is_Lock() ) { + Node* obj = n->as_Lock()->obj_node()->uncast(); + if( !(obj->is_Parm() || obj->is_Con()) ) + return true; + } + } + return false; +} + +bool ConnectionGraph::compute_escape() { + Compile* C = _compile; // 1. Populate Connection Graph (CG) with Ideal nodes. Unique_Node_List worklist_init; - worklist_init.map(_compile->unique(), NULL); // preallocate space + worklist_init.map(C->unique(), NULL); // preallocate space // Initialize worklist - if (_compile->root() != NULL) { - worklist_init.push(_compile->root()); + if (C->root() != NULL) { + worklist_init.push(C->root()); } GrowableArray cg_worklist; - PhaseGVN* igvn = _compile->initial_gvn(); + PhaseGVN* igvn = C->initial_gvn(); bool has_allocations = false; // Push all useful nodes onto CG list and set their type. for( uint next = 0; next < worklist_init.size(); ++next ) { Node* n = worklist_init.at(next); record_for_escape_analysis(n, igvn); - if (n->is_Call() && - _nodes->adr_at(n->_idx)->node_type() == PointsToNode::JavaObject) { + // Only allocations and java static calls results are checked + // for an escape status. See process_call_result() below. + if (n->is_Allocate() || n->is_CallStaticJava() && + ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { has_allocations = true; } if(n->is_AddP()) @@ -1269,24 +1290,23 @@ void ConnectionGraph::compute_escape() { } } - if (has_allocations) { - _has_allocations = true; - } else { - _has_allocations = false; + if (!has_allocations) { _collecting = false; - return; // Nothing to do. + return false; // Nothing to do. } // 2. First pass to create simple CG edges (doesn't require to walk CG). - for( uint next = 0; next < _delayed_worklist.size(); ++next ) { + uint delayed_size = _delayed_worklist.size(); + for( uint next = 0; next < delayed_size; ++next ) { Node* n = _delayed_worklist.at(next); build_connection_graph(n, igvn); } // 3. Pass to create fields edges (Allocate -F-> AddP). - for( int next = 0; next < cg_worklist.length(); ++next ) { + uint cg_length = cg_worklist.length(); + for( uint next = 0; next < cg_length; ++next ) { int ni = cg_worklist.at(next); - build_connection_graph(_nodes->adr_at(ni)->_node, igvn); + build_connection_graph(ptnode_adr(ni)->_node, igvn); } cg_worklist.clear(); @@ -1294,8 +1314,8 @@ void ConnectionGraph::compute_escape() { // 4. Build Connection Graph which need // to walk the connection graph. - for (uint ni = 0; ni < (uint)_nodes->length(); ni++) { - PointsToNode* ptn = _nodes->adr_at(ni); + for (uint ni = 0; ni < nodes_size(); ni++) { + PointsToNode* ptn = ptnode_adr(ni); Node *n = ptn->_node; if (n != NULL) { // Call, AddP, LoadP, StoreP build_connection_graph(n, igvn); @@ -1305,20 +1325,19 @@ void ConnectionGraph::compute_escape() { } VectorSet ptset(Thread::current()->resource_area()); - GrowableArray alloc_worklist; - GrowableArray worklist; GrowableArray deferred_edges; VectorSet visited(Thread::current()->resource_area()); - // remove deferred edges from the graph and collect - // information we will need for type splitting - for( int next = 0; next < cg_worklist.length(); ++next ) { + // 5. Remove deferred edges from the graph and collect + // information needed for type splitting. + cg_length = cg_worklist.length(); + for( uint next = 0; next < cg_length; ++next ) { int ni = cg_worklist.at(next); - PointsToNode* ptn = _nodes->adr_at(ni); + PointsToNode* ptn = ptnode_adr(ni); PointsToNode::NodeType nt = ptn->node_type(); - Node *n = ptn->_node; if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { remove_deferred(ni, &deferred_edges, &visited); + Node *n = ptn->_node; if (n->is_AddP()) { // If this AddP computes an address which may point to more that one // object or more then one field (array's element), nothing the address @@ -1329,116 +1348,123 @@ void ConnectionGraph::compute_escape() { if (ptset.Size() > 1 || (ptset.Size() != 0 && ptn->offset() == Type::OffsetBot)) { for( VectorSetI j(&ptset); j.test(); ++j ) { - uint pt = j.elem; - ptnode_adr(pt)->_scalar_replaceable = false; + ptnode_adr(j.elem)->_scalar_replaceable = false; } } } - } else if (nt == PointsToNode::JavaObject && n->is_Call()) { - // Push call on alloc_worlist (alocations are calls) - // for processing by split_unique_types(). - alloc_worklist.append(n); } } + // 6. Propagate escape states. + GrowableArray worklist; + bool has_non_escaping_obj = false; + // push all GlobalEscape nodes on the worklist - for( int next = 0; next < cg_worklist.length(); ++next ) { + for( uint next = 0; next < cg_length; ++next ) { int nk = cg_worklist.at(next); - if (_nodes->adr_at(nk)->escape_state() == PointsToNode::GlobalEscape) - worklist.append(nk); + if (ptnode_adr(nk)->escape_state() == PointsToNode::GlobalEscape) + worklist.push(nk); } - // mark all node reachable from GlobalEscape nodes + // mark all nodes reachable from GlobalEscape nodes while(worklist.length() > 0) { - PointsToNode n = _nodes->at(worklist.pop()); - for (uint ei = 0; ei < n.edge_count(); ei++) { - uint npi = n.edge_target(ei); + PointsToNode* ptn = ptnode_adr(worklist.pop()); + uint e_cnt = ptn->edge_count(); + for (uint ei = 0; ei < e_cnt; ei++) { + uint npi = ptn->edge_target(ei); PointsToNode *np = ptnode_adr(npi); if (np->escape_state() < PointsToNode::GlobalEscape) { np->set_escape_state(PointsToNode::GlobalEscape); - worklist.append_if_missing(npi); + worklist.push(npi); } } } // push all ArgEscape nodes on the worklist - for( int next = 0; next < cg_worklist.length(); ++next ) { + for( uint next = 0; next < cg_length; ++next ) { int nk = cg_worklist.at(next); - if (_nodes->adr_at(nk)->escape_state() == PointsToNode::ArgEscape) + if (ptnode_adr(nk)->escape_state() == PointsToNode::ArgEscape) worklist.push(nk); } - // mark all node reachable from ArgEscape nodes + // mark all nodes reachable from ArgEscape nodes while(worklist.length() > 0) { - PointsToNode n = _nodes->at(worklist.pop()); - for (uint ei = 0; ei < n.edge_count(); ei++) { - uint npi = n.edge_target(ei); + PointsToNode* ptn = ptnode_adr(worklist.pop()); + if (ptn->node_type() == PointsToNode::JavaObject) + has_non_escaping_obj = true; // Non GlobalEscape + uint e_cnt = ptn->edge_count(); + for (uint ei = 0; ei < e_cnt; ei++) { + uint npi = ptn->edge_target(ei); PointsToNode *np = ptnode_adr(npi); if (np->escape_state() < PointsToNode::ArgEscape) { np->set_escape_state(PointsToNode::ArgEscape); - worklist.append_if_missing(npi); + worklist.push(npi); } } } + GrowableArray alloc_worklist; + // push all NoEscape nodes on the worklist - for( int next = 0; next < cg_worklist.length(); ++next ) { + for( uint next = 0; next < cg_length; ++next ) { int nk = cg_worklist.at(next); - if (_nodes->adr_at(nk)->escape_state() == PointsToNode::NoEscape) + if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape) worklist.push(nk); } - // mark all node reachable from NoEscape nodes + // mark all nodes reachable from NoEscape nodes while(worklist.length() > 0) { - PointsToNode n = _nodes->at(worklist.pop()); - for (uint ei = 0; ei < n.edge_count(); ei++) { - uint npi = n.edge_target(ei); + PointsToNode* ptn = ptnode_adr(worklist.pop()); + if (ptn->node_type() == PointsToNode::JavaObject) + has_non_escaping_obj = true; // Non GlobalEscape + Node* n = ptn->_node; + if (n->is_Allocate() && ptn->_scalar_replaceable ) { + // Push scalar replaceable alocations on alloc_worklist + // for processing in split_unique_types(). + alloc_worklist.append(n); + } + uint e_cnt = ptn->edge_count(); + for (uint ei = 0; ei < e_cnt; ei++) { + uint npi = ptn->edge_target(ei); PointsToNode *np = ptnode_adr(npi); if (np->escape_state() < PointsToNode::NoEscape) { np->set_escape_state(PointsToNode::NoEscape); - worklist.append_if_missing(npi); + worklist.push(npi); } } } _collecting = false; + assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); - has_allocations = false; // Are there scalar replaceable allocations? + bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0; + if ( has_scalar_replaceable_candidates && + C->AliasLevel() >= 3 && EliminateAllocations ) { - for( int next = 0; next < alloc_worklist.length(); ++next ) { - Node* n = alloc_worklist.at(next); - uint ni = n->_idx; - PointsToNode* ptn = _nodes->adr_at(ni); - PointsToNode::EscapeState es = ptn->escape_state(); - if (ptn->escape_state() == PointsToNode::NoEscape && - ptn->_scalar_replaceable) { - has_allocations = true; - break; - } - } - if (!has_allocations) { - return; // Nothing to do. - } - - if(_compile->AliasLevel() >= 3 && EliminateAllocations) { // Now use the escape information to create unique types for - // unescaped objects + // scalar replaceable objects. split_unique_types(alloc_worklist); - if (_compile->failing()) return; + + if (C->failing()) return false; // Clean up after split unique types. ResourceMark rm; - PhaseRemoveUseless pru(_compile->initial_gvn(), _compile->for_igvn()); + PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); + + C->print_method("After Escape Analysis", 2); #ifdef ASSERT - } else if (PrintEscapeAnalysis || PrintEliminateAllocations) { + } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) { tty->print("=== No allocations eliminated for "); - C()->method()->print_short_name(); + C->method()->print_short_name(); if(!EliminateAllocations) { tty->print(" since EliminateAllocations is off ==="); - } else if(_compile->AliasLevel() < 3) { + } else if(!has_scalar_replaceable_candidates) { + tty->print(" since there are no scalar replaceable candidates ==="); + } else if(C->AliasLevel() < 3) { tty->print(" since AliasLevel < 3 ==="); } tty->cr(); #endif } + return has_non_escaping_obj; } void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { @@ -1538,7 +1564,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha } } if (copy_dependencies) - call_analyzer->copy_dependencies(C()->dependencies()); + call_analyzer->copy_dependencies(_compile->dependencies()); break; } } @@ -1561,7 +1587,6 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha for( VectorSetI j(&ptset); j.test(); ++j ) { uint pt = j.elem; set_escape_state(pt, PointsToNode::GlobalEscape); - PointsToNode *ptadr = ptnode_adr(pt); } } } @@ -1569,9 +1594,10 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha } } void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *phase) { - PointsToNode *ptadr = ptnode_adr(resproj->_idx); + CallNode *call = resproj->in(0)->as_Call(); + uint call_idx = call->_idx; + uint resproj_idx = resproj->_idx; - CallNode *call = resproj->in(0)->as_Call(); switch (call->Opcode()) { case Op_Allocate: { @@ -1587,7 +1613,6 @@ void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *pha ciKlass* cik = kt->klass(); ciInstanceKlass* ciik = cik->as_instance_klass(); - PointsToNode *ptadr = ptnode_adr(call->_idx); PointsToNode::EscapeState es; uint edge_to; if (cik->is_subclass_of(_compile->env()->Thread_klass()) || ciik->has_finalizer()) { @@ -1595,25 +1620,24 @@ void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *pha edge_to = _phantom_object; // Could not be worse } else { es = PointsToNode::NoEscape; - edge_to = call->_idx; + edge_to = call_idx; } - set_escape_state(call->_idx, es); - add_pointsto_edge(resproj->_idx, edge_to); - _processed.set(resproj->_idx); + set_escape_state(call_idx, es); + add_pointsto_edge(resproj_idx, edge_to); + _processed.set(resproj_idx); break; } case Op_AllocateArray: { - PointsToNode *ptadr = ptnode_adr(call->_idx); int length = call->in(AllocateNode::ALength)->find_int_con(-1); if (length < 0 || length > EliminateAllocationArraySizeLimit) { // Not scalar replaceable if the length is not constant or too big. - ptadr->_scalar_replaceable = false; + ptnode_adr(call_idx)->_scalar_replaceable = false; } - set_escape_state(call->_idx, PointsToNode::NoEscape); - add_pointsto_edge(resproj->_idx, call->_idx); - _processed.set(resproj->_idx); + set_escape_state(call_idx, PointsToNode::NoEscape); + add_pointsto_edge(resproj_idx, call_idx); + _processed.set(resproj_idx); break; } @@ -1631,19 +1655,17 @@ void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *pha // Note: we use isa_ptr() instead of isa_oopptr() here because the // _multianewarray functions return a TypeRawPtr. if (ret_type == NULL || ret_type->isa_ptr() == NULL) { - _processed.set(resproj->_idx); + _processed.set(resproj_idx); break; // doesn't return a pointer type } ciMethod *meth = call->as_CallJava()->method(); const TypeTuple * d = call->tf()->domain(); if (meth == NULL) { // not a Java method, assume global escape - set_escape_state(call->_idx, PointsToNode::GlobalEscape); - if (resproj != NULL) - add_pointsto_edge(resproj->_idx, _phantom_object); + set_escape_state(call_idx, PointsToNode::GlobalEscape); + add_pointsto_edge(resproj_idx, _phantom_object); } else { BCEscapeAnalyzer *call_analyzer = meth->get_bcea(); - VectorSet ptset(Thread::current()->resource_area()); bool copy_dependencies = false; if (call_analyzer->is_return_allocated()) { @@ -1651,13 +1673,12 @@ void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *pha // update dependency information. // Mark it as NoEscape so that objects referenced by // it's fields will be marked as NoEscape at least. - set_escape_state(call->_idx, PointsToNode::NoEscape); - if (resproj != NULL) - add_pointsto_edge(resproj->_idx, call->_idx); + set_escape_state(call_idx, PointsToNode::NoEscape); + add_pointsto_edge(resproj_idx, call_idx); copy_dependencies = true; - } else if (call_analyzer->is_return_local() && resproj != NULL) { + } else if (call_analyzer->is_return_local()) { // determine whether any arguments are returned - set_escape_state(call->_idx, PointsToNode::NoEscape); + set_escape_state(call_idx, PointsToNode::NoEscape); for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { const Type* at = d->field_at(i); @@ -1665,36 +1686,35 @@ void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *pha Node *arg = call->in(i)->uncast(); if (call_analyzer->is_arg_returned(i - TypeFunc::Parms)) { - PointsToNode *arg_esp = _nodes->adr_at(arg->_idx); + PointsToNode *arg_esp = ptnode_adr(arg->_idx); if (arg_esp->node_type() == PointsToNode::UnknownType) done = false; else if (arg_esp->node_type() == PointsToNode::JavaObject) - add_pointsto_edge(resproj->_idx, arg->_idx); + add_pointsto_edge(resproj_idx, arg->_idx); else - add_deferred_edge(resproj->_idx, arg->_idx); + add_deferred_edge(resproj_idx, arg->_idx); arg_esp->_hidden_alias = true; } } } copy_dependencies = true; } else { - set_escape_state(call->_idx, PointsToNode::GlobalEscape); - if (resproj != NULL) - add_pointsto_edge(resproj->_idx, _phantom_object); + set_escape_state(call_idx, PointsToNode::GlobalEscape); + add_pointsto_edge(resproj_idx, _phantom_object); for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { const Type* at = d->field_at(i); if (at->isa_oopptr() != NULL) { Node *arg = call->in(i)->uncast(); - PointsToNode *arg_esp = _nodes->adr_at(arg->_idx); + PointsToNode *arg_esp = ptnode_adr(arg->_idx); arg_esp->_hidden_alias = true; } } } if (copy_dependencies) - call_analyzer->copy_dependencies(C()->dependencies()); + call_analyzer->copy_dependencies(_compile->dependencies()); } if (done) - _processed.set(resproj->_idx); + _processed.set(resproj_idx); break; } @@ -1709,13 +1729,11 @@ void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *pha // Note: we use isa_ptr() instead of isa_oopptr() here because the // _multianewarray functions return a TypeRawPtr. if (ret_type->isa_ptr() != NULL) { - PointsToNode *ptadr = ptnode_adr(call->_idx); - set_escape_state(call->_idx, PointsToNode::GlobalEscape); - if (resproj != NULL) - add_pointsto_edge(resproj->_idx, _phantom_object); + set_escape_state(call_idx, PointsToNode::GlobalEscape); + add_pointsto_edge(resproj_idx, _phantom_object); } } - _processed.set(resproj->_idx); + _processed.set(resproj_idx); } } } @@ -1743,7 +1761,7 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) // Check if a call returns an object. const TypeTuple *r = n->as_Call()->tf()->range(); - if (r->cnt() > TypeFunc::Parms && + if (n->is_CallStaticJava() && r->cnt() > TypeFunc::Parms && n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { // Note: use isa_ptr() instead of isa_oopptr() here because // the _multianewarray functions return a TypeRawPtr. @@ -1776,7 +1794,7 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) { add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); int ti = n->in(1)->_idx; - PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type(); + PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); if (nt == PointsToNode::UnknownType) { _delayed_worklist.push(n); // Process it later. break; @@ -1866,7 +1884,7 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) if (in->is_top() || in == n) continue; // ignore top or inputs which go back this node int ti = in->_idx; - PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type(); + PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); if (nt == PointsToNode::UnknownType) { break; } else if (nt == PointsToNode::JavaObject) { @@ -1904,7 +1922,7 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) // Treat Return value as LocalVar with GlobalEscape escape state. add_node(n, PointsToNode::LocalVar, PointsToNode::GlobalEscape, false); int ti = n->in(TypeFunc::Parms)->_idx; - PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type(); + PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); if (nt == PointsToNode::UnknownType) { _delayed_worklist.push(n); // Process it later. break; @@ -1968,17 +1986,17 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) } void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { + uint n_idx = n->_idx; + // Don't set processed bit for AddP, LoadP, StoreP since // they may need more then one pass to process. - if (_processed.test(n->_idx)) + if (_processed.test(n_idx)) return; // No need to redefine node's state. - PointsToNode *ptadr = ptnode_adr(n->_idx); - if (n->is_Call()) { CallNode *call = n->as_Call(); process_call_arguments(call, phase); - _processed.set(n->_idx); + _processed.set(n_idx); return; } @@ -1991,7 +2009,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { PointsTo(ptset, base, phase); for( VectorSetI i(&ptset); i.test(); ++i ) { uint pt = i.elem; - add_field_edge(pt, n->_idx, address_offset(n, phase)); + add_field_edge(pt, n_idx, address_offset(n, phase)); } break; } @@ -2006,12 +2024,12 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { case Op_DecodeN: { int ti = n->in(1)->_idx; - if (_nodes->adr_at(ti)->node_type() == PointsToNode::JavaObject) { - add_pointsto_edge(n->_idx, ti); + if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { + add_pointsto_edge(n_idx, ti); } else { - add_deferred_edge(n->_idx, ti); + add_deferred_edge(n_idx, ti); } - _processed.set(n->_idx); + _processed.set(n_idx); break; } case Op_ConP: @@ -2060,7 +2078,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { int offset = address_offset(adr, phase); for( VectorSetI i(&ptset); i.test(); ++i ) { uint pt = i.elem; - add_deferred_edge_to_fields(n->_idx, pt, offset); + add_deferred_edge_to_fields(n_idx, pt, offset); } break; } @@ -2083,13 +2101,13 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { if (in->is_top() || in == n) continue; // ignore top or inputs which go back this node int ti = in->_idx; - if (_nodes->adr_at(in->_idx)->node_type() == PointsToNode::JavaObject) { - add_pointsto_edge(n->_idx, ti); + if (ptnode_adr(in->_idx)->node_type() == PointsToNode::JavaObject) { + add_pointsto_edge(n_idx, ti); } else { - add_deferred_edge(n->_idx, ti); + add_deferred_edge(n_idx, ti); } } - _processed.set(n->_idx); + _processed.set(n_idx); break; } case Op_Proj: @@ -2097,7 +2115,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { // we are only interested in the result projection from a call if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { process_call_result(n->as_Proj(), phase); - assert(_processed.test(n->_idx), "all call results should be processed"); + assert(_processed.test(n_idx), "all call results should be processed"); } else { assert(false, "Op_Proj"); } @@ -2112,12 +2130,12 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { } #endif int ti = n->in(TypeFunc::Parms)->_idx; - if (_nodes->adr_at(ti)->node_type() == PointsToNode::JavaObject) { - add_pointsto_edge(n->_idx, ti); + if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { + add_pointsto_edge(n_idx, ti); } else { - add_deferred_edge(n->_idx, ti); + add_deferred_edge(n_idx, ti); } - _processed.set(n->_idx); + _processed.set(n_idx); break; } case Op_StoreP: @@ -2162,9 +2180,9 @@ void ConnectionGraph::dump() { PhaseGVN *igvn = _compile->initial_gvn(); bool first = true; - uint size = (uint)_nodes->length(); + uint size = nodes_size(); for (uint ni = 0; ni < size; ni++) { - PointsToNode *ptn = _nodes->adr_at(ni); + PointsToNode *ptn = ptnode_adr(ni); PointsToNode::NodeType ptn_type = ptn->node_type(); if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL) @@ -2174,7 +2192,7 @@ void ConnectionGraph::dump() { if (first) { tty->cr(); tty->print("======== Connection graph for "); - C()->method()->print_short_name(); + _compile->method()->print_short_name(); tty->cr(); first = false; } @@ -2182,12 +2200,12 @@ void ConnectionGraph::dump() { ptn->dump(); // Print all locals which reference this allocation for (uint li = ni; li < size; li++) { - PointsToNode *ptn_loc = _nodes->adr_at(li); + PointsToNode *ptn_loc = ptnode_adr(li); PointsToNode::NodeType ptn_loc_type = ptn_loc->node_type(); if ( ptn_loc_type == PointsToNode::LocalVar && ptn_loc->_node != NULL && ptn_loc->edge_count() == 1 && ptn_loc->edge_target(0) == ni ) { tty->print("%6d LocalVar [[%d]]", li, ni); - _nodes->adr_at(li)->_node->dump(); + ptnode_adr(li)->_node->dump(); } } if (Verbose) { @@ -2195,7 +2213,7 @@ void ConnectionGraph::dump() { for (uint i = 0; i < ptn->edge_count(); i++) { uint ei = ptn->edge_target(i); tty->print("%6d Field [[%d]]", ei, ni); - _nodes->adr_at(ei)->_node->dump(); + ptnode_adr(ei)->_node->dump(); } } tty->cr(); diff --git a/hotspot/src/share/vm/opto/escape.hpp b/hotspot/src/share/vm/opto/escape.hpp index 1d2c83511e7..5d9259569ef 100644 --- a/hotspot/src/share/vm/opto/escape.hpp +++ b/hotspot/src/share/vm/opto/escape.hpp @@ -178,14 +178,24 @@ public: // count of outgoing edges uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } + // node index of target of outgoing edge "e" - uint edge_target(uint e) const; + uint edge_target(uint e) const { + assert(_edges != NULL, "valid edge index"); + return (_edges->at(e) >> EdgeShift); + } // type of outgoing edge "e" - EdgeType edge_type(uint e) const; + EdgeType edge_type(uint e) const { + assert(_edges != NULL, "valid edge index"); + return (EdgeType) (_edges->at(e) & EdgeMask); + } + // add a edge of the specified type pointing to the specified target void add_edge(uint targIdx, EdgeType et); + // remove an edge of the specified type pointing to the specified target void remove_edge(uint targIdx, EdgeType et); + #ifndef PRODUCT void dump() const; #endif @@ -194,7 +204,7 @@ public: class ConnectionGraph: public ResourceObj { private: - GrowableArray* _nodes; // Connection graph nodes indexed + GrowableArray _nodes; // Connection graph nodes indexed // by ideal node index. Unique_Node_List _delayed_worklist; // Nodes to be processed before @@ -207,9 +217,6 @@ private: // is still being collected. If false, // no new nodes will be processed. - bool _has_allocations; // Indicates whether method has any - // non-escaping allocations. - uint _phantom_object; // Index of globally escaping object // that pointer values loaded from // a field which has not been set @@ -217,14 +224,13 @@ private: Compile * _compile; // Compile object for current compilation - // address of an element in _nodes. Used when the element is to be modified - PointsToNode *ptnode_adr(uint idx) { - if ((uint)_nodes->length() <= idx) { - // expand _nodes array - PointsToNode dummy = _nodes->at_grow(idx); - } - return _nodes->adr_at(idx); + // Address of an element in _nodes. Used when the element is to be modified + PointsToNode *ptnode_adr(uint idx) const { + // There should be no new ideal nodes during ConnectionGraph build, + // growableArray::adr_at() will throw assert otherwise. + return _nodes.adr_at(idx); } + uint nodes_size() const { return _nodes.length(); } // Add node to ConnectionGraph. void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); @@ -307,30 +313,30 @@ private: // Set the escape state of a node void set_escape_state(uint ni, PointsToNode::EscapeState es); - // Get Compile object for current compilation. - Compile *C() const { return _compile; } - public: ConnectionGraph(Compile *C); + // Check for non-escaping candidates + static bool has_candidates(Compile *C); + // Compute the escape information - void compute_escape(); + bool compute_escape(); // escape state of a node PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase); // other information we have collected bool is_scalar_replaceable(Node *n) { - if (_collecting) + if (_collecting || (n->_idx >= nodes_size())) return false; - PointsToNode ptn = _nodes->at_grow(n->_idx); - return ptn.escape_state() == PointsToNode::NoEscape && ptn._scalar_replaceable; + PointsToNode* ptn = ptnode_adr(n->_idx); + return ptn->escape_state() == PointsToNode::NoEscape && ptn->_scalar_replaceable; } bool hidden_alias(Node *n) { - if (_collecting) + if (_collecting || (n->_idx >= nodes_size())) return true; - PointsToNode ptn = _nodes->at_grow(n->_idx); - return (ptn.escape_state() != PointsToNode::NoEscape) || ptn._hidden_alias; + PointsToNode* ptn = ptnode_adr(n->_idx); + return (ptn->escape_state() != PointsToNode::NoEscape) || ptn->_hidden_alias; } #ifndef PRODUCT From 1dce7af76f26ab1860a83f60e9f4853e56952d8e Mon Sep 17 00:00:00 2001 From: Mikhail Lapshin Date: Mon, 7 Jul 2008 16:56:23 +0400 Subject: [PATCH 007/289] 6647340: Minimized JInternalFrame icons appear in incorrect positions if the main frame is resized Now BasicInternalFrameUI and BasicDesktopIconUI both recalculate frame icon position Reviewed-by: peterz --- .../swing/plaf/basic/BasicDesktopIconUI.java | 12 +- .../plaf/basic/BasicInternalFrameUI.java | 45 ++--- .../swing/plaf/basic/DesktopIconMover.java | 168 ++++++++++++++++++ .../JInternalFrame/6647340/bug6647340.java | 146 +++++++++++++++ 4 files changed, 335 insertions(+), 36 deletions(-) create mode 100644 jdk/src/share/classes/javax/swing/plaf/basic/DesktopIconMover.java create mode 100644 jdk/test/javax/swing/JInternalFrame/6647340/bug6647340.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java index 9aab4dbe17d..5ebb6289440 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicDesktopIconUI.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ public class BasicDesktopIconUI extends DesktopIconUI { protected JInternalFrame.JDesktopIcon desktopIcon; protected JInternalFrame frame; + private DesktopIconMover desktopIconMover; /** * The title pane component used in the desktop icon. @@ -127,12 +128,21 @@ public class BasicDesktopIconUI extends DesktopIconUI { mouseInputListener = createMouseInputListener(); desktopIcon.addMouseMotionListener(mouseInputListener); desktopIcon.addMouseListener(mouseInputListener); + getDesktopIconMover().installListeners(); } protected void uninstallListeners() { desktopIcon.removeMouseMotionListener(mouseInputListener); desktopIcon.removeMouseListener(mouseInputListener); mouseInputListener = null; + getDesktopIconMover().uninstallListeners(); + } + + private DesktopIconMover getDesktopIconMover() { + if (desktopIconMover == null) { + desktopIconMover = new DesktopIconMover(desktopIcon); + } + return desktopIconMover; } protected void installDefaults() { diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java index 83b0fd73bd9..86a8f15ddd0 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,6 @@ public class BasicInternalFrameUI extends InternalFrameUI protected MouseInputAdapter borderListener; protected PropertyChangeListener propertyChangeListener; protected LayoutManager internalFrameLayout; - protected ComponentListener componentListener; protected MouseInputListener glassPaneDispatcher; private InternalFrameListener internalFrameListener; @@ -67,9 +66,9 @@ public class BasicInternalFrameUI extends InternalFrameUI protected BasicInternalFrameTitlePane titlePane; // access needs this private static DesktopManager sharedDesktopManager; - private boolean componentListenerAdded = false; private Rectangle parentBounds; + private DesktopIconMover desktopIconMover; private boolean dragging = false; private boolean resizing = false; @@ -210,14 +209,17 @@ public class BasicInternalFrameUI extends InternalFrameUI frame.getGlassPane().addMouseListener(glassPaneDispatcher); frame.getGlassPane().addMouseMotionListener(glassPaneDispatcher); } - componentListener = createComponentListener(); if (frame.getParent() != null) { parentBounds = frame.getParent().getBounds(); } - if ((frame.getParent() != null) && !componentListenerAdded) { - frame.getParent().addComponentListener(componentListener); - componentListenerAdded = true; + getDesktopIconMover().installListeners(); + } + + private DesktopIconMover getDesktopIconMover() { + if (desktopIconMover == null) { + desktopIconMover = new DesktopIconMover(frame); } + return desktopIconMover; } // Provide a FocusListener to listen for a WINDOW_LOST_FOCUS event, @@ -288,11 +290,7 @@ public class BasicInternalFrameUI extends InternalFrameUI * @since 1.3 */ protected void uninstallListeners() { - if ((frame.getParent() != null) && componentListenerAdded) { - frame.getParent().removeComponentListener(componentListener); - componentListenerAdded = false; - } - componentListener = null; + getDesktopIconMover().uninstallListeners(); if (glassPaneDispatcher != null) { frame.getGlassPane().removeMouseListener(glassPaneDispatcher); frame.getGlassPane().removeMouseMotionListener(glassPaneDispatcher); @@ -1230,15 +1228,6 @@ public class BasicInternalFrameUI extends InternalFrameUI } } - // Relocate the icon base on the new parent bounds. - if (icon != null) { - Rectangle iconBounds = icon.getBounds(); - int y = iconBounds.y + - (parentNewBounds.height - parentBounds.height); - icon.setBounds(iconBounds.x, y, - iconBounds.width, iconBounds.height); - } - // Update the new parent bounds for next resize. if (!parentBounds.equals(parentNewBounds)) { parentBounds = parentNewBounds; @@ -1413,10 +1402,6 @@ public class BasicInternalFrameUI extends InternalFrameUI // Cancel a resize in progress if the internal frame // gets a setClosed(true) or dispose(). cancelResize(); - if ((frame.getParent() != null) && componentListenerAdded) { - frame.getParent().removeComponentListener( - componentListener); - } closeFrame(f); } } else if (JInternalFrame.IS_MAXIMUM_PROPERTY == prop) { @@ -1449,16 +1434,6 @@ public class BasicInternalFrameUI extends InternalFrameUI } else { parentBounds = null; } - if ((frame.getParent() != null) && !componentListenerAdded) { - f.getParent().addComponentListener(componentListener); - componentListenerAdded = true; - } else if ((newValue == null) && componentListenerAdded) { - if (f.getParent() != null) { - f.getParent().removeComponentListener( - componentListener); - } - componentListenerAdded = false; - } } else if (JInternalFrame.TITLE_PROPERTY == prop || prop == "closable" || prop == "iconable" || prop == "maximizable") { diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/DesktopIconMover.java b/jdk/src/share/classes/javax/swing/plaf/basic/DesktopIconMover.java new file mode 100644 index 00000000000..deff4f27a5f --- /dev/null +++ b/jdk/src/share/classes/javax/swing/plaf/basic/DesktopIconMover.java @@ -0,0 +1,168 @@ +/* + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.plaf.basic; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.beans.*; + +/** + * DesktopIconMover is intended to move desktop icon + * when parent window is resized. + */ +class DesktopIconMover implements ComponentListener, PropertyChangeListener { + private Component parent; + private JInternalFrame frame; // if not null, DesktopIconMover(frame) + // constructor was used + private JInternalFrame.JDesktopIcon icon; + private Rectangle parentBounds; + private boolean componentListenerAdded = false; + + public DesktopIconMover(JInternalFrame frame) { + if (frame == null) { + throw new NullPointerException("Frame cannot be null"); + } + this.frame = frame; + this.icon = frame.getDesktopIcon(); + if (icon == null) { + throw new NullPointerException( + "frame.getDesktopIcon() cannot be null"); + } + this.parent = frame.getParent(); + if (this.parent != null) { + parentBounds = this.parent.getBounds(); + } + } + + public DesktopIconMover(JInternalFrame.JDesktopIcon icon) { + if (icon == null) { + throw new NullPointerException("Icon cannot be null"); + } + this.icon = icon; + this.parent = icon.getParent(); + if (this.parent != null) { + parentBounds = this.parent.getBounds(); + } + } + + public void installListeners() { + if (frame != null) { + frame.addPropertyChangeListener(this); + } else { + icon.addPropertyChangeListener(this); + } + addComponentListener(); + } + + public void uninstallListeners() { + if (frame != null) { + frame.removePropertyChangeListener(this); + } else { + icon.removePropertyChangeListener(this); + } + removeComponentListener(); + } + + public void propertyChange(PropertyChangeEvent evt) { + String propName = evt.getPropertyName(); + if ("ancestor".equals(propName)) { + Component newAncestor = (Component) evt.getNewValue(); + + // Remove component listener if parent is changing + Component probablyNewParent = getCurrentParent(); + if ((probablyNewParent != null) && + (!probablyNewParent.equals(parent))) { + removeComponentListener(); + parent = probablyNewParent; + } + + if (newAncestor == null) { + removeComponentListener(); + } else { + addComponentListener(); + } + + // Update parentBounds + if (parent != null) { + parentBounds = parent.getBounds(); + } else { + parentBounds = null; + } + } else if (JInternalFrame.IS_CLOSED_PROPERTY.equals(propName)) { + removeComponentListener(); + } + } + + private void addComponentListener() { + if (!componentListenerAdded && (parent != null)) { + parent.addComponentListener(this); + componentListenerAdded = true; + } + } + + private void removeComponentListener() { + if ((parent != null) && componentListenerAdded) { + parent.removeComponentListener(this); + componentListenerAdded = false; + } + } + + private Component getCurrentParent() { + if (frame != null) { + return frame.getParent(); + } else { + return icon.getParent(); + } + } + + public void componentResized(ComponentEvent e) { + if ((parent == null) || (parentBounds == null)) { + return; + } + + Rectangle parentNewBounds = parent.getBounds(); + if ((parentNewBounds == null) || parentNewBounds.equals(parentBounds)) { + return; + } + + // Move desktop icon only in up-down direction + int newIconY = icon.getLocation().y + + (parentNewBounds.height - parentBounds.height); + icon.setLocation(icon.getLocation().x, newIconY); + + parentBounds = parentNewBounds; + } + + public void componentMoved(ComponentEvent e) { + } + + public void componentShown(ComponentEvent e) { + } + + public void componentHidden(ComponentEvent e) { + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/6647340/bug6647340.java b/jdk/test/javax/swing/JInternalFrame/6647340/bug6647340.java new file mode 100644 index 00000000000..b4c180140bd --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/6647340/bug6647340.java @@ -0,0 +1,146 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6647340 + * @summary Checks that iconified internal frame follows + * the main frame borders properly. + * @author Mikhail Lapshin + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import java.awt.*; +import java.beans.PropertyVetoException; + +public class bug6647340 { + private JFrame frame; + private Point location; + private JInternalFrame jif; + + public static void main(String[] args) throws Exception { + final bug6647340 test = new bug6647340(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + test.setupUI(); + } + }); + test.test(); + } finally { + if (test.frame != null) { + test.frame.dispose(); + } + } + } + + private void setupUI() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JDesktopPane desktop = new JDesktopPane(); + frame.add(desktop); + + jif = new JInternalFrame("Internal Frame", true, true, true, true); + jif.setBounds(20, 20, 200, 100); + desktop.add(jif); + jif.setVisible(true); + + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setBounds((screen.width - 400) / 2, (screen.height - 400) / 2, 400, 400); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void test() throws Exception { + realSync(); + test1(); + realSync(); + check1(); + realSync(); + test2(); + realSync(); + check2(); + } + + private void test1() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setIcon(true); + location = jif.getDesktopIcon().getLocation(); + Dimension size = frame.getSize(); + frame.setSize(size.width + 100, size.height + 100); + } + }); + } + + private void test2() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setIcon(false); + } + }); + realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Dimension size = frame.getSize(); + frame.setSize(size.width - 100, size.height - 100); + } + }); + realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + setIcon(true); + } + }); + } + + private void check1() { + if (!jif.getDesktopIcon().getLocation().equals(location)) { + System.out.println("First test passed"); + } else { + throw new RuntimeException("Icon isn't shifted with the frame bounds"); + } + } + + private void check2() { + if (jif.getDesktopIcon().getLocation().equals(location)) { + System.out.println("Second test passed"); + } else { + throw new RuntimeException("Icon isn't located near the frame bottom"); + } + } + + private static void realSync() { + ((SunToolkit) (Toolkit.getDefaultToolkit())).realSync(); + } + + private void setIcon(boolean b) { + try { + jif.setIcon(b); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + } +} From b4be323f02abd645a977db142d496eb8512e7d90 Mon Sep 17 00:00:00 2001 From: Peter Zhelezniakov Date: Tue, 8 Jul 2008 11:36:19 +0400 Subject: [PATCH 008/289] 6635663: make/tools/AutoMulti/{AutoMulti,TestALFGenerator}.java still generate files with wrong legal notices Removed unused files Reviewed-by: ohair --- jdk/make/tools/Makefile | 1 - jdk/make/tools/auto_multi/Makefile | 43 -- .../src/build/tools/automulti/AutoMulti.java | 458 ------------------ .../src/build/tools/automulti/README.txt | 36 -- .../tools/automulti/TestALFGenerator.java | 401 --------------- .../tools/automulti/TestALFLookAndFeel.java | 182 ------- 6 files changed, 1121 deletions(-) delete mode 100644 jdk/make/tools/auto_multi/Makefile delete mode 100644 jdk/make/tools/src/build/tools/automulti/AutoMulti.java delete mode 100644 jdk/make/tools/src/build/tools/automulti/README.txt delete mode 100644 jdk/make/tools/src/build/tools/automulti/TestALFGenerator.java delete mode 100644 jdk/make/tools/src/build/tools/automulti/TestALFLookAndFeel.java diff --git a/jdk/make/tools/Makefile b/jdk/make/tools/Makefile index be1c59a7cfa..c396097c086 100644 --- a/jdk/make/tools/Makefile +++ b/jdk/make/tools/Makefile @@ -32,7 +32,6 @@ include $(BUILDDIR)/common/Defs.gmk SUBDIRS = \ addjsum \ - auto_multi \ buildmetaindex \ commentchecker \ compile_font_config \ diff --git a/jdk/make/tools/auto_multi/Makefile b/jdk/make/tools/auto_multi/Makefile deleted file mode 100644 index f5db35099ad..00000000000 --- a/jdk/make/tools/auto_multi/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# - -# -# Makefile for building the automulti tool -# - -BUILDDIR = ../.. -PACKAGE = build.tools.automulti -PRODUCT = tools -PROGRAM = automulti -include $(BUILDDIR)/common/Defs.gmk - -BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src -BUILDTOOL_MAIN = $(PKGDIR)/AutoMulti.java - -# -# Build tool jar rules. -# -include $(BUILDDIR)/common/BuildToolJar.gmk - diff --git a/jdk/make/tools/src/build/tools/automulti/AutoMulti.java b/jdk/make/tools/src/build/tools/automulti/AutoMulti.java deleted file mode 100644 index a59edc856ca..00000000000 --- a/jdk/make/tools/src/build/tools/automulti/AutoMulti.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright 1998-2001 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package build.tools.automulti; - -import java.lang.reflect.*; -import java.util.*; -import java.io.*; - -/** - * Automatically generates the Multiplexing UI classes - * for Swing. - *

- * To use, type 'java AutoMulti ' where - * is the directory containing the source for Swing's UI classes and - * is the package prefix to use before ".swing.plaf.multi". - * For example: - * - *

- * cd TEST
- * ../../../../build/solaris-sparc/bin/java AutoMulti ../../../../src/share/classes/javax/swing/plaf javax
- * 
- * - * AutoMulti will scour the plaf directory for *UI.java files and - * generate Multi*UI.java files that do the multiplexing thing. - *

- * NOTE: This tool depends upon the existence of and on the - * compiled classes from being somewhere in the class path. - * - * @author Willie Walker - */ -public class AutoMulti { - static String importLines; - - /** - * A silly list of parameter names to use. Skips "i" because we use - * it as a 'for' loop counter. If you want to get fancy, please feel - * to change how parameter names are obtained. This will break if - * someone decides to create a UI method that takes more than 8 - * parameters. Which one is a bug (this breaking or having a method - * with more than eight parameters) is a subjective thing. - */ - public static String[] paramNames = {"a","b","c","d","e","f","g","h"}; - - /** - * Removes the package names (e.g., javax.swing) from the name. - */ - public static String unqualifyName(String name) { - StringTokenizer parser = new StringTokenizer(name,"."); - String unqualifiedName = null; - while (parser.hasMoreTokens()) { - unqualifiedName = parser.nextToken(); - } - return removeDollars(unqualifiedName); - } - - /** - * Strips the extension from the filename. - */ - public static String stripExtension(String name) { - StringTokenizer parser = new StringTokenizer(name,"."); - return parser.nextToken(); - } - - /** - * Adds some spaces. - */ - public static void indent(StringBuffer s, int i) { - while (i > 0) { - s.append(" "); - i--; - } - } - - /** - * Spits out all the beginning stuff. - */ - public static StringBuffer createPreamble(String prefixName) { - StringBuffer s = new StringBuffer(); - s.append("/*\n"); - s.append(" *\n"); - s.append(" * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.\n"); - s.append(" * \n"); - s.append(" * This software is the proprietary information of Sun Microsystems, Inc. \n"); - s.append(" * Use is subject to license terms.\n"); - s.append(" * \n"); - s.append(" */\n"); - s.append("package " + prefixName + ".swing.plaf.multi;\n"); - s.append("\n"); - return s; - } - - /** - * Replaces 'Xxx$Yyy' with "Xxx'. Used by addImport because you - * can't import nested classes directly. - */ - public static String removeNestedClassName(String s) { - int dollarPosition = s.indexOf('$'); - - if (dollarPosition >= 0) { // s contains '$' - StringBuffer sb = new StringBuffer(s); - sb.setLength(dollarPosition); - return sb.toString(); - } else { // no '$' - return s; - } - } - - /** - * Replaces '$' with ".'. Needed for printing inner class names - * for argument and return types. - */ - public static String removeDollars(String s) { - int dollarPosition = s.indexOf('$'); - - if (dollarPosition >= 0) { // s contains '$' - StringBuffer sb = new StringBuffer(s); - while (dollarPosition >= 0) { - //XXX: will there ever be more than one '$'? - sb.replace(dollarPosition, dollarPosition+1, "."); - dollarPosition = sb.indexOf("$", dollarPosition); - } - return sb.toString(); - } else { // no $ - return s; - } - } - - /** - * Adds an import line to the String. - */ - public static void addImport(String s, Class theClass) { - if (!theClass.isPrimitive() && (theClass != Object.class)) { - String className = removeNestedClassName(theClass.getName()); - String importLine = new String("import " + className + ";\n"); - if (importLines.indexOf(importLine) == -1) { - importLines += importLine; - } - } - } - - /** - * Spits out the class header information. - */ - public static void addHeader(StringBuffer s, String className) { - s.append("/**\n"); - s.append(" * A multiplexing UI used to combine " + className + "s.\n"); - s.append(" * \n"); - s.append(" *

This file was automatically generated by AutoMulti.\n"); - s.append(" *\n"); - s.append(" * @author Otto Multey\n"); // Get it? I crack myself up. - s.append(" */\n"); - s.append("public class Multi" + className + " extends " + className + " {\n"); - s.append("\n"); - s.append(" /**\n"); - s.append(" * The vector containing the real UIs. This is populated \n"); - s.append(" * in the call to createUI, and can be obtained by calling\n"); - s.append(" * the getUIs method. The first element is guaranteed to be the real UI \n"); - s.append(" * obtained from the default look and feel.\n"); - s.append(" */\n"); - s.append(" protected Vector uis = new Vector();\n"); - s.append("\n"); - s.append("////////////////////\n"); - s.append("// Common UI methods\n"); - s.append("////////////////////\n"); - s.append("\n"); - s.append(" /**\n"); - s.append(" * Returns the list of UIs associated with this multiplexing UI. This \n"); - s.append(" * allows processing of the UIs by an application aware of multiplexing \n"); - s.append(" * UIs on components.\n"); - s.append(" */\n"); - s.append(" public ComponentUI[] getUIs() {\n"); - s.append(" return MultiLookAndFeel.uisToArray(uis);\n"); - s.append(" }\n"); - } - - /** - * Prints out the code for a method. This is pretty specific to the - * Multiplexing UI code, so don't get any fancy ideas. - */ - public static void addMethod(StringBuffer s, Method m, String origName, String className) { - - // Get the method name and the return type. Be a little careful about arrays. - // - String methodName = unqualifyName(m.getName()); - String returnType; - if (!m.getReturnType().isArray()) { - returnType = unqualifyName(m.getReturnType().toString()); - addImport(importLines,m.getReturnType()); - } else { - returnType = unqualifyName(m.getReturnType().getComponentType().toString()) - + "[]"; - addImport(importLines,m.getReturnType().getComponentType()); - } - - // Print the javadoc - // - s.append("\n"); - if (methodName.equals("createUI")) { - s.append(" /**\n"); - s.append(" * Returns a multiplexing UI instance if any of the auxiliary\n"); - s.append(" * LookAndFeels supports this UI. Otherwise, just returns the \n"); - s.append(" * UI object obtained from the default LookAndFeel.\n"); - s.append(" */\n"); - } else if (!returnType.equals("void")) { - s.append(" /**\n"); - s.append(" * Invokes the " + methodName + " method on each UI handled by this object.\n"); - s.append(" * \n"); - s.append(" * @return the value obtained from the first UI, which is\n"); - s.append(" * the UI obtained from the default LookAndFeel\n"); - s.append(" */\n"); - } else { - s.append(" /**\n"); - s.append(" * Invokes the " + methodName - + " method on each UI handled by this object.\n"); - s.append(" */\n"); - } - - // Print the method signature - // - s.append(" public"); - if (Modifier.isStatic(m.getModifiers())) { - s.append(" static"); - } - s.append(" " + returnType); - s.append(" " + methodName); - s.append("("); - - Class[] params = m.getParameterTypes(); - Class temp; - String braces; - for (int i = 0; i < params.length; i++) { - if (i > 0) { - s.append(", "); - } - temp = params[i]; - braces = new String(""); - while (temp.isArray()) { - braces += "[]"; - temp = temp.getComponentType(); - } - s.append(unqualifyName(temp.getName()) + braces + " " + paramNames[i]); - addImport(importLines,temp); - } - s.append(")"); - - // Don't forget about exceptions - // - Class exceptions[] = m.getExceptionTypes(); - String throwsString = new String(""); - - if (exceptions.length > 0) { - s.append("\n"); - indent(s,12); - s.append("throws "); - for (int i = 0; i < exceptions.length; i++) { - if (i > 0) { - s.append(", "); - } - s.append(unqualifyName(exceptions[i].getName())); - addImport(importLines,exceptions[i]); - } - } - s.append(throwsString + " {\n"); - - // Now print out the contents of the method. We do a special thing - // for the createUI method, another thing if the method returns 'void' - // and a third thing if we don't do either of the first two. If - // you want to squash this down, feel free. - // - if (methodName.equals("createUI")) { - indent(s,8); - s.append("ComponentUI mui = new Multi" + origName + "();\n"); - indent(s,8); - s.append("return MultiLookAndFeel.createUIs(mui,\n"); - indent(s,42); - s.append("((Multi" + origName +") mui).uis,\n"); - indent(s,42); - for (int i = 0; i < params.length; i++) { - if (i > 0) { - s.append(","); - } - s.append(paramNames[i]); - } - s.append(");\n"); - } else if (!returnType.equals("void")) { - indent(s,8); - s.append(returnType + " returnValue = \n"); - indent(s,12); - s.append("((" + className + ") (uis.elementAt(0)))." - + methodName + "("); - for (int i = 0; i < params.length; i++) { - if (i > 0) { - s.append(","); - } - s.append(paramNames[i]); - } - s.append(");\n"); - indent(s,8); - s.append("for (int i = 1; i < uis.size(); i++) {\n"); - indent(s,12); - s.append("((" + className + ") (uis.elementAt(i)))." - + methodName + "("); - for (int i = 0; i < params.length; i++) { - if (i > 0) { - s.append(","); - } - s.append(paramNames[i]); - } - s.append(");\n"); - indent(s,8); - s.append("}\n"); - indent(s,8); - s.append("return returnValue;\n"); - } else { - indent(s,8); - s.append("for (int i = 0; i < uis.size(); i++) {\n"); - indent(s,12); - s.append("((" + className + ") (uis.elementAt(i)))." - + methodName + "("); - for (int i = 0; i < params.length; i++) { - if (i > 0) { - s.append(","); - } - s.append(paramNames[i]); - } - s.append(");\n"); - indent(s,8); - s.append("}\n"); - } - indent(s,4); - s.append("}\n"); - } - - /** - * Takes a plaf class name (e.g., "MenuUI") and generates the corresponding - * Multiplexing UI Java source code (e.g., "MultiMenuUI.java"). - */ - public static void generateFile(String prefixName, String className) { - try { - FileOutputStream fos; - PrintWriter outFile; - - importLines = new String(); - importLines += new String("import java.util.Vector;\n"); - - StringBuffer body = new StringBuffer(); - Class wee = Class.forName(prefixName + ".swing.plaf." + className); - String weeName = unqualifyName(wee.getName()); - addImport(importLines,wee); - while (!weeName.equals("Object")) { - body.append("\n"); - body.append("////////////////////\n"); - body.append("// " + weeName + " methods\n"); - body.append("////////////////////\n"); - Method[] methods = wee.getDeclaredMethods(); - for (int i=0; i < methods.length; i++) { - if (Modifier.isPublic(methods[i].getModifiers())) { - addMethod(body,methods[i],className,weeName); - } - } - wee = wee.getSuperclass(); - weeName = unqualifyName(wee.getName()); - addImport(importLines,wee); - } - - fos = new FileOutputStream("Multi" + className + ".java"); - outFile = new PrintWriter(fos); - StringBuffer outText = createPreamble(prefixName); - outText.append(importLines.toString() + "\n"); - addHeader(outText,className); - outText.append(body.toString()); - outText.append("}\n"); - outFile.write(outText.toString()); - outFile.flush(); - outFile.close(); - } catch (Exception e) { - System.err.println(e); - } - } - - /** - * D'Oh! Something bad happened. - */ - public static void usage(String s) throws IOException { - System.err.println("Usage: AutoMulti [com.sun]"); - throw new IllegalArgumentException(s); - } - - /** - * Takes the plaf directory name and generates the multiplexing UI - * source code. - */ - public static void main(String[] args) throws IOException { - - if (args.length < 1) { - usage(""); - } - - String dirName = args[0]; - File dir = new File(dirName); - if (!dir.isDirectory()) { - System.err.println("No such directory: " + dirName); - usage(""); - } - - String prefixName; - if (args.length > 1) { - prefixName = args[1]; - } else { - prefixName = "com.sun.java"; - } - - String plafUIs[] = dir.list(new UIJavaFilter()); - for (int i = 0; i < plafUIs.length; i++) { - generateFile(prefixName,stripExtension(plafUIs[i])); - } - } -} - -/** - * Only accepts file names of the form *UI.java. The one exception - * is not accepting ComponentUI.java because we don't need to generate - * a multiplexing class for it. - */ -class UIJavaFilter implements FilenameFilter { - public boolean accept(File dir, String name) { - if (name.equals("ComponentUI.java")) { - return false; - } else if (name.endsWith("UI.java")) { - return true; - } else { - return false; - } - } -} diff --git a/jdk/make/tools/src/build/tools/automulti/README.txt b/jdk/make/tools/src/build/tools/automulti/README.txt deleted file mode 100644 index b5de5afe910..00000000000 --- a/jdk/make/tools/src/build/tools/automulti/README.txt +++ /dev/null @@ -1,36 +0,0 @@ -AutoMulti is the tool that automatically generates the -Multi*UI classes for the Multiplexing look and feel. -Instructions for using it are in AutoMulti.java. - -TestALFGenerator is a tool (a variation of AutoMulti) -that automatically generates an auxiliary look and -feel that you can use to test the Multiplexing look -and feel. The TestALF look and feel implements every -method by printing the message "In the xxx method of -the TextALFYyyUI class." and, except in the case of -createUI, returning something meaningless (since, -except in the case of createUI, the return value is -ignored). - -TestALFLookAndFeel.java is the only non-auto-generated -file for the TestALF L&F. If you specify a package -argument to TestALFGenerator, you'll have to change -the code in TestALFLookAndFeel.java to reflect the -package name. - -To test any application with the TestALF, make sure the -compiled TestALF classes are in the class path. Then add -this to the /lib/swing.properties file (which -you'll probably have to create): - -swing.auxiliarylaf=TestALFLookAndFeel - -E.g., if you're running SwingSet2 against your solaris -build, then you'd create/edit the swing.properties file -in /build/solaris-sparc/lib. - -Then run any app. You'll see lots of thrilling "In the -Xxxx method of the Yyy class" messages. If you get anything -else (especially an exception), then you've found a bug. -Probably in the default look and feel. - diff --git a/jdk/make/tools/src/build/tools/automulti/TestALFGenerator.java b/jdk/make/tools/src/build/tools/automulti/TestALFGenerator.java deleted file mode 100644 index 9b07dbc4048..00000000000 --- a/jdk/make/tools/src/build/tools/automulti/TestALFGenerator.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package build.tools.automulti; - -import java.lang.reflect.*; -import java.util.*; -import java.io.*; - -/** - * Automatically generates an auxiliary look and feel to be - * used for testing the Multiplexing look and feel. - *

- * To use, type 'java TestALFGenerator []' where - * is the directory containing the source for Swing's UI classes. - * is an optional argument that specifies the package - * of the TestALF classes. If it's omitted, the classes are in - * the default package. - * For example: - * - *

- * ../../../../build/solaris-sparc/bin/java TestALFGenerator ../../../../src/share/classes/javax/swing/plaf com.myco.myalaf
- * 
- * - * TestALFGenerator will scour the plaf directory for *UI.java files and - * generate TestALF*UI.java files. - *

- * NOTE: This tool depends upon the existence of and on the - * compiled classes from being somewhere in the class path. - * - * @author Willie Walker - */ -public class TestALFGenerator { - static String importLines; - static String packageName; - static String classPrefix = "TestALF"; - - /** - * A silly list of parameter names to use. Skips "i" because we use - * it as a 'for' loop counter. If you want to get fancy, please feel - * to change how parameter names are obtained. This will break if - * someone decides to create a UI method that takes more than 8 - * parameters. Which one is a bug (this breaking or having a method - * with more than eight parameters) is a subjective thing. - */ - public static String[] paramNames = {"a","b","c","d","e","f","g","h"}; - - /** - * Removes the package names (e.g., javax.swing) from the name. - */ - public static String unqualifyName(String name) { - StringTokenizer parser = new StringTokenizer(name,"."); - String unqualifiedName = null; - while (parser.hasMoreTokens()) { - unqualifiedName = parser.nextToken(); - } - return removeDollars(unqualifiedName); - } - - /** - * Strips the extension from the filename. - */ - public static String stripExtension(String name) { - StringTokenizer parser = new StringTokenizer(name,"."); - return parser.nextToken(); - } - - /** - * Adds some spaces. - */ - public static void indent(StringBuffer s, int i) { - while (i > 0) { - s.append(" "); - i--; - } - } - - /** - * Spits out all the beginning stuff. - */ - public static StringBuffer createPreamble(String prefixName) { - StringBuffer s = new StringBuffer(); - s.append("/*\n"); - s.append(" *\n"); - s.append(" * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.\n"); - s.append(" * \n"); - s.append(" * This software is the proprietary information of Sun Microsystems, Inc. \n"); - s.append(" * Use is subject to license terms.\n"); - s.append(" * \n"); - s.append(" */\n"); - if (packageName != null) { - s.append("package " + packageName + ";\n"); - s.append("\n"); - } - return s; - } - - /** - * Replaces 'Xxx$Yyy' with "Xxx'. Used by addImport because you - * can't import nested classes directly. - */ - public static String removeNestedClassName(String s) { - int dollarPosition = s.indexOf('$'); - - if (dollarPosition >= 0) { // s contains '$' - StringBuffer sb = new StringBuffer(s); - sb.setLength(dollarPosition); - return sb.toString(); - } else { // no '$' - return s; - } - } - - /** - * Replaces '$' with ".'. Needed for printing inner class names - * for argument and return types. - */ - public static String removeDollars(String s) { - int dollarPosition = s.indexOf('$'); - - if (dollarPosition >= 0) { // s contains '$' - StringBuffer sb = new StringBuffer(s); - while (dollarPosition >= 0) { - //XXX: will there ever be more than one '$'? - sb.replace(dollarPosition, dollarPosition+1, "."); - dollarPosition = sb.indexOf("$", dollarPosition); - } - return sb.toString(); - } else { // no $ - return s; - } - } - - /** - * Adds an import line to the String. - */ - public static void addImport(String s, Class theClass) { - if (!theClass.isPrimitive() && (theClass != Object.class)) { - String className = removeNestedClassName(theClass.getName()); - String importLine = new String("import " + className + ";\n"); - if (importLines.indexOf(importLine) == -1) { - importLines += importLine; - } - } - } - - /** - * Spits out the class header information. - */ - public static void addHeader(StringBuffer s, String className) { - s.append("/**\n"); - s.append(" * An auxiliary UI for " + className + "s.\n"); - s.append(" * \n"); - s.append(" *

This file was automatically generated by TestALFGenerator.\n"); - s.append(" *\n"); - s.append(" * @author Otto Multey\n"); // Get it? I crack myself up. - s.append(" */\n"); - s.append("public class " + classPrefix + className + " extends " + className + " {\n"); - s.append("\n"); - } - - /** - * Prints out the code for a method. - */ - public static void addMethod(StringBuffer s, Method m, String origName, String className) { - - // Get the method name and the return type. Be a little careful about arrays. - // - String methodName = unqualifyName(m.getName()); - String returnType; - - if (!m.getReturnType().isArray()) { - returnType = unqualifyName(m.getReturnType().toString()); - addImport(importLines,m.getReturnType()); - } else { - returnType = unqualifyName(m.getReturnType().getComponentType().toString()) - + "[]"; - addImport(importLines,m.getReturnType().getComponentType()); - } - - // Print the javadoc - // - s.append("\n"); - - if (methodName.equals("createUI")) { - s.append(" /**\n"); - s.append(" * Returns a UI object for this component.\n"); - s.append(" */\n"); - } else { - s.append(" /**\n"); - s.append(" * Prints a message saying this method has been invoked.\n"); - s.append(" */\n"); - } - - // Print the method signature - // - s.append(" public"); - if (Modifier.isStatic(m.getModifiers())) { - s.append(" static"); - } - s.append(" " + returnType); - s.append(" " + methodName); - s.append("("); - - Class[] params = m.getParameterTypes(); - Class temp; - String braces; - for (int i = 0; i < params.length; i++) { - if (i > 0) { - s.append(", "); - } - temp = params[i]; - braces = new String(""); - while (temp.isArray()) { - braces += "[]"; - temp = temp.getComponentType(); - } - s.append(unqualifyName(temp.getName()) + braces + " " + paramNames[i]); - addImport(importLines,temp); - } - s.append(")"); - - // Don't forget about exceptions - // - Class exceptions[] = m.getExceptionTypes(); - String throwsString = new String(""); - - if (exceptions.length > 0) { - s.append("\n"); - indent(s,12); - s.append("throws "); - for (int i = 0; i < exceptions.length; i++) { - if (i > 0) { - s.append(", "); - } - s.append(unqualifyName(exceptions[i].getName())); - addImport(importLines,exceptions[i]); - } - } - s.append(throwsString + " {\n"); - - // Now print out the contents of the method. - indent(s,8); - s.append("System.out.println(\"In the " + methodName - + " method of the " - + classPrefix + origName + " class.\");\n"); - if (methodName.equals("createUI")) { - indent(s,8); - s.append("return ui;\n"); - } else { - // If we have to return something, do so. - if (!returnType.equals("void")) { - Class rType = m.getReturnType(); - indent(s,8); - if (!rType.isPrimitive()) { - s.append("return null;\n"); - } else if (rType == Boolean.TYPE) { - s.append("return false;\n"); - } else if (rType == Character.TYPE) { - s.append("return '0';\n"); - } else { // byte, short, int, long, float, or double - s.append("return 0;\n"); - } - } - } - - indent(s,4); - s.append("}\n"); - } - - /** - * Takes a plaf class name (e.g., "MenuUI") and generates the corresponding - * TestALF UI Java source code (e.g., "TestALFMenuUI.java"). - */ - public static void generateFile(String prefixName, String className) { - try { - FileOutputStream fos; - PrintWriter outFile; - - importLines = new String(); - importLines += new String("import java.util.Vector;\n"); - - StringBuffer body = new StringBuffer(); - Class wee = Class.forName(prefixName + ".swing.plaf." + className); - String weeName = unqualifyName(wee.getName()); - String thisClassName = classPrefix + className; - addImport(importLines,wee); - - // Declare and initialize the shared UI object. - body.append("\n"); - body.append("////////////////////\n"); - body.append("// Shared UI object\n"); - body.append("////////////////////\n"); - body.append("private final static " + thisClassName - + " ui = new " + thisClassName + "();\n"); - - while (!weeName.equals("Object")) { - body.append("\n"); - body.append("////////////////////\n"); - body.append("// " + weeName + " methods\n"); - body.append("////////////////////\n"); - Method[] methods = wee.getDeclaredMethods(); - for (int i=0; i < methods.length; i++) { - if (Modifier.isPublic(methods[i].getModifiers())) { - addMethod(body,methods[i],className,weeName); - } - } - wee = wee.getSuperclass(); - weeName = unqualifyName(wee.getName()); - addImport(importLines,wee); - } - - fos = new FileOutputStream(classPrefix + className + ".java"); - outFile = new PrintWriter(fos); - StringBuffer outText = createPreamble(prefixName); - outText.append(importLines.toString() + "\n"); - addHeader(outText,className); - outText.append(body.toString()); - outText.append("}\n"); - outFile.write(outText.toString()); - outFile.flush(); - outFile.close(); - } catch (Exception e) { - System.err.println(e); - } - } - - /** - * D'Oh! Something bad happened. - */ - public static void usage(String s) throws IOException { - System.err.println("Usage: java TestALFGenerator []"); - throw new IllegalArgumentException(s); - } - - /** - * Takes the plaf directory name and generates the TestALF UI - * source code. - */ - public static void main(String[] args) throws IOException { - - if (args.length < 1) { - usage(""); - } - - String dirName = args[0]; - File dir = new File(dirName); - if (!dir.isDirectory()) { - System.err.println("No such directory: " + dirName); - usage(""); - } - - if (args.length > 1) { - packageName = args[1]; - } - - String plafUIs[] = dir.list(new UIJavaFilter()); - for (int i = 0; i < plafUIs.length; i++) { - generateFile("javax",stripExtension(plafUIs[i])); - } - } -} - -/** - * Only accepts file names of the form *UI.java. The one exception - * is not accepting ComponentUI.java because we don't need to generate - * a TestALF class for it. - */ -class UIJavaFilter implements FilenameFilter { - public boolean accept(File dir, String name) { - if (name.equals("ComponentUI.java")) { - return false; - } else if (name.endsWith("UI.java")) { - return true; - } else { - return false; - } - } -} diff --git a/jdk/make/tools/src/build/tools/automulti/TestALFLookAndFeel.java b/jdk/make/tools/src/build/tools/automulti/TestALFLookAndFeel.java deleted file mode 100644 index aadab48cac1..00000000000 --- a/jdk/make/tools/src/build/tools/automulti/TestALFLookAndFeel.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ -//package com.myco.myalaf; //search for myalaf for other refs to package name - - -package build.tools.automulti; - -import java.util.Vector; -import java.lang.reflect.Method; -import javax.swing.*; -import javax.swing.plaf.*; - -/** - *

An auxiliary look and feel used for testing the Multiplexing - * look and feel. - *

- * - * @see UIManager#addAuxiliaryLookAndFeel - * @see javax.swing.plaf.multi - * - * @author Kathy Walrath - * @author Will Walker - */ -public class TestALFLookAndFeel extends LookAndFeel { - -////////////////////////////// -// LookAndFeel methods -////////////////////////////// - - /** - * Returns a string, suitable for use in menus, - * that identifies this look and feel. - * - * @return a string such as "Test Auxiliary Look and Feel" - */ - public String getName() { - return "Test Auxiliary Look and Feel"; - } - - /** - * Returns a string, suitable for use by applications/services, - * that identifies this look and feel. - * - * @return "TestALF" - */ - public String getID() { - return "TestALF"; - } - - /** - * Returns a one-line description of this look and feel. - * - * @return a descriptive string such as "Allows multiple UI instances per component instance" - */ - public String getDescription() { - return "Allows multiple UI instances per component instance"; - } - - /** - * Returns false; - * this look and feel is not native to any platform. - * - * @return false - */ - public boolean isNativeLookAndFeel() { - return false; - } - - /** - * Returns true; - * every platform permits this look and feel. - * - * @return true - */ - public boolean isSupportedLookAndFeel() { - return true; - } - - /** - * Creates, initializes, and returns - * the look and feel specific defaults. - * For this look and feel, - * the defaults consist solely of - * mappings of UI class IDs - * (such as "ButtonUI") - * to ComponentUI class names - * (such as "com.myco.myalaf.MultiButtonUI"). - * - * @return an initialized UIDefaults object - * @see javax.swing.JComponent#getUIClassID - */ - public UIDefaults getDefaults() { - System.out.println("In the TestALFLookAndFeel getDefaults method."); - UIDefaults table = new TestALFUIDefaults(); - //String prefix = "com.myco.myalaf.TestALF"; - String prefix = "TestALF"; - Object[] uiDefaults = { - "ButtonUI", prefix + "ButtonUI", - "CheckBoxMenuItemUI", prefix + "MenuItemUI", - "CheckBoxUI", prefix + "ButtonUI", - "ColorChooserUI", prefix + "ColorChooserUI", - "ComboBoxUI", prefix + "ComboBoxUI", - "DesktopIconUI", prefix + "DesktopIconUI", - "DesktopPaneUI", prefix + "DesktopPaneUI", - "EditorPaneUI", prefix + "TextUI", - "FileChooserUI", prefix + "FileChooserUI", - "FormattedTextFieldUI", prefix + "TextUI", - "InternalFrameUI", prefix + "InternalFrameUI", - "LabelUI", prefix + "LabelUI", - "ListUI", prefix + "ListUI", - "MenuBarUI", prefix + "MenuBarUI", - "MenuItemUI", prefix + "MenuItemUI", - "MenuUI", prefix + "MenuItemUI", - "OptionPaneUI", prefix + "OptionPaneUI", - "PanelUI", prefix + "PanelUI", - "PasswordFieldUI", prefix + "TextUI", - "PopupMenuSeparatorUI", prefix + "SeparatorUI", - "PopupMenuUI", prefix + "PopupMenuUI", - "ProgressBarUI", prefix + "ProgressBarUI", - "RadioButtonMenuItemUI", prefix + "MenuItemUI", - "RadioButtonUI", prefix + "ButtonUI", - "RootPaneUI", prefix + "RootPaneUI", - "ScrollBarUI", prefix + "ScrollBarUI", - "ScrollPaneUI", prefix + "ScrollPaneUI", - "SeparatorUI", prefix + "SeparatorUI", - "SliderUI", prefix + "SliderUI", - "SpinnerUI", prefix + "SpinnerUI", - "SplitPaneUI", prefix + "SplitPaneUI", - "TabbedPaneUI", prefix + "TabbedPaneUI", - "TableHeaderUI", prefix + "TableHeaderUI", - "TableUI", prefix + "TableUI", - "TextAreaUI", prefix + "TextUI", - "TextFieldUI", prefix + "TextUI", - "TextPaneUI", prefix + "TextUI", - "ToggleButtonUI", prefix + "ButtonUI", - "ToolBarSeparatorUI", prefix + "SeparatorUI", - "ToolBarUI", prefix + "ToolBarUI", - "ToolTipUI", prefix + "ToolTipUI", - "TreeUI", prefix + "TreeUI", - "ViewportUI", prefix + "ViewportUI", - }; - - table.putDefaults(uiDefaults); - return table; - } - -} - -/** - * We want the Test auxiliary look and feel to be quiet and fallback - * gracefully if it cannot find a UI. This class overrides the - * getUIError method of UIDefaults, which is the method that - * emits error messages when it cannot find a UI class in the - * LAF. - */ -class TestALFUIDefaults extends UIDefaults { - protected void getUIError(String msg) { - System.err.println("Test auxiliary L&F: " + msg); - } -} From e2a366414cf30606390865ef7044efa145133348 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 8 Jul 2008 16:40:38 +0400 Subject: [PATCH 009/289] 4916852: RFE: LTP: BorderLayout Persistence Delegate should use 1.5 API Reviewed-by: peterz, loneid --- .../share/classes/java/beans/MetaData.java | 54 +++++++----- .../XMLEncoder/java_awt_BorderLayout.java | 82 +++++++++++++++++++ .../beans/XMLEncoder/java_awt_Component.java | 58 +++++++++++++ 3 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 jdk/test/java/beans/XMLEncoder/java_awt_BorderLayout.java create mode 100644 jdk/test/java/beans/XMLEncoder/java_awt_Component.java diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index 9bcd505c215..e2cb0326c69 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -986,14 +986,20 @@ class java_awt_Component_PersistenceDelegate extends DefaultPersistenceDelegate // null to defined values after the Windows are made visible - // special case them for now. if (!(oldInstance instanceof java.awt.Window)) { - String[] fieldNames = new String[]{"background", "foreground", "font"}; - for(int i = 0; i < fieldNames.length; i++) { - String name = fieldNames[i]; - Object oldValue = ReflectionUtils.getPrivateField(oldInstance, java.awt.Component.class, name, out.getExceptionListener()); - Object newValue = (newInstance == null) ? null : ReflectionUtils.getPrivateField(newInstance, java.awt.Component.class, name, out.getExceptionListener()); - if (oldValue != null && !oldValue.equals(newValue)) { - invokeStatement(oldInstance, "set" + NameGenerator.capitalize(name), new Object[]{oldValue}, out); - } + Object oldBackground = c.isBackgroundSet() ? c.getBackground() : null; + Object newBackground = c2.isBackgroundSet() ? c2.getBackground() : null; + if (!MetaData.equals(oldBackground, newBackground)) { + invokeStatement(oldInstance, "setBackground", new Object[] { oldBackground }, out); + } + Object oldForeground = c.isForegroundSet() ? c.getForeground() : null; + Object newForeground = c2.isForegroundSet() ? c2.getForeground() : null; + if (!MetaData.equals(oldForeground, newForeground)) { + invokeStatement(oldInstance, "setForeground", new Object[] { oldForeground }, out); + } + Object oldFont = c.isFontSet() ? c.getFont() : null; + Object newFont = c2.isFontSet() ? c2.getFont() : null; + if (!MetaData.equals(oldFont, newFont)) { + invokeStatement(oldInstance, "setFont", new Object[] { oldFont }, out); } } @@ -1104,26 +1110,30 @@ class java_awt_List_PersistenceDelegate extends DefaultPersistenceDelegate { // BorderLayout class java_awt_BorderLayout_PersistenceDelegate extends DefaultPersistenceDelegate { + private static final String[] CONSTRAINTS = { + BorderLayout.NORTH, + BorderLayout.SOUTH, + BorderLayout.EAST, + BorderLayout.WEST, + BorderLayout.CENTER, + BorderLayout.PAGE_START, + BorderLayout.PAGE_END, + BorderLayout.LINE_START, + BorderLayout.LINE_END, + }; + @Override protected void initialize(Class type, Object oldInstance, Object newInstance, Encoder out) { super.initialize(type, oldInstance, newInstance, out); - String[] locations = {"north", "south", "east", "west", "center"}; - String[] names = {java.awt.BorderLayout.NORTH, java.awt.BorderLayout.SOUTH, - java.awt.BorderLayout.EAST, java.awt.BorderLayout.WEST, - java.awt.BorderLayout.CENTER}; - for(int i = 0; i < locations.length; i++) { - Object oldC = ReflectionUtils.getPrivateField(oldInstance, - java.awt.BorderLayout.class, - locations[i], - out.getExceptionListener()); - Object newC = ReflectionUtils.getPrivateField(newInstance, - java.awt.BorderLayout.class, - locations[i], - out.getExceptionListener()); + BorderLayout oldLayout = (BorderLayout) oldInstance; + BorderLayout newLayout = (BorderLayout) newInstance; + for (String constraints : CONSTRAINTS) { + Object oldC = oldLayout.getLayoutComponent(constraints); + Object newC = newLayout.getLayoutComponent(constraints); // Pending, assume any existing elements are OK. if (oldC != null && newC == null) { invokeStatement(oldInstance, "addLayoutComponent", - new Object[]{oldC, names[i]}, out); + new Object[] { oldC, constraints }, out); } } } diff --git a/jdk/test/java/beans/XMLEncoder/java_awt_BorderLayout.java b/jdk/test/java/beans/XMLEncoder/java_awt_BorderLayout.java new file mode 100644 index 00000000000..1eba0c21bac --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/java_awt_BorderLayout.java @@ -0,0 +1,82 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4916852 + * @summary Tests BorderLayout encoding + * @author Sergey Malenkov + */ + +import java.awt.BorderLayout; +import javax.swing.JLabel; + +public final class java_awt_BorderLayout extends AbstractTest { + private static final String[] CONSTRAINTS = { + BorderLayout.NORTH, + BorderLayout.SOUTH, + BorderLayout.EAST, + BorderLayout.WEST, + BorderLayout.CENTER, + BorderLayout.PAGE_START, + BorderLayout.PAGE_END, + BorderLayout.LINE_START, + BorderLayout.LINE_END, + }; + + public static void main(String[] args) { + new java_awt_BorderLayout().test(true); + } + + @Override + protected BorderLayout getObject() { + BorderLayout layout = new BorderLayout(); + update(layout, BorderLayout.EAST); + update(layout, BorderLayout.WEST); + update(layout, BorderLayout.NORTH); + update(layout, BorderLayout.SOUTH); + return layout; + } + + @Override + protected BorderLayout getAnotherObject() { + BorderLayout layout = getObject(); + update(layout, BorderLayout.CENTER); + return layout; + } + + @Override + protected void validate(BorderLayout before, BorderLayout after) { + super.validate(before, after); + + BeanValidator validator = new BeanValidator(); + for (String constraint : CONSTRAINTS) { + validator.validate(before.getLayoutComponent(constraint), + after.getLayoutComponent(constraint)); + } + } + + private static void update(BorderLayout layout, String constraints) { + layout.addLayoutComponent(new JLabel(constraints), constraints); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/java_awt_Component.java b/jdk/test/java/beans/XMLEncoder/java_awt_Component.java new file mode 100644 index 00000000000..a98424a3b7a --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/java_awt_Component.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4916852 + * @summary Tests Component encoding (background, foreground and font) + * @author Sergey Malenkov + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; + +public final class java_awt_Component extends AbstractTest { + public static void main(String[] args) { + new java_awt_Component().test(true); + } + + @Override + protected Component getObject() { + Component component = new MyComponent(); + component.setBackground(Color.WHITE); + component.setFont(new Font(null, Font.BOLD, 5)); + return component; + } + + @Override + protected Component getAnotherObject() { + Component component = new MyComponent(); + component.setForeground(Color.BLACK); + component.setFont(new Font(null, Font.ITALIC, 6)); + return component; + } + + public static final class MyComponent extends Component { + } +} \ No newline at end of file From 1bdca97b29cf1ccfa27349d1198d07849df1c256 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 9 Jul 2008 15:25:38 +0400 Subject: [PATCH 010/289] 6351692: catch(Throwable) in java.beans.MetaData preventing thread shutdown Reviewed-by: peterz, loneid --- .../share/classes/java/beans/DefaultPersistenceDelegate.java | 2 +- jdk/src/share/classes/java/beans/EventHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java index 6553a517200..5339aba83e4 100644 --- a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java +++ b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java @@ -298,7 +298,7 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { oldL = (EventListener[])MethodUtil.invoke(m, oldInstance, new Object[]{}); newL = (EventListener[])MethodUtil.invoke(m, newInstance, new Object[]{}); } - catch (Throwable e2) { + catch (Exception e2) { try { Method m = type.getMethod("getListeners", new Class[]{Class.class}); oldL = (EventListener[])MethodUtil.invoke(m, oldInstance, new Object[]{listenerType}); diff --git a/jdk/src/share/classes/java/beans/EventHandler.java b/jdk/src/share/classes/java/beans/EventHandler.java index 9d50dea91d1..43cd76ff383 100644 --- a/jdk/src/share/classes/java/beans/EventHandler.java +++ b/jdk/src/share/classes/java/beans/EventHandler.java @@ -404,7 +404,7 @@ public class EventHandler implements InvocationHandler { Object newTarget = MethodUtil.invoke(getter, target, new Object[]{}); return applyGetters(newTarget, rest); } - catch (Throwable e) { + catch (Exception e) { throw new RuntimeException("Failed to call method: " + first + " on " + target, e); } From 3916f38bd49205164c4f8c68c12cb46ee64204da Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 9 Jul 2008 19:29:07 +0400 Subject: [PATCH 011/289] 4994637: LTP: java.beans.java_util_Map_PersistenceDelegate: ConcurrentModificationException Reviewed-by: peterz, loneid --- .../share/classes/java/beans/MetaData.java | 2 +- .../java/beans/XMLEncoder/Test4994637.java | 58 +++++++++++++++++++ .../beans/XMLEncoder/java_util_HashMap.java | 24 ++++++-- 3 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/beans/XMLEncoder/Test4994637.java diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index e2cb0326c69..5d8fd697918 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -650,7 +650,7 @@ class java_util_Map_PersistenceDelegate extends DefaultPersistenceDelegate { // Remove the new elements. // Do this first otherwise we undo the adding work. if (newMap != null) { - for ( Object newKey : newMap.keySet() ) { + for (Object newKey : newMap.keySet().toArray()) { // PENDING: This "key" is not in the right environment. if (!oldMap.containsKey(newKey)) { invokeStatement(oldInstance, "remove", new Object[]{newKey}, out); diff --git a/jdk/test/java/beans/XMLEncoder/Test4994637.java b/jdk/test/java/beans/XMLEncoder/Test4994637.java new file mode 100644 index 00000000000..5476a8100bb --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/Test4994637.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4994637 + * @summary Tests custom map encoding + * @author Sergey Malenkov + */ + +import java.util.HashMap; + +public final class Test4994637 extends AbstractTest { + public static void main(String[] args) { + new Test4994637().test(true); + } + + @Override + protected CustomMap getObject() { + return new CustomMap(); + } + + @Override + protected CustomMap getAnotherObject() { + CustomMap map = new CustomMap(); + map.clear(); + map.put(null, "zero"); + return map; + } + + public static final class CustomMap extends HashMap { + public CustomMap() { + put("1", "one"); + put("2", "two"); + put("3", "three"); + } + } +} diff --git a/jdk/test/java/beans/XMLEncoder/java_util_HashMap.java b/jdk/test/java/beans/XMLEncoder/java_util_HashMap.java index 9a9771f80db..d9058003e4d 100644 --- a/jdk/test/java/beans/XMLEncoder/java_util_HashMap.java +++ b/jdk/test/java/beans/XMLEncoder/java_util_HashMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4631471 4921212 + * @bug 4631471 4921212 4994637 * @summary Tests HashMap encoding * @author Sergey Malenkov */ @@ -36,10 +36,17 @@ public final class java_util_HashMap extends AbstractTest> { new java_util_HashMap().test(true); } + @Override protected Map getObject() { - return new HashMap(); + Map map = new HashMap(); + map.put(null, null); + map.put("key", "value"); + map.put("key-null", "null-value"); + map.put("way", "remove"); + return map; } + @Override protected Map getAnotherObject() { Map map = new HashMap(); map.put(null, "null-value"); @@ -48,6 +55,7 @@ public final class java_util_HashMap extends AbstractTest> { return map; } + @Override protected void validate(Map before, Map after) { super.validate(before, after); validate(before); @@ -55,10 +63,18 @@ public final class java_util_HashMap extends AbstractTest> { } private static void validate(Map map) { - if (!map.isEmpty()) { + switch (map.size()) { + case 3: validate(map, null, "null-value"); validate(map, "key", "value"); validate(map, "key-null", null); + break; + case 4: + validate(map, null, null); + validate(map, "key", "value"); + validate(map, "key-null", "null-value"); + validate(map, "way", "remove"); + break; } } From 18dbebd14308d8aa9a2c30ffe2f790f7cff46bd7 Mon Sep 17 00:00:00 2001 From: Jon Masamitsu Date: Wed, 9 Jul 2008 15:08:55 -0700 Subject: [PATCH 012/289] 6672698: mangle_unused_area() should not remangle the entire heap at each collection Maintain a high water mark for the allocations in a space and mangle only up to that high water mark. Reviewed-by: ysr, apetrusenko --- .../binaryTreeDictionary.cpp | 11 +- .../compactibleFreeListSpace.cpp | 2 +- .../freeBlockDictionary.hpp | 1 - .../concurrentMarkSweep/freeChunk.hpp | 2 + .../includeDB_gc_concurrentMarkSweep | 2 + .../vm/gc_implementation/includeDB_gc_parNew | 16 +- .../includeDB_gc_parallelScavenge | 21 +- .../vm/gc_implementation/includeDB_gc_shared | 2 + .../parNew/asParNewGeneration.cpp | 35 ++- .../parNew/parNewGeneration.cpp | 16 +- .../parallelScavenge/asPSYoungGen.cpp | 112 +++++++-- .../parallelScavenge/cardTableExtension.cpp | 6 +- .../parallelScavenge/parallelScavengeHeap.cpp | 20 ++ .../parallelScavenge/parallelScavengeHeap.hpp | 6 + .../parallelScavenge/psMarkSweep.cpp | 16 +- .../parallelScavenge/psMarkSweepDecorator.cpp | 4 +- .../parallelScavenge/psOldGen.cpp | 42 +++- .../parallelScavenge/psOldGen.hpp | 4 + .../parallelScavenge/psParallelCompact.cpp | 36 ++- .../parallelScavenge/psParallelCompact.hpp | 93 ++++++++ .../parallelScavenge/psScavenge.cpp | 19 +- .../parallelScavenge/psYoungGen.cpp | 214 +++++++++++++++--- .../parallelScavenge/psYoungGen.hpp | 8 + .../shared/mutableNUMASpace.cpp | 63 ++++-- .../shared/mutableNUMASpace.hpp | 13 +- .../gc_implementation/shared/mutableSpace.cpp | 55 ++++- .../gc_implementation/shared/mutableSpace.hpp | 42 +++- .../shared/spaceDecorator.cpp | 140 ++++++++++++ .../shared/spaceDecorator.hpp | 141 ++++++++++++ hotspot/src/share/vm/includeDB_core | 10 + hotspot/src/share/vm/includeDB_features | 1 + .../src/share/vm/memory/defNewGeneration.cpp | 118 ++++++++-- .../src/share/vm/memory/defNewGeneration.hpp | 15 +- hotspot/src/share/vm/memory/dump.cpp | 2 +- .../src/share/vm/memory/genCollectedHeap.cpp | 29 +++ .../src/share/vm/memory/genCollectedHeap.hpp | 6 + hotspot/src/share/vm/memory/genMarkSweep.cpp | 4 + hotspot/src/share/vm/memory/generation.cpp | 21 +- hotspot/src/share/vm/memory/generation.hpp | 9 + hotspot/src/share/vm/memory/space.cpp | 81 +++++-- hotspot/src/share/vm/memory/space.hpp | 53 ++++- hotspot/src/share/vm/runtime/globals.hpp | 8 +- .../share/vm/utilities/globalDefinitions.hpp | 6 +- 43 files changed, 1299 insertions(+), 206 deletions(-) create mode 100644 hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp create mode 100644 hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.hpp diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp index 91d381d5501..5064f1104b3 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp @@ -71,8 +71,15 @@ TreeList* TreeList::as_TreeList(TreeChunk* tc) { TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) { TreeChunk* tc = (TreeChunk*) addr; assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk"); - assert(tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL, - "Space should be clear"); + // The space in the heap will have been mangled initially but + // is not remangled when a free chunk is returned to the free list + // (since it is used to maintain the chunk on the free list). + assert((ZapUnusedHeapArea && + SpaceMangler::is_mangled((HeapWord*) tc->size_addr()) && + SpaceMangler::is_mangled((HeapWord*) tc->prev_addr()) && + SpaceMangler::is_mangled((HeapWord*) tc->next_addr())) || + (tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL), + "Space should be clear or mangled"); tc->setSize(size); tc->linkPrev(NULL); tc->linkNext(NULL); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 245807e7319..a0c86f686f0 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -54,7 +54,7 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, _collector(NULL) { _bt.set_space(this); - initialize(mr, true); + initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); // We have all of "mr", all of which we place in the dictionary // as one big chunk. We'll need to decide here which of several // possible alternative dictionary implementations to use. For diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp index b238c023674..fd0448c1a15 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp @@ -22,7 +22,6 @@ * */ - // A FreeBlockDictionary is an abstract superclass that will allow // a number of alternative implementations in the future. class FreeBlockDictionary: public CHeapObj { diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp index be2479475a8..e356dc05092 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp @@ -85,6 +85,8 @@ class FreeChunk VALUE_OBJ_CLASS_SPEC { } debug_only(void* prev_addr() const { return (void*)&_prev; }) + debug_only(void* next_addr() const { return (void*)&_next; }) + debug_only(void* size_addr() const { return (void*)&_size; }) size_t size() const volatile { LP64_ONLY(if (UseCompressedOops) return mark()->get_size(); else ) diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep index d3e253edc7b..621c3f9b94e 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep @@ -28,6 +28,7 @@ binaryTreeDictionary.cpp allocationStats.hpp binaryTreeDictionary.cpp binaryTreeDictionary.hpp binaryTreeDictionary.cpp globals.hpp binaryTreeDictionary.cpp ostream.hpp +binaryTreeDictionary.cpp spaceDecorator.hpp binaryTreeDictionary.hpp freeBlockDictionary.hpp binaryTreeDictionary.hpp freeList.hpp @@ -114,6 +115,7 @@ compactibleFreeListSpace.cpp java.hpp compactibleFreeListSpace.cpp liveRange.hpp compactibleFreeListSpace.cpp oop.inline.hpp compactibleFreeListSpace.cpp resourceArea.hpp +compactibleFreeListSpace.cpp spaceDecorator.hpp compactibleFreeListSpace.cpp universe.inline.hpp compactibleFreeListSpace.cpp vmThread.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew index 7c926792262..e5e5bc17b7c 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew @@ -22,16 +22,17 @@ // // -asParNewGeneration.hpp adaptiveSizePolicy.hpp -asParNewGeneration.hpp parNewGeneration.hpp +asParNewGeneration.hpp adaptiveSizePolicy.hpp +asParNewGeneration.hpp parNewGeneration.hpp -asParNewGeneration.cpp asParNewGeneration.hpp -asParNewGeneration.cpp cmsAdaptiveSizePolicy.hpp +asParNewGeneration.cpp asParNewGeneration.hpp +asParNewGeneration.cpp cmsAdaptiveSizePolicy.hpp asParNewGeneration.cpp cmsGCAdaptivePolicyCounters.hpp -asParNewGeneration.cpp defNewGeneration.inline.hpp -asParNewGeneration.cpp oop.pcgc.inline.hpp -asParNewGeneration.cpp parNewGeneration.hpp +asParNewGeneration.cpp defNewGeneration.inline.hpp +asParNewGeneration.cpp oop.pcgc.inline.hpp +asParNewGeneration.cpp parNewGeneration.hpp asParNewGeneration.cpp referencePolicy.hpp +asParNewGeneration.cpp spaceDecorator.hpp parCardTableModRefBS.cpp allocation.inline.hpp parCardTableModRefBS.cpp cardTableModRefBS.hpp @@ -75,6 +76,7 @@ parNewGeneration.cpp referencePolicy.hpp parNewGeneration.cpp resourceArea.hpp parNewGeneration.cpp sharedHeap.hpp parNewGeneration.cpp space.hpp +parNewGeneration.cpp spaceDecorator.hpp parNewGeneration.cpp workgroup.hpp parNewGeneration.hpp defNewGeneration.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge index 8a2a7a6127b..3406c59d91f 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge @@ -53,14 +53,15 @@ asPSOldGen.cpp java.hpp asPSOldGen.cpp oop.inline.hpp asPSOldGen.cpp parallelScavengeHeap.hpp asPSOldGen.cpp psMarkSweepDecorator.hpp -asPSOldGen.cpp asPSOldGen.hpp +asPSOldGen.cpp asPSOldGen.hpp asPSYoungGen.hpp generationCounters.hpp asPSYoungGen.hpp mutableSpace.hpp asPSYoungGen.hpp objectStartArray.hpp asPSYoungGen.hpp spaceCounters.hpp asPSYoungGen.hpp psVirtualspace.hpp -asPSYoungGen.hpp psYoungGen.hpp +asPSYoungGen.hpp psYoungGen.hpp +asPSYoungGen.hpp spaceDecorator.hpp asPSYoungGen.cpp gcUtil.hpp asPSYoungGen.cpp java.hpp @@ -68,8 +69,9 @@ asPSYoungGen.cpp oop.inline.hpp asPSYoungGen.cpp parallelScavengeHeap.hpp asPSYoungGen.cpp psMarkSweepDecorator.hpp asPSYoungGen.cpp psScavenge.hpp -asPSYoungGen.cpp asPSYoungGen.hpp -asPSYoungGen.cpp psYoungGen.hpp +asPSYoungGen.cpp asPSYoungGen.hpp +asPSYoungGen.cpp psYoungGen.hpp +asPSYoungGen.cpp spaceDecorator.hpp cardTableExtension.cpp cardTableExtension.hpp cardTableExtension.cpp gcTaskManager.hpp @@ -225,6 +227,7 @@ psMarkSweep.cpp psYoungGen.hpp psMarkSweep.cpp referencePolicy.hpp psMarkSweep.cpp referenceProcessor.hpp psMarkSweep.cpp safepoint.hpp +psMarkSweep.cpp spaceDecorator.hpp psMarkSweep.cpp symbolTable.hpp psMarkSweep.cpp systemDictionary.hpp psMarkSweep.cpp vmThread.hpp @@ -239,6 +242,7 @@ psMarkSweepDecorator.cpp oop.inline.hpp psMarkSweepDecorator.cpp parallelScavengeHeap.hpp psMarkSweepDecorator.cpp psMarkSweep.hpp psMarkSweepDecorator.cpp psMarkSweepDecorator.hpp +psMarkSweepDecorator.cpp spaceDecorator.hpp psMarkSweepDecorator.cpp systemDictionary.hpp psMarkSweepDecorator.hpp mutableSpace.hpp @@ -290,6 +294,7 @@ psOldGen.cpp oop.inline.hpp psOldGen.cpp parallelScavengeHeap.hpp psOldGen.cpp psMarkSweepDecorator.hpp psOldGen.cpp psOldGen.hpp +psOldGen.cpp spaceDecorator.hpp psOldGen.hpp psGenerationCounters.hpp psOldGen.hpp mutableSpace.hpp @@ -351,6 +356,7 @@ psScavenge.cpp psTasks.hpp psScavenge.cpp referencePolicy.hpp psScavenge.cpp referenceProcessor.hpp psScavenge.cpp resourceArea.hpp +psScavenge.cpp spaceDecorator.hpp psScavenge.cpp threadCritical.hpp psScavenge.cpp vmThread.hpp psScavenge.cpp vm_operations.hpp @@ -409,8 +415,8 @@ psVirtualspace.hpp virtualspace.hpp psVirtualspace.cpp os.hpp psVirtualspace.cpp os_.inline.hpp -psVirtualspace.cpp psVirtualspace.hpp -psVirtualspace.cpp virtualspace.hpp +psVirtualspace.cpp psVirtualspace.hpp +psVirtualspace.cpp virtualspace.hpp psYoungGen.cpp gcUtil.hpp psYoungGen.cpp java.hpp @@ -419,7 +425,8 @@ psYoungGen.cpp parallelScavengeHeap.hpp psYoungGen.cpp psMarkSweepDecorator.hpp psYoungGen.cpp psScavenge.hpp psYoungGen.cpp psYoungGen.hpp -psYoungGen.cpp mutableNUMASpace.hpp +psYoungGen.cpp mutableNUMASpace.hpp +psYoungGen.cpp spaceDecorator.hpp psYoungGen.hpp psGenerationCounters.hpp psYoungGen.hpp mutableSpace.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared b/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared index 367fccf4807..7729f5eb830 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared @@ -56,6 +56,7 @@ markSweep.inline.hpp psParallelCompact.hpp mutableNUMASpace.cpp mutableNUMASpace.hpp mutableNUMASpace.cpp oop.inline.hpp mutableNUMASpace.cpp sharedHeap.hpp +mutableNUMASpace.cpp spaceDecorator.hpp mutableNUMASpace.cpp thread_.inline.hpp mutableNUMASpace.hpp mutableSpace.hpp @@ -64,6 +65,7 @@ mutableNUMASpace.hpp gcUtil.hpp mutableSpace.cpp mutableSpace.hpp mutableSpace.cpp oop.inline.hpp mutableSpace.cpp safepoint.hpp +mutableSpace.cpp spaceDecorator.hpp mutableSpace.cpp thread.hpp spaceCounters.cpp resourceArea.hpp diff --git a/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp index fa4a554b976..abdeb185a93 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp @@ -162,10 +162,9 @@ bool ASParNewGeneration::resize_generation(size_t eden_size, // Grow the generation size_t change = desired_size - orig_size; assert(change % alignment == 0, "just checking"); - if (!virtual_space()->expand_by(change)) { + if (expand(change)) { return false; // Error if we fail to resize! } - size_changed = true; } else if (desired_size < orig_size) { size_t desired_change = orig_size - desired_size; @@ -222,7 +221,9 @@ void ASParNewGeneration::reset_survivors_after_shrink() { // Was there a shrink of the survivor space? if (new_end < to()->end()) { MemRegion mr(to()->bottom(), new_end); - to()->initialize(mr, false /* clear */); + to()->initialize(mr, + SpaceDecorator::DontClear, + SpaceDecorator::DontMangle); } } } @@ -322,9 +323,7 @@ void ASParNewGeneration::resize_spaces(size_t requested_eden_size, pointer_delta(from_start, eden_start, sizeof(char))); } -// tty->print_cr("eden_size before: " SIZE_FORMAT, eden_size); eden_size = align_size_down(eden_size, alignment); -// tty->print_cr("eden_size after: " SIZE_FORMAT, eden_size); eden_end = eden_start + eden_size; assert(eden_end >= eden_start, "addition overflowed") @@ -501,11 +500,31 @@ void ASParNewGeneration::resize_spaces(size_t requested_eden_size, size_t old_from = from()->capacity(); size_t old_to = to()->capacity(); + // If not clearing the spaces, do some checking to verify that + // the spaces are already mangled. + + // Must check mangling before the spaces are reshaped. Otherwise, + // the bottom or end of one space may have moved into another + // a failure of the check may not correctly indicate which space + // is not properly mangled. + if (ZapUnusedHeapArea) { + HeapWord* limit = (HeapWord*) virtual_space()->high(); + eden()->check_mangled_unused_area(limit); + from()->check_mangled_unused_area(limit); + to()->check_mangled_unused_area(limit); + } + // The call to initialize NULL's the next compaction space - eden()->initialize(edenMR, true); + eden()->initialize(edenMR, + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); eden()->set_next_compaction_space(from()); - to()->initialize(toMR , true); - from()->initialize(fromMR, false); // Note, not cleared! + to()->initialize(toMR , + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); + from()->initialize(fromMR, + SpaceDecorator::DontClear, + SpaceDecorator::DontMangle); assert(from()->top() == old_from_top, "from top changed!"); diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index 8beea55ee97..e2f7ef1541c 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -727,7 +727,7 @@ void ParNewGeneration::collect(bool full, SpecializationStats::clear(); age_table()->clear(); - to()->clear(); + to()->clear(SpaceDecorator::Mangle); gch->save_marks(); assert(workers != NULL, "Need parallel worker threads."); @@ -793,8 +793,18 @@ void ParNewGeneration::collect(bool full, } if (!promotion_failed()) { // Swap the survivor spaces. - eden()->clear(); - from()->clear(); + eden()->clear(SpaceDecorator::Mangle); + from()->clear(SpaceDecorator::Mangle); + if (ZapUnusedHeapArea) { + // This is now done here because of the piece-meal mangling which + // can check for valid mangling at intermediate points in the + // collection(s). When a minor collection fails to collect + // sufficient space resizing of the young generation can occur + // an redistribute the spaces in the young generation. Mangle + // here so that unzapped regions don't get distributed to + // other spaces. + to()->mangle_unused_area(); + } swap_spaces(); assert(to()->is_empty(), "to space should be empty now"); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp index 7ef34bb89bd..d1efec8ff71 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp @@ -170,9 +170,20 @@ bool ASPSYoungGen::resize_generation(size_t eden_size, size_t survivor_size) { if (desired_size > orig_size) { // Grow the generation size_t change = desired_size - orig_size; + HeapWord* prev_low = (HeapWord*) virtual_space()->low(); if (!virtual_space()->expand_by(change)) { return false; } + if (ZapUnusedHeapArea) { + // Mangle newly committed space immediately because it + // can be done here more simply that after the new + // spaces have been computed. + HeapWord* new_low = (HeapWord*) virtual_space()->low(); + assert(new_low < prev_low, "Did not grow"); + + MemRegion mangle_region(new_low, prev_low); + SpaceMangler::mangle_region(mangle_region); + } size_changed = true; } else if (desired_size < orig_size) { size_t desired_change = orig_size - desired_size; @@ -215,8 +226,10 @@ bool ASPSYoungGen::resize_generation(size_t eden_size, size_t survivor_size) { // current implementation does not allow holes between the spaces // _young_generation_boundary has to be reset because it changes. // so additional verification + void ASPSYoungGen::resize_spaces(size_t requested_eden_size, size_t requested_survivor_size) { + assert(UseAdaptiveSizePolicy, "sanity check"); assert(requested_eden_size > 0 && requested_survivor_size > 0, "just checking"); @@ -276,22 +289,42 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size, ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); const size_t alignment = heap->intra_heap_alignment(); + const bool maintain_minimum = + (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size(); + bool eden_from_to_order = from_start < to_start; // Check whether from space is below to space - if (from_start < to_start) { + if (eden_from_to_order) { // Eden, from, to + if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" Eden, from, to:"); } // Set eden - // Compute how big eden can be, then adjust end. - // See comment in PSYoungGen::resize_spaces() on - // calculating eden_end. - const size_t eden_size = MIN2(requested_eden_size, - pointer_delta(from_start, - eden_start, - sizeof(char))); + // "requested_eden_size" is a goal for the size of eden + // and may not be attainable. "eden_size" below is + // calculated based on the location of from-space and + // the goal for the size of eden. from-space is + // fixed in place because it contains live data. + // The calculation is done this way to avoid 32bit + // overflow (i.e., eden_start + requested_eden_size + // may too large for representation in 32bits). + size_t eden_size; + if (maintain_minimum) { + // Only make eden larger than the requested size if + // the minimum size of the generation has to be maintained. + // This could be done in general but policy at a higher + // level is determining a requested size for eden and that + // should be honored unless there is a fundamental reason. + eden_size = pointer_delta(from_start, + eden_start, + sizeof(char)); + } else { + eden_size = MIN2(requested_eden_size, + pointer_delta(from_start, eden_start, sizeof(char))); + } + eden_end = eden_start + eden_size; assert(eden_end >= eden_start, "addition overflowed") @@ -371,12 +404,14 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size, to_start = MAX2(to_start, eden_start + alignment); // Compute how big eden can be, then adjust end. - // See comment in PSYoungGen::resize_spaces() on - // calculating eden_end. - const size_t eden_size = MIN2(requested_eden_size, - pointer_delta(to_start, - eden_start, - sizeof(char))); + // See comments above on calculating eden_end. + size_t eden_size; + if (maintain_minimum) { + eden_size = pointer_delta(to_start, eden_start, sizeof(char)); + } else { + eden_size = MIN2(requested_eden_size, + pointer_delta(to_start, eden_start, sizeof(char))); + } eden_end = eden_start + eden_size; assert(eden_end >= eden_start, "addition overflowed") @@ -423,9 +458,47 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size, size_t old_from = from_space()->capacity_in_bytes(); size_t old_to = to_space()->capacity_in_bytes(); - eden_space()->initialize(edenMR, true); - to_space()->initialize(toMR , true); - from_space()->initialize(fromMR, false); // Note, not cleared! + if (ZapUnusedHeapArea) { + // NUMA is a special case because a numa space is not mangled + // in order to not prematurely bind its address to memory to + // the wrong memory (i.e., don't want the GC thread to first + // touch the memory). The survivor spaces are not numa + // spaces and are mangled. + if (UseNUMA) { + if (eden_from_to_order) { + mangle_survivors(from_space(), fromMR, to_space(), toMR); + } else { + mangle_survivors(to_space(), toMR, from_space(), fromMR); + } + } + + // If not mangling the spaces, do some checking to verify that + // the spaces are already mangled. + // The spaces should be correctly mangled at this point so + // do some checking here. Note that they are not being mangled + // in the calls to initialize(). + // Must check mangling before the spaces are reshaped. Otherwise, + // the bottom or end of one space may have moved into an area + // covered by another space and a failure of the check may + // not correctly indicate which space is not properly mangled. + + HeapWord* limit = (HeapWord*) virtual_space()->high(); + eden_space()->check_mangled_unused_area(limit); + from_space()->check_mangled_unused_area(limit); + to_space()->check_mangled_unused_area(limit); + } + // When an existing space is being initialized, it is not + // mangled because the space has been previously mangled. + eden_space()->initialize(edenMR, + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); + to_space()->initialize(toMR, + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); + from_space()->initialize(fromMR, + SpaceDecorator::DontClear, + SpaceDecorator::DontMangle); + PSScavenge::set_young_generation_boundary(eden_space()->bottom()); assert(from_space()->top() == old_from_top, "from top changed!"); @@ -446,7 +519,6 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size, } space_invariants(); } - void ASPSYoungGen::reset_after_change() { assert_locked_or_safepoint(Heap_lock); @@ -458,7 +530,9 @@ void ASPSYoungGen::reset_after_change() { HeapWord* eden_bottom = eden_space()->bottom(); if (new_eden_bottom != eden_bottom) { MemRegion eden_mr(new_eden_bottom, eden_space()->end()); - eden_space()->initialize(eden_mr, true); + eden_space()->initialize(eden_mr, + SpaceDecorator::Clear, + SpaceDecorator::Mangle); PSScavenge::set_young_generation_boundary(eden_space()->bottom()); } MemRegion cmr((HeapWord*)virtual_space()->low(), diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp index 2b2c6f87c51..affd72fc2b1 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp @@ -666,9 +666,9 @@ void CardTableExtension::resize_commit_uncommit(int changed_region, HeapWord* new_end_for_commit = MIN2(cur_committed.end(), _guard_region.start()); - MemRegion new_committed = - MemRegion(new_start_aligned, new_end_for_commit); - if(!new_committed.is_empty()) { + if(new_start_aligned < new_end_for_commit) { + MemRegion new_committed = + MemRegion(new_start_aligned, new_end_for_commit); if (!os::commit_memory((char*)new_committed.start(), new_committed.byte_size())) { vm_exit_out_of_memory(new_committed.byte_size(), diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index 6fd50b39fc5..85ffd751270 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -938,3 +938,23 @@ void ParallelScavengeHeap::resize_old_gen(size_t desired_free_space) { // Delegate the resize to the generation. _old_gen->resize(desired_free_space); } + +#ifndef PRODUCT +void ParallelScavengeHeap::record_gen_tops_before_GC() { + if (ZapUnusedHeapArea) { + young_gen()->record_spaces_top(); + old_gen()->record_spaces_top(); + perm_gen()->record_spaces_top(); + } +} + +void ParallelScavengeHeap::gen_mangle_unused_area() { + if (ZapUnusedHeapArea) { + young_gen()->eden_space()->mangle_unused_area(); + young_gen()->to_space()->mangle_unused_area(); + young_gen()->from_space()->mangle_unused_area(); + old_gen()->object_space()->mangle_unused_area(); + perm_gen()->object_space()->mangle_unused_area(); + } +} +#endif diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp index d26eec48882..a4c141840b7 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp @@ -213,6 +213,12 @@ class ParallelScavengeHeap : public CollectedHeap { // Resize the old generation. The reserved space for the // generation may be expanded in preparation for the resize. void resize_old_gen(size_t desired_free_space); + + // Save the tops of the spaces in all generations + void record_gen_tops_before_GC() PRODUCT_RETURN; + + // Mangle the unused parts of all spaces in the heap + void gen_mangle_unused_area() PRODUCT_RETURN; }; inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp index 3a817a2049e..d42d4fc26df 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp @@ -98,6 +98,9 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { // Increment the invocation count heap->increment_total_collections(true /* full */); + // Save information needed to minimize mangling + heap->record_gen_tops_before_GC(); + // We need to track unique mark sweep invocations as well. _total_invocations++; @@ -188,6 +191,12 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { deallocate_stacks(); + if (ZapUnusedHeapArea) { + // Do a complete mangle (top to end) because the usage for + // scratch does not maintain a top pointer. + young_gen->to_space()->mangle_unused_area_complete(); + } + eden_empty = young_gen->eden_space()->is_empty(); if (!eden_empty) { eden_empty = absorb_live_data_from_eden(size_policy, young_gen, old_gen); @@ -198,7 +207,7 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { Universe::update_heap_info_at_gc(); survivors_empty = young_gen->from_space()->is_empty() && - young_gen->to_space()->is_empty(); + young_gen->to_space()->is_empty(); young_gen_empty = eden_empty && survivors_empty; BarrierSet* bs = heap->barrier_set(); @@ -344,6 +353,11 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { perm_gen->verify_object_start_array(); } + if (ZapUnusedHeapArea) { + old_gen->object_space()->check_mangled_unused_area_complete(); + perm_gen->object_space()->check_mangled_unused_area_complete(); + } + NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); if (PrintHeapAtGC) { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp index cec3a48db1a..c0fa75a8c98 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp @@ -438,5 +438,7 @@ void PSMarkSweepDecorator::compact(bool mangle_free_space ) { "should point inside space"); space()->set_top(compaction_top()); - if (mangle_free_space) space()->mangle_unused_area(); + if (mangle_free_space) { + space()->mangle_unused_area(); + } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp index f92d291cc4e..89515f945c6 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp @@ -87,6 +87,15 @@ void PSOldGen::initialize_work(const char* perf_data_name, int level) { MemRegion cmr((HeapWord*)virtual_space()->low(), (HeapWord*)virtual_space()->high()); + if (ZapUnusedHeapArea) { + // Mangle newly committed space immediately rather than + // waiting for the initialization of the space even though + // mangling is related to spaces. Doing it here eliminates + // the need to carry along information that a complete mangling + // (bottom to end) needs to be done. + SpaceMangler::mangle_region(cmr); + } + Universe::heap()->barrier_set()->resize_covered_region(cmr); CardTableModRefBS* _ct = (CardTableModRefBS*)Universe::heap()->barrier_set(); @@ -112,7 +121,9 @@ void PSOldGen::initialize_work(const char* perf_data_name, int level) { if (_object_space == NULL) vm_exit_during_initialization("Could not allocate an old gen space"); - object_space()->initialize(cmr, true); + object_space()->initialize(cmr, + SpaceDecorator::Clear, + SpaceDecorator::Mangle); _object_mark_sweep = new PSMarkSweepDecorator(_object_space, start_array(), MarkSweepDeadRatio); @@ -232,6 +243,19 @@ bool PSOldGen::expand_by(size_t bytes) { assert_locked_or_safepoint(Heap_lock); bool result = virtual_space()->expand_by(bytes); if (result) { + if (ZapUnusedHeapArea) { + // We need to mangle the newly expanded area. The memregion spans + // end -> new_end, we assume that top -> end is already mangled. + // Do the mangling before post_resize() is called because + // the space is available for allocation after post_resize(); + HeapWord* const virtual_space_high = (HeapWord*) virtual_space()->high(); + assert(object_space()->end() < virtual_space_high, + "Should be true before post_resize()"); + MemRegion mangle_region(object_space()->end(), virtual_space_high); + // Note that the object space has not yet been updated to + // coincede with the new underlying virtual space. + SpaceMangler::mangle_region(mangle_region); + } post_resize(); if (UsePerfData) { _space_counters->update_capacity(); @@ -348,16 +372,7 @@ void PSOldGen::post_resize() { start_array()->set_covered_region(new_memregion); Universe::heap()->barrier_set()->resize_covered_region(new_memregion); - // Did we expand? HeapWord* const virtual_space_high = (HeapWord*) virtual_space()->high(); - if (object_space()->end() < virtual_space_high) { - // We need to mangle the newly expanded area. The memregion spans - // end -> new_end, we assume that top -> end is already mangled. - // This cannot be safely tested for, as allocation may be taking - // place. - MemRegion mangle_region(object_space()->end(), virtual_space_high); - object_space()->mangle_region(mangle_region); - } // ALWAYS do this last!! object_space()->set_end(virtual_space_high); @@ -462,3 +477,10 @@ void PSOldGen::verify_object_start_array() { VerifyObjectStartArrayClosure check( this, &_start_array ); object_iterate(&check); } + +#ifndef PRODUCT +void PSOldGen::record_spaces_top() { + assert(ZapUnusedHeapArea, "Not mangling unused space"); + object_space()->set_top_for_allocations(); +} +#endif diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp index a7a68bdf68e..7e1d30811e6 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp @@ -185,4 +185,8 @@ class PSOldGen : public CHeapObj { // Printing support virtual const char* name() const { return _name; } + + // Debugging support + // Save the tops of all spaces for later use during mangling. + void record_spaces_top() PRODUCT_RETURN; }; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 8f9ec0e59c3..2b25332ab96 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -1058,6 +1058,10 @@ void PSParallelCompact::post_compact() ref_processor()->enqueue_discovered_references(NULL); + if (ZapUnusedHeapArea) { + heap->gen_mangle_unused_area(); + } + // Update time of last GC reset_millis_since_last_gc(); } @@ -1959,6 +1963,11 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { PSPermGen* perm_gen = heap->perm_gen(); PSAdaptiveSizePolicy* size_policy = heap->size_policy(); + if (ZapUnusedHeapArea) { + // Save information needed to minimize mangling + heap->record_gen_tops_before_GC(); + } + _print_phases = PrintGCDetails && PrintParallelOldGCPhaseTimes; // Make sure data structures are sane, make the heap parsable, and do other @@ -2127,17 +2136,19 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { size_t max_eden_size = young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes(); - size_policy->compute_generation_free_space(young_gen->used_in_bytes(), - young_gen->eden_space()->used_in_bytes(), - old_gen->used_in_bytes(), - perm_gen->used_in_bytes(), - young_gen->eden_space()->capacity_in_bytes(), - old_gen->max_gen_size(), - max_eden_size, - true /* full gc*/, - gc_cause); + size_policy->compute_generation_free_space( + young_gen->used_in_bytes(), + young_gen->eden_space()->used_in_bytes(), + old_gen->used_in_bytes(), + perm_gen->used_in_bytes(), + young_gen->eden_space()->capacity_in_bytes(), + old_gen->max_gen_size(), + max_eden_size, + true /* full gc*/, + gc_cause); - heap->resize_old_gen(size_policy->calculated_old_free_size_in_bytes()); + heap->resize_old_gen( + size_policy->calculated_old_free_size_in_bytes()); // Don't resize the young generation at an major collection. A // desired young generation size may have been calculated but @@ -2210,6 +2221,11 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { perm_gen->verify_object_start_array(); } + if (ZapUnusedHeapArea) { + old_gen->object_space()->check_mangled_unused_area_complete(); + perm_gen->object_space()->check_mangled_unused_area_complete(); + } + NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); collection_exit.update(); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp index 9566821169b..4b1f8572fa5 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp @@ -716,6 +716,99 @@ class BitBlockUpdateClosure: public ParMarkBitMapClosure { virtual IterationStatus do_addr(HeapWord* addr, size_t words); }; +// The UseParallelOldGC collector is a stop-the-world garbage +// collector that does parts of the collection using parallel threads. +// The collection includes the tenured generation and the young +// generation. The permanent generation is collected at the same +// time as the other two generations but the permanent generation +// is collect by a single GC thread. The permanent generation is +// collected serially because of the requirement that during the +// processing of a klass AAA, any objects reference by AAA must +// already have been processed. This requirement is enforced by +// a left (lower address) to right (higher address) sliding compaction. +// +// There are four phases of the collection. +// +// - marking phase +// - summary phase +// - compacting phase +// - clean up phase +// +// Roughly speaking these phases correspond, respectively, to +// - mark all the live objects +// - calculate the destination of each object at the end of the collection +// - move the objects to their destination +// - update some references and reinitialize some variables +// +// These three phases are invoked in PSParallelCompact::invoke_no_policy(). +// The marking phase is implemented in PSParallelCompact::marking_phase() +// and does a complete marking of the heap. +// The summary phase is implemented in PSParallelCompact::summary_phase(). +// The move and update phase is implemented in PSParallelCompact::compact(). +// +// A space that is being collected is divided into chunks and with +// each chunk is associated an object of type ParallelCompactData. +// Each chunk is of a fixed size and typically will contain more than +// 1 object and may have parts of objects at the front and back of the +// chunk. +// +// chunk -----+---------------------+---------- +// objects covered [ AAA )[ BBB )[ CCC )[ DDD ) +// +// The marking phase does a complete marking of all live objects in the +// heap. The marking also compiles the size of the data for +// all live objects covered by the chunk. This size includes the +// part of any live object spanning onto the chunk (part of AAA +// if it is live) from the front, all live objects contained in the chunk +// (BBB and/or CCC if they are live), and the part of any live objects +// covered by the chunk that extends off the chunk (part of DDD if it is +// live). The marking phase uses multiple GC threads and marking is +// done in a bit array of type ParMarkBitMap. The marking of the +// bit map is done atomically as is the accumulation of the size of the +// live objects covered by a chunk. +// +// The summary phase calculates the total live data to the left of +// each chunk XXX. Based on that total and the bottom of the space, +// it can calculate the starting location of the live data in XXX. +// The summary phase calculates for each chunk XXX quantites such as +// +// - the amount of live data at the beginning of a chunk from an object +// entering the chunk. +// - the location of the first live data on the chunk +// - a count of the number of chunks receiving live data from XXX. +// +// See ParallelCompactData for precise details. The summary phase also +// calculates the dense prefix for the compaction. The dense prefix +// is a portion at the beginning of the space that is not moved. The +// objects in the dense prefix do need to have their object references +// updated. See method summarize_dense_prefix(). +// +// The summary phase is done using 1 GC thread. +// +// The compaction phase moves objects to their new location and updates +// all references in the object. +// +// A current exception is that objects that cross a chunk boundary +// are moved but do not have their references updated. References are +// not updated because it cannot easily be determined if the klass +// pointer KKK for the object AAA has been updated. KKK likely resides +// in a chunk to the left of the chunk containing AAA. These AAA's +// have there references updated at the end in a clean up phase. +// See the method PSParallelCompact::update_deferred_objects(). An +// alternate strategy is being investigated for this deferral of updating. +// +// Compaction is done on a chunk basis. A chunk that is ready to be +// filled is put on a ready list and GC threads take chunk off the list +// and fill them. A chunk is ready to be filled if it +// empty of live objects. Such a chunk may have been initially +// empty (only contained +// dead objects) or may have had all its live objects copied out already. +// A chunk that compacts into itself is also ready for filling. The +// ready list is initially filled with empty chunks and chunks compacting +// into themselves. There is always at least 1 chunk that can be put on +// the ready list. The chunks are atomically added and removed from +// the ready list. +// class PSParallelCompact : AllStatic { public: // Convenient access to type names. diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index 5f960dc9ece..7d655878206 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -265,6 +265,11 @@ bool PSScavenge::invoke_no_policy() { young_gen->eden_space()->accumulate_statistics(); } + if (ZapUnusedHeapArea) { + // Save information needed to minimize mangling + heap->record_gen_tops_before_GC(); + } + if (PrintHeapAtGC) { Universe::print_heap_before_gc(); } @@ -315,7 +320,7 @@ bool PSScavenge::invoke_no_policy() { if (!ScavengeWithObjectsInToSpace) { assert(young_gen->to_space()->is_empty(), "Attempt to scavenge with live objects in to_space"); - young_gen->to_space()->clear(); + young_gen->to_space()->clear(SpaceDecorator::Mangle); } else if (ZapUnusedHeapArea) { young_gen->to_space()->mangle_unused_area(); } @@ -437,8 +442,10 @@ bool PSScavenge::invoke_no_policy() { if (!promotion_failure_occurred) { // Swap the survivor spaces. - young_gen->eden_space()->clear(); - young_gen->from_space()->clear(); + + + young_gen->eden_space()->clear(SpaceDecorator::Mangle); + young_gen->from_space()->clear(SpaceDecorator::Mangle); young_gen->swap_spaces(); size_t survived = young_gen->from_space()->used_in_bytes(); @@ -600,6 +607,12 @@ bool PSScavenge::invoke_no_policy() { Universe::print_heap_after_gc(); } + if (ZapUnusedHeapArea) { + young_gen->eden_space()->check_mangled_unused_area_complete(); + young_gen->from_space()->check_mangled_unused_area_complete(); + young_gen->to_space()->check_mangled_unused_area_complete(); + } + scavenge_exit.update(); if (PrintGCTaskTimeStamps) { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp index b7088556bdc..56a8491f6b0 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp @@ -36,7 +36,7 @@ PSYoungGen::PSYoungGen(size_t initial_size, void PSYoungGen::initialize_virtual_space(ReservedSpace rs, size_t alignment) { assert(_init_gen_size != 0, "Should have a finite size"); _virtual_space = new PSVirtualSpace(rs, alignment); - if (!_virtual_space->expand_by(_init_gen_size)) { + if (!virtual_space()->expand_by(_init_gen_size)) { vm_exit_during_initialization("Could not reserve enough space for " "object heap"); } @@ -49,13 +49,20 @@ void PSYoungGen::initialize(ReservedSpace rs, size_t alignment) { void PSYoungGen::initialize_work() { - _reserved = MemRegion((HeapWord*)_virtual_space->low_boundary(), - (HeapWord*)_virtual_space->high_boundary()); + _reserved = MemRegion((HeapWord*)virtual_space()->low_boundary(), + (HeapWord*)virtual_space()->high_boundary()); - MemRegion cmr((HeapWord*)_virtual_space->low(), - (HeapWord*)_virtual_space->high()); + MemRegion cmr((HeapWord*)virtual_space()->low(), + (HeapWord*)virtual_space()->high()); Universe::heap()->barrier_set()->resize_covered_region(cmr); + if (ZapUnusedHeapArea) { + // Mangle newly committed space immediately because it + // can be done here more simply that after the new + // spaces have been computed. + SpaceMangler::mangle_region(cmr); + } + if (UseNUMA) { _eden_space = new MutableNUMASpace(); } else { @@ -89,7 +96,7 @@ void PSYoungGen::initialize_work() { // Compute maximum space sizes for performance counters ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); size_t alignment = heap->intra_heap_alignment(); - size_t size = _virtual_space->reserved_size(); + size_t size = virtual_space()->reserved_size(); size_t max_survivor_size; size_t max_eden_size; @@ -142,7 +149,7 @@ void PSYoungGen::compute_initial_space_boundaries() { // Compute sizes size_t alignment = heap->intra_heap_alignment(); - size_t size = _virtual_space->committed_size(); + size_t size = virtual_space()->committed_size(); size_t survivor_size = size / InitialSurvivorRatio; survivor_size = align_size_down(survivor_size, alignment); @@ -164,18 +171,18 @@ void PSYoungGen::compute_initial_space_boundaries() { } void PSYoungGen::set_space_boundaries(size_t eden_size, size_t survivor_size) { - assert(eden_size < _virtual_space->committed_size(), "just checking"); + assert(eden_size < virtual_space()->committed_size(), "just checking"); assert(eden_size > 0 && survivor_size > 0, "just checking"); // Initial layout is Eden, to, from. After swapping survivor spaces, // that leaves us with Eden, from, to, which is step one in our two // step resize-with-live-data procedure. - char *eden_start = _virtual_space->low(); + char *eden_start = virtual_space()->low(); char *to_start = eden_start + eden_size; char *from_start = to_start + survivor_size; char *from_end = from_start + survivor_size; - assert(from_end == _virtual_space->high(), "just checking"); + assert(from_end == virtual_space()->high(), "just checking"); assert(is_object_aligned((intptr_t)eden_start), "checking alignment"); assert(is_object_aligned((intptr_t)to_start), "checking alignment"); assert(is_object_aligned((intptr_t)from_start), "checking alignment"); @@ -184,9 +191,9 @@ void PSYoungGen::set_space_boundaries(size_t eden_size, size_t survivor_size) { MemRegion to_mr ((HeapWord*)to_start, (HeapWord*)from_start); MemRegion from_mr((HeapWord*)from_start, (HeapWord*)from_end); - eden_space()->initialize(eden_mr, true); - to_space()->initialize(to_mr , true); - from_space()->initialize(from_mr, true); + eden_space()->initialize(eden_mr, true, ZapUnusedHeapArea); + to_space()->initialize(to_mr , true, ZapUnusedHeapArea); + from_space()->initialize(from_mr, true, ZapUnusedHeapArea); } #ifndef PRODUCT @@ -207,7 +214,7 @@ void PSYoungGen::space_invariants() { char* to_start = (char*)to_space()->bottom(); char* to_end = (char*)to_space()->end(); - guarantee(eden_start >= _virtual_space->low(), "eden bottom"); + guarantee(eden_start >= virtual_space()->low(), "eden bottom"); guarantee(eden_start < eden_end, "eden space consistency"); guarantee(from_start < from_end, "from space consistency"); guarantee(to_start < to_end, "to space consistency"); @@ -217,29 +224,29 @@ void PSYoungGen::space_invariants() { // Eden, from, to guarantee(eden_end <= from_start, "eden/from boundary"); guarantee(from_end <= to_start, "from/to boundary"); - guarantee(to_end <= _virtual_space->high(), "to end"); + guarantee(to_end <= virtual_space()->high(), "to end"); } else { // Eden, to, from guarantee(eden_end <= to_start, "eden/to boundary"); guarantee(to_end <= from_start, "to/from boundary"); - guarantee(from_end <= _virtual_space->high(), "from end"); + guarantee(from_end <= virtual_space()->high(), "from end"); } // More checks that the virtual space is consistent with the spaces - assert(_virtual_space->committed_size() >= + assert(virtual_space()->committed_size() >= (eden_space()->capacity_in_bytes() + to_space()->capacity_in_bytes() + from_space()->capacity_in_bytes()), "Committed size is inconsistent"); - assert(_virtual_space->committed_size() <= _virtual_space->reserved_size(), + assert(virtual_space()->committed_size() <= virtual_space()->reserved_size(), "Space invariant"); char* eden_top = (char*)eden_space()->top(); char* from_top = (char*)from_space()->top(); char* to_top = (char*)to_space()->top(); - assert(eden_top <= _virtual_space->high(), "eden top"); - assert(from_top <= _virtual_space->high(), "from top"); - assert(to_top <= _virtual_space->high(), "to top"); + assert(eden_top <= virtual_space()->high(), "eden top"); + assert(from_top <= virtual_space()->high(), "from top"); + assert(to_top <= virtual_space()->high(), "to top"); - _virtual_space->verify(); + virtual_space()->verify(); } #endif @@ -265,8 +272,8 @@ void PSYoungGen::resize(size_t eden_size, size_t survivor_size) { bool PSYoungGen::resize_generation(size_t eden_size, size_t survivor_size) { - const size_t alignment = _virtual_space->alignment(); - size_t orig_size = _virtual_space->committed_size(); + const size_t alignment = virtual_space()->alignment(); + size_t orig_size = virtual_space()->committed_size(); bool size_changed = false; // There used to be this guarantee there. @@ -288,10 +295,18 @@ bool PSYoungGen::resize_generation(size_t eden_size, size_t survivor_size) { // Grow the generation size_t change = desired_size - orig_size; assert(change % alignment == 0, "just checking"); - if (!_virtual_space->expand_by(change)) { + HeapWord* prev_high = (HeapWord*) virtual_space()->high(); + if (!virtual_space()->expand_by(change)) { return false; // Error if we fail to resize! } - + if (ZapUnusedHeapArea) { + // Mangle newly committed space immediately because it + // can be done here more simply that after the new + // spaces have been computed. + HeapWord* new_high = (HeapWord*) virtual_space()->high(); + MemRegion mangle_region(prev_high, new_high); + SpaceMangler::mangle_region(mangle_region); + } size_changed = true; } else if (desired_size < orig_size) { size_t desired_change = orig_size - desired_size; @@ -321,19 +336,95 @@ bool PSYoungGen::resize_generation(size_t eden_size, size_t survivor_size) { post_resize(); if (Verbose && PrintGC) { - size_t current_size = _virtual_space->committed_size(); + size_t current_size = virtual_space()->committed_size(); gclog_or_tty->print_cr("PSYoung generation size changed: " SIZE_FORMAT "K->" SIZE_FORMAT "K", orig_size/K, current_size/K); } } - guarantee(eden_plus_survivors <= _virtual_space->committed_size() || - _virtual_space->committed_size() == max_size(), "Sanity"); + guarantee(eden_plus_survivors <= virtual_space()->committed_size() || + virtual_space()->committed_size() == max_size(), "Sanity"); return true; } +#ifndef PRODUCT +// In the numa case eden is not mangled so a survivor space +// moving into a region previously occupied by a survivor +// may find an unmangled region. Also in the PS case eden +// to-space and from-space may not touch (i.e., there may be +// gaps between them due to movement while resizing the +// spaces). Those gaps must be mangled. +void PSYoungGen::mangle_survivors(MutableSpace* s1, + MemRegion s1MR, + MutableSpace* s2, + MemRegion s2MR) { + // Check eden and gap between eden and from-space, in deciding + // what to mangle in from-space. Check the gap between from-space + // and to-space when deciding what to mangle. + // + // +--------+ +----+ +---+ + // | eden | |s1 | |s2 | + // +--------+ +----+ +---+ + // +-------+ +-----+ + // |s1MR | |s2MR | + // +-------+ +-----+ + // All of survivor-space is properly mangled so find the + // upper bound on the mangling for any portion above current s1. + HeapWord* delta_end = MIN2(s1->bottom(), s1MR.end()); + MemRegion delta1_left; + if (s1MR.start() < delta_end) { + delta1_left = MemRegion(s1MR.start(), delta_end); + s1->mangle_region(delta1_left); + } + // Find any portion to the right of the current s1. + HeapWord* delta_start = MAX2(s1->end(), s1MR.start()); + MemRegion delta1_right; + if (delta_start < s1MR.end()) { + delta1_right = MemRegion(delta_start, s1MR.end()); + s1->mangle_region(delta1_right); + } + + // Similarly for the second survivor space except that + // any of the new region that overlaps with the current + // region of the first survivor space has already been + // mangled. + delta_end = MIN2(s2->bottom(), s2MR.end()); + delta_start = MAX2(s2MR.start(), s1->end()); + MemRegion delta2_left; + if (s2MR.start() < delta_end) { + delta2_left = MemRegion(s2MR.start(), delta_end); + s2->mangle_region(delta2_left); + } + delta_start = MAX2(s2->end(), s2MR.start()); + MemRegion delta2_right; + if (delta_start < s2MR.end()) { + s2->mangle_region(delta2_right); + } + + if (TraceZapUnusedHeapArea) { + // s1 + gclog_or_tty->print_cr("Current region: [" PTR_FORMAT ", " PTR_FORMAT ") " + "New region: [" PTR_FORMAT ", " PTR_FORMAT ")", + s1->bottom(), s1->end(), s1MR.start(), s1MR.end()); + gclog_or_tty->print_cr(" Mangle before: [" PTR_FORMAT ", " + PTR_FORMAT ") Mangle after: [" PTR_FORMAT ", " PTR_FORMAT ")", + delta1_left.start(), delta1_left.end(), delta1_right.start(), + delta1_right.end()); + + // s2 + gclog_or_tty->print_cr("Current region: [" PTR_FORMAT ", " PTR_FORMAT ") " + "New region: [" PTR_FORMAT ", " PTR_FORMAT ")", + s2->bottom(), s2->end(), s2MR.start(), s2MR.end()); + gclog_or_tty->print_cr(" Mangle before: [" PTR_FORMAT ", " + PTR_FORMAT ") Mangle after: [" PTR_FORMAT ", " PTR_FORMAT ")", + delta2_left.start(), delta2_left.end(), delta2_right.start(), + delta2_right.end()); + } + +} +#endif // NOT PRODUCT void PSYoungGen::resize_spaces(size_t requested_eden_size, size_t requested_survivor_size) { @@ -396,9 +487,11 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size, const bool maintain_minimum = (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size(); + bool eden_from_to_order = from_start < to_start; // Check whether from space is below to space - if (from_start < to_start) { + if (eden_from_to_order) { // Eden, from, to + eden_from_to_order = true; if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" Eden, from, to:"); } @@ -435,7 +528,7 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size, // extra calculations. // First calculate an optimal to-space - to_end = (char*)_virtual_space->high(); + to_end = (char*)virtual_space()->high(); to_start = (char*)pointer_delta(to_end, (char*)requested_survivor_size, sizeof(char)); @@ -491,7 +584,7 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size, // to space as if we were able to resize from space, even though from // space is not modified. // Giving eden priority was tried and gave poorer performance. - to_end = (char*)pointer_delta(_virtual_space->high(), + to_end = (char*)pointer_delta(virtual_space()->high(), (char*)requested_survivor_size, sizeof(char)); to_end = MIN2(to_end, from_start); @@ -560,9 +653,45 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size, size_t old_from = from_space()->capacity_in_bytes(); size_t old_to = to_space()->capacity_in_bytes(); - eden_space()->initialize(edenMR, true); - to_space()->initialize(toMR , true); - from_space()->initialize(fromMR, false); // Note, not cleared! + if (ZapUnusedHeapArea) { + // NUMA is a special case because a numa space is not mangled + // in order to not prematurely bind its address to memory to + // the wrong memory (i.e., don't want the GC thread to first + // touch the memory). The survivor spaces are not numa + // spaces and are mangled. + if (UseNUMA) { + if (eden_from_to_order) { + mangle_survivors(from_space(), fromMR, to_space(), toMR); + } else { + mangle_survivors(to_space(), toMR, from_space(), fromMR); + } + } + + // If not mangling the spaces, do some checking to verify that + // the spaces are already mangled. + // The spaces should be correctly mangled at this point so + // do some checking here. Note that they are not being mangled + // in the calls to initialize(). + // Must check mangling before the spaces are reshaped. Otherwise, + // the bottom or end of one space may have moved into an area + // covered by another space and a failure of the check may + // not correctly indicate which space is not properly mangled. + HeapWord* limit = (HeapWord*) virtual_space()->high(); + eden_space()->check_mangled_unused_area(limit); + from_space()->check_mangled_unused_area(limit); + to_space()->check_mangled_unused_area(limit); + } + // When an existing space is being initialized, it is not + // mangled because the space has been previously mangled. + eden_space()->initialize(edenMR, + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); + to_space()->initialize(toMR, + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); + from_space()->initialize(fromMR, + SpaceDecorator::DontClear, + SpaceDecorator::DontMangle); assert(from_space()->top() == old_from_top, "from top changed!"); @@ -671,7 +800,7 @@ void PSYoungGen::print_on(outputStream* st) const { st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K", capacity_in_bytes()/K, used_in_bytes()/K); } - _virtual_space->print_space_boundaries_on(st); + virtual_space()->print_space_boundaries_on(st); st->print(" eden"); eden_space()->print_on(st); st->print(" from"); from_space()->print_on(st); st->print(" to "); to_space()->print_on(st); @@ -774,7 +903,9 @@ void PSYoungGen::reset_survivors_after_shrink() { // Was there a shrink of the survivor space? if (new_end < space_shrinking->end()) { MemRegion mr(space_shrinking->bottom(), new_end); - space_shrinking->initialize(mr, false /* clear */); + space_shrinking->initialize(mr, + SpaceDecorator::DontClear, + SpaceDecorator::Mangle); } } @@ -809,3 +940,12 @@ void PSYoungGen::verify(bool allow_dirty) { from_space()->verify(allow_dirty); to_space()->verify(allow_dirty); } + +#ifndef PRODUCT +void PSYoungGen::record_spaces_top() { + assert(ZapUnusedHeapArea, "Not mangling unused space"); + eden_space()->set_top_for_allocations(); + from_space()->set_top_for_allocations(); + to_space()->set_top_for_allocations(); +} +#endif diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp index 953d4309f20..4fad1bccffb 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp @@ -179,4 +179,12 @@ class PSYoungGen : public CHeapObj { // Space boundary invariant checker void space_invariants() PRODUCT_RETURN; + + // Helper for mangling survivor spaces. + void mangle_survivors(MutableSpace* s1, + MemRegion s1MR, + MutableSpace* s2, + MemRegion s2MR) PRODUCT_RETURN; + + void record_spaces_top() PRODUCT_RETURN; }; diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp index ff58cc3a43f..20ca6d3e31f 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @@ -42,19 +42,31 @@ MutableNUMASpace::~MutableNUMASpace() { delete lgrp_spaces(); } +#ifndef PRODUCT void MutableNUMASpace::mangle_unused_area() { - for (int i = 0; i < lgrp_spaces()->length(); i++) { - LGRPSpace *ls = lgrp_spaces()->at(i); - MutableSpace *s = ls->space(); - if (!os::numa_has_static_binding()) { - HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom()); - if (top < s->end()) { - ls->add_invalid_region(MemRegion(top, s->end())); - } - } - s->mangle_unused_area(); - } + // This method should do nothing. + // It can be called on a numa space during a full compaction. } +void MutableNUMASpace::mangle_unused_area_complete() { + // This method should do nothing. + // It can be called on a numa space during a full compaction. +} +void MutableNUMASpace::mangle_region(MemRegion mr) { + // This method should do nothing because numa spaces are not mangled. +} +void MutableNUMASpace::set_top_for_allocations(HeapWord* v) { + assert(false, "Do not mangle MutableNUMASpace's"); +} +void MutableNUMASpace::set_top_for_allocations() { + // This method should do nothing. +} +void MutableNUMASpace::check_mangled_unused_area(HeapWord* limit) { + // This method should do nothing. +} +void MutableNUMASpace::check_mangled_unused_area_complete() { + // This method should do nothing. +} +#endif // NOT_PRODUCT // There may be unallocated holes in the middle chunks // that should be filled with dead objects to ensure parseability. @@ -243,7 +255,10 @@ void MutableNUMASpace::update() { s->set_end(s->bottom()); s->set_top(s->bottom()); } - initialize(region(), true); + // A NUMA space is never mangled + initialize(region(), + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); } else { bool should_initialize = false; if (!os::numa_has_static_binding()) { @@ -257,7 +272,10 @@ void MutableNUMASpace::update() { if (should_initialize || (UseAdaptiveNUMAChunkSizing && adaptation_cycles() < samples_count())) { - initialize(region(), true); + // A NUMA space is never mangled + initialize(region(), + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); } } @@ -448,14 +466,17 @@ void MutableNUMASpace::merge_regions(MemRegion new_region, MemRegion* intersecti } } -void MutableNUMASpace::initialize(MemRegion mr, bool clear_space) { +void MutableNUMASpace::initialize(MemRegion mr, + bool clear_space, + bool mangle_space) { assert(clear_space, "Reallocation will destory data!"); assert(lgrp_spaces()->length() > 0, "There should be at least one space"); MemRegion old_region = region(), new_region; set_bottom(mr.start()); set_end(mr.end()); - MutableSpace::set_top(bottom()); + // Must always clear the space + clear(SpaceDecorator::DontMangle); // Compute chunk sizes size_t prev_page_size = page_size(); @@ -586,10 +607,8 @@ void MutableNUMASpace::initialize(MemRegion mr, bool clear_space) { bias_region(top_region, ls->lgrp_id()); } - // If we clear the region, we would mangle it in debug. That would cause page - // allocation in a different place. Hence setting the top directly. - s->initialize(new_region, false); - s->set_top(s->bottom()); + // Clear space (set top = bottom) but never mangle. + s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle); set_adaptation_cycles(samples_count()); } @@ -641,10 +660,12 @@ void MutableNUMASpace::set_top(HeapWord* value) { MutableSpace::set_top(value); } -void MutableNUMASpace::clear() { +void MutableNUMASpace::clear(bool mangle_space) { MutableSpace::set_top(bottom()); for (int i = 0; i < lgrp_spaces()->length(); i++) { - lgrp_spaces()->at(i)->space()->clear(); + // Never mangle NUMA spaces because the mangling will + // bind the memory to a possibly unwanted lgroup. + lgrp_spaces()->at(i)->space()->clear(SpaceDecorator::DontMangle); } } diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp index 6b5dcbbe214..54a01299beb 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp @@ -171,14 +171,21 @@ class MutableNUMASpace : public MutableSpace { MutableNUMASpace(); virtual ~MutableNUMASpace(); // Space initialization. - virtual void initialize(MemRegion mr, bool clear_space); + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); // Update space layout if necessary. Do all adaptive resizing job. virtual void update(); // Update allocation rate averages. virtual void accumulate_statistics(); - virtual void clear(); - virtual void mangle_unused_area(); + virtual void clear(bool mangle_space); + virtual void mangle_unused_area() PRODUCT_RETURN; + virtual void mangle_unused_area_complete() PRODUCT_RETURN; + virtual void mangle_region(MemRegion mr) PRODUCT_RETURN; + virtual void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; + virtual void check_mangled_unused_area_complete() PRODUCT_RETURN; + virtual void set_top_for_allocations(HeapWord* v) PRODUCT_RETURN; + virtual void set_top_for_allocations() PRODUCT_RETURN; + virtual void ensure_parsability(); virtual size_t used_in_words() const; virtual size_t free_in_words() const; diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp index a91247a80d9..a5befabf056 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp @@ -25,7 +25,17 @@ # include "incls/_precompiled.incl" # include "incls/_mutableSpace.cpp.incl" -void MutableSpace::initialize(MemRegion mr, bool clear_space) { +MutableSpace::MutableSpace(): ImmutableSpace(), _top(NULL) { + _mangler = new MutableSpaceMangler(this); +} + +MutableSpace::~MutableSpace() { + delete _mangler; +} + +void MutableSpace::initialize(MemRegion mr, + bool clear_space, + bool mangle_space) { HeapWord* bottom = mr.start(); HeapWord* end = mr.end(); @@ -34,14 +44,51 @@ void MutableSpace::initialize(MemRegion mr, bool clear_space) { set_bottom(bottom); set_end(end); - if (clear_space) clear(); + if (clear_space) { + clear(mangle_space); + } } -void MutableSpace::clear() { +void MutableSpace::clear(bool mangle_space) { set_top(bottom()); - if (ZapUnusedHeapArea) mangle_unused_area(); + if (ZapUnusedHeapArea && mangle_space) { + mangle_unused_area(); + } } +#ifndef PRODUCT +void MutableSpace::check_mangled_unused_area(HeapWord* limit) { + mangler()->check_mangled_unused_area(limit); +} + +void MutableSpace::check_mangled_unused_area_complete() { + mangler()->check_mangled_unused_area_complete(); +} + +// Mangle only the unused space that has not previously +// been mangled and that has not been allocated since being +// mangled. +void MutableSpace::mangle_unused_area() { + mangler()->mangle_unused_area(); +} + +void MutableSpace::mangle_unused_area_complete() { + mangler()->mangle_unused_area_complete(); +} + +void MutableSpace::mangle_region(MemRegion mr) { + SpaceMangler::mangle_region(mr); +} + +void MutableSpace::set_top_for_allocations(HeapWord* v) { + mangler()->set_top_for_allocations(v); +} + +void MutableSpace::set_top_for_allocations() { + mangler()->set_top_for_allocations(top()); +} +#endif + // This version requires locking. */ HeapWord* MutableSpace::allocate(size_t size) { assert(Heap_lock->owned_by_self() || diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp index f21930123b9..9c0271245f4 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp @@ -30,14 +30,23 @@ // Invariant: (ImmutableSpace +) bottom() <= top() <= end() // top() is inclusive and end() is exclusive. +class MutableSpaceMangler; + class MutableSpace: public ImmutableSpace { friend class VMStructs; + + // Helper for mangling unused space in debug builds + MutableSpaceMangler* _mangler; + protected: HeapWord* _top; + MutableSpaceMangler* mangler() { return _mangler; } + public: - virtual ~MutableSpace() {} - MutableSpace() { _top = NULL; } + virtual ~MutableSpace(); + MutableSpace(); + // Accessors HeapWord* top() const { return _top; } virtual void set_top(HeapWord* value) { _top = value; } @@ -52,21 +61,30 @@ class MutableSpace: public ImmutableSpace { MemRegion used_region() { return MemRegion(bottom(), top()); } // Initialization - virtual void initialize(MemRegion mr, bool clear_space); - virtual void clear(); + virtual void initialize(MemRegion mr, + bool clear_space, + bool mangle_space); + virtual void clear(bool mangle_space); + // Does the usual initialization but optionally resets top to bottom. +#if 0 // MANGLE_SPACE + void initialize(MemRegion mr, bool clear_space, bool reset_top); +#endif virtual void update() { } virtual void accumulate_statistics() { } - // Overwrites the unused portion of this space. Note that some collectors - // may use this "scratch" space during collections. - virtual void mangle_unused_area() { - mangle_region(MemRegion(_top, _end)); - } + // Methods used in mangling. See descriptions under SpaceMangler. + virtual void mangle_unused_area() PRODUCT_RETURN; + virtual void mangle_unused_area_complete() PRODUCT_RETURN; + virtual void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; + virtual void check_mangled_unused_area_complete() PRODUCT_RETURN; + virtual void set_top_for_allocations(HeapWord* v) PRODUCT_RETURN; + + // Used to save the space's current top for later use during mangling. + virtual void set_top_for_allocations() PRODUCT_RETURN; + virtual void ensure_parsability() { } - void mangle_region(MemRegion mr) { - debug_only(Copy::fill_to_words(mr.start(), mr.word_size(), badHeapWord)); - } + virtual void mangle_region(MemRegion mr) PRODUCT_RETURN; // Boolean querries. bool is_empty() const { return used_in_words() == 0; } diff --git a/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp b/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp new file mode 100644 index 00000000000..2d9fc59f675 --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.cpp @@ -0,0 +1,140 @@ +/* + * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +# include "incls/_precompiled.incl" +# include "incls/_spaceDecorator.cpp.incl" + +// Catch-all file for utility classes + +#ifndef PRODUCT + +// Returns true is the location q matches the mangling +// pattern. +bool SpaceMangler::is_mangled(HeapWord* q) { + // This test loses precision but is good enough + return badHeapWord == (max_juint & (uintptr_t) q->value()); +} + + +void SpaceMangler::set_top_for_allocations(HeapWord* v) { + if (v < end()) { + assert(is_mangled(v), "The high water mark is not mangled"); + } + _top_for_allocations = v; +} + +// Mangle only the unused space that has not previously +// been mangled and that has not been allocated since being +// mangled. +void SpaceMangler::mangle_unused_area() { + assert(ZapUnusedHeapArea, "Mangling should not be in use"); + // Mangle between top and the high water mark. Safeguard + // against the space changing since top_for_allocations was + // set. + HeapWord* mangled_end = MIN2(top_for_allocations(), end()); + if (top() < mangled_end) { + MemRegion mangle_mr(top(), mangled_end); + SpaceMangler::mangle_region(mangle_mr); + // Light weight check of mangling. + check_mangled_unused_area(end()); + } + // Complete check of unused area which is functional when + // DEBUG_MANGLING is defined. + check_mangled_unused_area_complete(); +} + +// A complete mangle is expected in the +// exceptional case where top_for_allocations is not +// properly tracking the high water mark for mangling. +// This can be the case when to-space is being used for +// scratch space during a mark-sweep-compact. See +// contribute_scratch() and PSMarkSweep::allocate_stacks(). +void SpaceMangler::mangle_unused_area_complete() { + assert(ZapUnusedHeapArea, "Mangling should not be in use"); + MemRegion mangle_mr(top(), end()); + SpaceMangler::mangle_region(mangle_mr); +} + +// Simply mangle the MemRegion mr. +void SpaceMangler::mangle_region(MemRegion mr) { + assert(ZapUnusedHeapArea, "Mangling should not be in use"); +#ifdef ASSERT + if(TraceZapUnusedHeapArea) { + gclog_or_tty->print("Mangling [0x%x to 0x%x)", mr.start(), mr.end()); + } + Copy::fill_to_words(mr.start(), mr.word_size(), badHeapWord); + if(TraceZapUnusedHeapArea) { + gclog_or_tty->print_cr(" done"); + } +#endif +} + +// Check that top, top_for_allocations and the last +// word of the space are mangled. In a tight memory +// situation even this light weight mangling could +// cause paging by touching the end of the space. +void SpaceMangler::check_mangled_unused_area(HeapWord* limit) { + if (CheckZapUnusedHeapArea) { + // This method can be called while the spaces are + // being reshaped so skip the test if the end of the + // space is beyond the specified limit; + if (end() > limit) return; + + assert(top() == end() || + (is_mangled(top())), "Top not mangled"); + assert((top_for_allocations() < top()) || + (top_for_allocations() >= end()) || + (is_mangled(top_for_allocations())), + "Older unused not mangled"); + assert(top() == end() || + (is_mangled(end() - 1)), "End not properly mangled"); + // Only does checking when DEBUG_MANGLING is defined. + check_mangled_unused_area_complete(); + } +} + +#undef DEBUG_MANGLING +// This should only be used while debugging the mangling +// because of the high cost of checking the completeness. +void SpaceMangler::check_mangled_unused_area_complete() { + if (CheckZapUnusedHeapArea) { + assert(ZapUnusedHeapArea, "Not mangling unused area"); +#ifdef DEBUG_MANGLING + HeapWord* q = top(); + HeapWord* limit = end(); + + bool passed = true; + while (q < limit) { + if (!is_mangled(q)) { + passed = false; + break; + } + q++; + } + assert(passed, "Mangling is not complete"); +#endif + } +} +#undef DEBUG_MANGLING +#endif // not PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.hpp b/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.hpp new file mode 100644 index 00000000000..7298c47a91b --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.hpp @@ -0,0 +1,141 @@ +/* + * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +class SpaceDecorator: public AllStatic { + public: + // Initialization flags. + static const bool Clear = true; + static const bool DontClear = false; + static const bool Mangle = true; + static const bool DontMangle = false; +}; + +// Functionality for use with class Space and class MutableSpace. +// The approach taken with the mangling is to mangle all +// the space initially and then to mangle areas that have +// been allocated since the last collection. Mangling is +// done in the context of a generation and in the context +// of a space. +// The space in a generation is mangled when it is first +// initialized and when the generation grows. The spaces +// are not necessarily up-to-date when this mangling occurs +// and the method mangle_region() is used. +// After allocations have been done in a space, the space generally +// need to be remangled. Remangling is only done on the +// recently allocated regions in the space. Typically, that is +// the region between the new top and the top just before a +// garbage collection. +// An exception to the usual mangling in a space is done when the +// space is used for an extraordinary purpose. Specifically, when +// to-space is used as scratch space for a mark-sweep-compact +// collection. +// Spaces are mangled after a collection. If the generation +// grows after a collection, the added space is mangled as part of +// the growth of the generation. No additional mangling is needed when the +// spaces are resized after an expansion. +// The class SpaceMangler keeps a pointer to the top of the allocated +// area and provides the methods for doing the piece meal mangling. +// Methods for doing sparces and full checking of the mangling are +// included. The full checking is done if DEBUG_MANGLING is defined. +// GenSpaceMangler is used with the GenCollectedHeap collectors and +// MutableSpaceMangler is used with the ParallelScavengeHeap collectors. +// These subclasses abstract the differences in the types of spaces used +// by each heap. + +class SpaceMangler: public CHeapObj { + friend class VMStructs; + + // High water mark for allocations. Typically, the space above + // this point have been mangle previously and don't need to be + // touched again. Space belows this point has been allocated + // and remangling is needed between the current top and this + // high water mark. + HeapWord* _top_for_allocations; + HeapWord* top_for_allocations() { return _top_for_allocations; } + + public: + + // Setting _top_for_allocations to NULL at initialization + // makes it always below top so that mangling done as part + // of the initialize() call of a space does nothing (as it + // should since the mangling is done as part of the constructor + // for the space. + SpaceMangler() : _top_for_allocations(NULL) {} + + // Methods for top and end that delegate to the specific + // space type. + virtual HeapWord* top() const = 0; + virtual HeapWord* end() const = 0; + + // Return true if q matches the mangled pattern. + static bool is_mangled(HeapWord* q) PRODUCT_RETURN0; + + // Used to save the an address in a space for later use during mangling. + void set_top_for_allocations(HeapWord* v); + + // Overwrites the unused portion of this space. + // Mangle only the region not previously mangled [top, top_previously_mangled) + void mangle_unused_area(); + // Mangle all the unused region [top, end) + void mangle_unused_area_complete(); + // Do some sparse checking on the area that should have been mangled. + void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; + // Do a complete check of the area that should be mangled. + void check_mangled_unused_area_complete() PRODUCT_RETURN; + + // Mangle the MemRegion. This is a non-space specific mangler. It + // is used during the initial mangling of a space before the space + // is fully constructed. Also is used when a generation is expanded + // and possibly before the spaces have been reshaped to to the new + // size of the generation. + static void mangle_region(MemRegion mr); +}; + +class ContiguousSpace; + +// For use with GenCollectedHeap's +class GenSpaceMangler: public SpaceMangler { + ContiguousSpace* _sp; + + ContiguousSpace* sp() { return _sp; } + + HeapWord* top() const { return _sp->top(); } + HeapWord* end() const { return _sp->end(); } + + public: + GenSpaceMangler(ContiguousSpace* sp) : SpaceMangler(), _sp(sp) {} +}; + +// For use with ParallelScavengeHeap's. +class MutableSpaceMangler: public SpaceMangler { + MutableSpace* _sp; + + MutableSpace* sp() { return _sp; } + + HeapWord* top() const { return _sp->top(); } + HeapWord* end() const { return _sp->end(); } + + public: + MutableSpaceMangler(MutableSpace* sp) : SpaceMangler(), _sp(sp) {} +}; diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 2af8fd826f1..8fade1d4d27 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -1405,6 +1405,7 @@ defNewGeneration.cpp java.hpp defNewGeneration.cpp oop.inline.hpp defNewGeneration.cpp referencePolicy.hpp defNewGeneration.cpp space.inline.hpp +defNewGeneration.cpp spaceDecorator.hpp defNewGeneration.cpp thread_.inline.hpp defNewGeneration.hpp ageTable.hpp @@ -1789,6 +1790,7 @@ generation.cpp generation.inline.hpp generation.cpp java.hpp generation.cpp oop.hpp generation.cpp oop.inline.hpp +generation.cpp spaceDecorator.hpp generation.cpp space.inline.hpp generation.hpp allocation.hpp @@ -3722,6 +3724,7 @@ space.cpp oop.inline2.hpp space.cpp safepoint.hpp space.cpp space.hpp space.cpp space.inline.hpp +space.cpp spaceDecorator.hpp space.cpp systemDictionary.hpp space.cpp universe.inline.hpp space.cpp vmSymbols.hpp @@ -3744,6 +3747,13 @@ space.inline.hpp safepoint.hpp space.inline.hpp space.hpp space.inline.hpp universe.hpp +spaceDecorator.hpp globalDefinitions.hpp +spaceDecorator.hpp mutableSpace.hpp +spaceDecorator.hpp space.hpp + +spaceDecorator.cpp copy.hpp +spaceDecorator.cpp spaceDecorator.hpp + specialized_oop_closures.cpp ostream.hpp specialized_oop_closures.cpp specialized_oop_closures.hpp diff --git a/hotspot/src/share/vm/includeDB_features b/hotspot/src/share/vm/includeDB_features index eec1c35259e..88f4c293643 100644 --- a/hotspot/src/share/vm/includeDB_features +++ b/hotspot/src/share/vm/includeDB_features @@ -51,6 +51,7 @@ dump.cpp oop.hpp dump.cpp oopFactory.hpp dump.cpp resourceArea.hpp dump.cpp signature.hpp +dump.cpp spaceDecorator.hpp dump.cpp symbolTable.hpp dump.cpp systemDictionary.hpp dump.cpp vmThread.hpp diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp index d13c9e9adff..23449688dd7 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp @@ -172,15 +172,25 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _to_counters = new CSpaceCounters("s1", 2, _max_survivor_size, _to_space, _gen_counters); - compute_space_boundaries(0); + compute_space_boundaries(0, SpaceDecorator::Clear, SpaceDecorator::Mangle); update_counters(); _next_gen = NULL; _tenuring_threshold = MaxTenuringThreshold; _pretenure_size_threshold_words = PretenureSizeThreshold >> LogHeapWordSize; } -void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size) { - uintx alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment(); +void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size, + bool clear_space, + bool mangle_space) { + uintx alignment = + GenCollectedHeap::heap()->collector_policy()->min_alignment(); + + // If the spaces are being cleared (only done at heap initialization + // currently), the survivor spaces need not be empty. + // Otherwise, no care is taken for used areas in the survivor spaces + // so check. + assert(clear_space || (to()->is_empty() && from()->is_empty()), + "Initialization of the survivor spaces assumes these are empty"); // Compute sizes uintx size = _virtual_space.committed_size(); @@ -214,16 +224,41 @@ void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size) { MemRegion fromMR((HeapWord*)from_start, (HeapWord*)to_start); MemRegion toMR ((HeapWord*)to_start, (HeapWord*)to_end); - eden()->initialize(edenMR, (minimum_eden_size == 0)); - // If minumum_eden_size != 0, we will not have cleared any + // A minimum eden size implies that there is a part of eden that + // is being used and that affects the initialization of any + // newly formed eden. + bool live_in_eden = minimum_eden_size > 0; + + // If not clearing the spaces, do some checking to verify that + // the space are already mangled. + if (!clear_space) { + // Must check mangling before the spaces are reshaped. Otherwise, + // the bottom or end of one space may have moved into another + // a failure of the check may not correctly indicate which space + // is not properly mangled. + if (ZapUnusedHeapArea) { + HeapWord* limit = (HeapWord*) _virtual_space.high(); + eden()->check_mangled_unused_area(limit); + from()->check_mangled_unused_area(limit); + to()->check_mangled_unused_area(limit); + } + } + + // Reset the spaces for their new regions. + eden()->initialize(edenMR, + clear_space && !live_in_eden, + SpaceDecorator::Mangle); + // If clear_space and live_in_eden, we will not have cleared any // portion of eden above its top. This can cause newly // expanded space not to be mangled if using ZapUnusedHeapArea. // We explicitly do such mangling here. - if (ZapUnusedHeapArea && (minimum_eden_size != 0)) { + if (ZapUnusedHeapArea && clear_space && live_in_eden && mangle_space) { eden()->mangle_unused_area(); } - from()->initialize(fromMR, true); - to()->initialize(toMR , true); + from()->initialize(fromMR, clear_space, mangle_space); + to()->initialize(toMR, clear_space, mangle_space); + + // Set next compaction spaces. eden()->set_next_compaction_space(from()); // The to-space is normally empty before a compaction so need // not be considered. The exception is during promotion @@ -250,7 +285,16 @@ void DefNewGeneration::swap_spaces() { bool DefNewGeneration::expand(size_t bytes) { MutexLocker x(ExpandHeap_lock); + HeapWord* prev_high = (HeapWord*) _virtual_space.high(); bool success = _virtual_space.expand_by(bytes); + if (success && ZapUnusedHeapArea) { + // Mangle newly committed space immediately because it + // can be done here more simply that after the new + // spaces have been computed. + HeapWord* new_high = (HeapWord*) _virtual_space.high(); + MemRegion mangle_region(prev_high, new_high); + SpaceMangler::mangle_region(mangle_region); + } // Do not attempt an expand-to-the reserve size. The // request should properly observe the maximum size of @@ -262,7 +306,8 @@ bool DefNewGeneration::expand(size_t bytes) { // value. if (GC_locker::is_active()) { if (PrintGC && Verbose) { - gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead"); + gclog_or_tty->print_cr("Garbage collection disabled, " + "expanded heap instead"); } } @@ -326,16 +371,24 @@ void DefNewGeneration::compute_new_size() { changed = true; } if (changed) { - compute_space_boundaries(eden()->used()); - MemRegion cmr((HeapWord*)_virtual_space.low(), (HeapWord*)_virtual_space.high()); + // The spaces have already been mangled at this point but + // may not have been cleared (set top = bottom) and should be. + // Mangling was done when the heap was being expanded. + compute_space_boundaries(eden()->used(), + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); + MemRegion cmr((HeapWord*)_virtual_space.low(), + (HeapWord*)_virtual_space.high()); Universe::heap()->barrier_set()->resize_covered_region(cmr); if (Verbose && PrintGC) { size_t new_size_after = _virtual_space.committed_size(); size_t eden_size_after = eden()->capacity(); size_t survivor_size_after = from()->capacity(); - gclog_or_tty->print("New generation size " SIZE_FORMAT "K->" SIZE_FORMAT "K [eden=" + gclog_or_tty->print("New generation size " SIZE_FORMAT "K->" + SIZE_FORMAT "K [eden=" SIZE_FORMAT "K,survivor=" SIZE_FORMAT "K]", - new_size_before/K, new_size_after/K, eden_size_after/K, survivor_size_after/K); + new_size_before/K, new_size_after/K, + eden_size_after/K, survivor_size_after/K); if (WizardMode) { gclog_or_tty->print("[allowed " SIZE_FORMAT "K extra for %d threads]", thread_increase_size/K, threads_count); @@ -480,7 +533,7 @@ void DefNewGeneration::collect(bool full, ScanWeakRefClosure scan_weak_ref(this); age_table()->clear(); - to()->clear(); + to()->clear(SpaceDecorator::Mangle); gch->rem_set()->prepare_for_younger_refs_iterate(false); @@ -525,8 +578,18 @@ void DefNewGeneration::collect(bool full, soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers, NULL); if (!promotion_failed()) { // Swap the survivor spaces. - eden()->clear(); - from()->clear(); + eden()->clear(SpaceDecorator::Mangle); + from()->clear(SpaceDecorator::Mangle); + if (ZapUnusedHeapArea) { + // This is now done here because of the piece-meal mangling which + // can check for valid mangling at intermediate points in the + // collection(s). When a minor collection fails to collect + // sufficient space resizing of the young generation can occur + // an redistribute the spaces in the young generation. Mangle + // here so that unzapped regions don't get distributed to + // other spaces. + to()->mangle_unused_area(); + } swap_spaces(); assert(to()->is_empty(), "to space should be empty now"); @@ -753,6 +816,15 @@ void DefNewGeneration::contribute_scratch(ScratchBlock*& list, Generation* reque } } +void DefNewGeneration::reset_scratch() { + // If contributing scratch in to_space, mangle all of + // to_space if ZapUnusedHeapArea. This is needed because + // top is not maintained while using to-space as scratch. + if (ZapUnusedHeapArea) { + to()->mangle_unused_area_complete(); + } +} + bool DefNewGeneration::collection_attempt_is_safe() { if (!to()->is_empty()) { return false; @@ -806,11 +878,25 @@ void DefNewGeneration::gc_epilogue(bool full) { } } + if (ZapUnusedHeapArea) { + eden()->check_mangled_unused_area_complete(); + from()->check_mangled_unused_area_complete(); + to()->check_mangled_unused_area_complete(); + } + // update the generation and space performance counters update_counters(); gch->collector_policy()->counters()->update_counters(); } +void DefNewGeneration::record_spaces_top() { + assert(ZapUnusedHeapArea, "Not mangling unused space"); + eden()->set_top_for_allocations(); + to()->set_top_for_allocations(); + from()->set_top_for_allocations(); +} + + void DefNewGeneration::update_counters() { if (UsePerfData) { _eden_counters->update_all(); diff --git a/hotspot/src/share/vm/memory/defNewGeneration.hpp b/hotspot/src/share/vm/memory/defNewGeneration.hpp index 893afc055c7..9d0cd68364a 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.hpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp @@ -279,6 +279,9 @@ protected: virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); + // Save the tops for eden, from, and to + virtual void record_spaces_top(); + // Doesn't require additional work during GC prologue and epilogue virtual bool performs_in_place_marking() const { return false; } @@ -299,9 +302,12 @@ protected: // For non-youngest collection, the DefNewGeneration can contribute // "to-space". - void contribute_scratch(ScratchBlock*& list, Generation* requestor, + virtual void contribute_scratch(ScratchBlock*& list, Generation* requestor, size_t max_alloc_words); + // Reset for contribution of "to-space". + virtual void reset_scratch(); + // GC support virtual void compute_new_size(); virtual void collect(bool full, @@ -331,7 +337,12 @@ protected: void verify(bool allow_dirty); protected: - void compute_space_boundaries(uintx minimum_eden_size); + // If clear_space is true, clear the survivor spaces. Eden is + // cleared if the minimum size of eden is 0. If mangle_space + // is true, also mangle the space in debug mode. + void compute_space_boundaries(uintx minimum_eden_size, + bool clear_space, + bool mangle_space); // Scavenge support void swap_spaces(); }; diff --git a/hotspot/src/share/vm/memory/dump.cpp b/hotspot/src/share/vm/memory/dump.cpp index 9499336282b..c5b938ea73f 100644 --- a/hotspot/src/share/vm/memory/dump.cpp +++ b/hotspot/src/share/vm/memory/dump.cpp @@ -645,7 +645,7 @@ public: class ClearSpaceClosure : public SpaceClosure { public: void do_space(Space* s) { - s->clear(); + s->clear(SpaceDecorator::Mangle); } }; diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index dc3ba9b3cf3..efb3a95596f 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -465,6 +465,11 @@ void GenCollectedHeap::do_collection(bool full, _gens[i]->stat_record()->invocations++; _gens[i]->stat_record()->accumulated_time.start(); + // Must be done anew before each collection because + // a previous collection will do mangling and will + // change top of some spaces. + record_gen_tops_before_GC(); + if (PrintGC && Verbose) { gclog_or_tty->print("level=%d invoke=%d size=" SIZE_FORMAT, i, @@ -1058,6 +1063,12 @@ ScratchBlock* GenCollectedHeap::gather_scratch(Generation* requestor, return res; } +void GenCollectedHeap::release_scratch() { + for (int i = 0; i < _n_gens; i++) { + _gens[i]->reset_scratch(); + } +} + size_t GenCollectedHeap::large_typearray_limit() { return gen_policy()->large_typearray_limit(); } @@ -1285,6 +1296,24 @@ void GenCollectedHeap::gc_epilogue(bool full) { always_do_update_barrier = UseConcMarkSweepGC; }; +#ifndef PRODUCT +class GenGCSaveTopsBeforeGCClosure: public GenCollectedHeap::GenClosure { + private: + public: + void do_generation(Generation* gen) { + gen->record_spaces_top(); + } +}; + +void GenCollectedHeap::record_gen_tops_before_GC() { + if (ZapUnusedHeapArea) { + GenGCSaveTopsBeforeGCClosure blk; + generation_iterate(&blk, false); // not old-to-young. + perm_gen()->record_spaces_top(); + } +} +#endif // not PRODUCT + class GenEnsureParsabilityClosure: public GenCollectedHeap::GenClosure { public: void do_generation(Generation* gen) { diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp index 54dce33bb80..1872c01ae6d 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp @@ -259,6 +259,9 @@ public: // be provided are returned as a list of ScratchBlocks, sorted by // decreasing size. ScratchBlock* gather_scratch(Generation* requestor, size_t max_alloc_words); + // Allow each generation to reset any scratch space that it has + // contributed as it needs. + void release_scratch(); size_t large_typearray_limit(); @@ -482,6 +485,9 @@ private: bool should_do_concurrent_full_gc(GCCause::Cause cause); void collect_mostly_concurrent(GCCause::Cause cause); + // Save the tops of the spaces in all generations + void record_gen_tops_before_GC() PRODUCT_RETURN; + protected: virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); diff --git a/hotspot/src/share/vm/memory/genMarkSweep.cpp b/hotspot/src/share/vm/memory/genMarkSweep.cpp index e98f6793001..318a3525cb7 100644 --- a/hotspot/src/share/vm/memory/genMarkSweep.cpp +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp @@ -190,6 +190,10 @@ void GenMarkSweep::allocate_stacks() { void GenMarkSweep::deallocate_stacks() { + + GenCollectedHeap* gch = GenCollectedHeap::heap(); + gch->release_scratch(); + if (_preserved_oop_stack) { delete _preserved_mark_stack; _preserved_mark_stack = NULL; diff --git a/hotspot/src/share/vm/memory/generation.cpp b/hotspot/src/share/vm/memory/generation.cpp index 5ed3ec09b7b..efefddf96d4 100644 --- a/hotspot/src/share/vm/memory/generation.cpp +++ b/hotspot/src/share/vm/memory/generation.cpp @@ -32,6 +32,12 @@ Generation::Generation(ReservedSpace rs, size_t initial_size, int level) : vm_exit_during_initialization("Could not reserve enough space for " "object heap"); } + // Mangle all of the the initial generation. + if (ZapUnusedHeapArea) { + MemRegion mangle_region((HeapWord*)_virtual_space.low(), + (HeapWord*)_virtual_space.high()); + SpaceMangler::mangle_region(mangle_region); + } _reserved = MemRegion((HeapWord*)_virtual_space.low_boundary(), (HeapWord*)_virtual_space.high_boundary()); } @@ -505,8 +511,11 @@ bool OneContigSpaceCardGeneration::grow_by(size_t bytes) { _bts->resize(new_word_size); // Fix for bug #4668531 - MemRegion mangle_region(_the_space->end(), (HeapWord*)_virtual_space.high()); - _the_space->mangle_region(mangle_region); + if (ZapUnusedHeapArea) { + MemRegion mangle_region(_the_space->end(), + (HeapWord*)_virtual_space.high()); + SpaceMangler::mangle_region(mangle_region); + } // Expand space -- also expands space's BOT // (which uses (part of) shared array above) @@ -622,6 +631,14 @@ void OneContigSpaceCardGeneration::gc_epilogue(bool full) { // update the generation and space performance counters update_counters(); + if (ZapUnusedHeapArea) { + the_space()->check_mangled_unused_area_complete(); + } +} + +void OneContigSpaceCardGeneration::record_spaces_top() { + assert(ZapUnusedHeapArea, "Not mangling unused space"); + the_space()->set_top_for_allocations(); } void OneContigSpaceCardGeneration::verify(bool allow_dirty) { diff --git a/hotspot/src/share/vm/memory/generation.hpp b/hotspot/src/share/vm/memory/generation.hpp index 2e146d53844..d87ebc3e529 100644 --- a/hotspot/src/share/vm/memory/generation.hpp +++ b/hotspot/src/share/vm/memory/generation.hpp @@ -376,6 +376,9 @@ class Generation: public CHeapObj { // The default is to do nothing. virtual void gc_epilogue(bool full) {}; + // Save the high water marks for the used space in a generation. + virtual void record_spaces_top() {}; + // Some generations may need to be "fixed-up" after some allocation // activity to make them parsable again. The default is to do nothing. virtual void ensure_parsability() {}; @@ -476,6 +479,10 @@ class Generation: public CHeapObj { virtual void contribute_scratch(ScratchBlock*& list, Generation* requestor, size_t max_alloc_words) {} + // Give each generation an opportunity to do clean up for any + // contributed scratch. + virtual void reset_scratch() {}; + // When an older generation has been collected, and perhaps resized, // this method will be invoked on all younger generations (from older to // younger), allowing them to resize themselves as appropriate. @@ -699,6 +706,8 @@ class OneContigSpaceCardGeneration: public CardGeneration { virtual void gc_epilogue(bool full); + virtual void record_spaces_top(); + virtual void verify(bool allow_dirty); virtual void print_on(outputStream* st) const; }; diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp index 50dfd1df8d6..b3dab36a045 100644 --- a/hotspot/src/share/vm/memory/space.cpp +++ b/hotspot/src/share/vm/memory/space.cpp @@ -232,30 +232,44 @@ ContiguousSpace::new_dcto_cl(OopClosure* cl, return new ContiguousSpaceDCTOC(this, cl, precision, boundary); } -void Space::initialize(MemRegion mr, bool clear_space) { +void Space::initialize(MemRegion mr, + bool clear_space, + bool mangle_space) { HeapWord* bottom = mr.start(); HeapWord* end = mr.end(); assert(Universe::on_page_boundary(bottom) && Universe::on_page_boundary(end), "invalid space boundaries"); set_bottom(bottom); set_end(end); - if (clear_space) clear(); + if (clear_space) clear(mangle_space); } -void Space::clear() { - if (ZapUnusedHeapArea) mangle_unused_area(); +void Space::clear(bool mangle_space) { + if (ZapUnusedHeapArea && mangle_space) { + mangle_unused_area(); + } } -void ContiguousSpace::initialize(MemRegion mr, bool clear_space) +ContiguousSpace::ContiguousSpace(): CompactibleSpace(), _top(NULL) { + _mangler = new GenSpaceMangler(this); +} + +ContiguousSpace::~ContiguousSpace() { + delete _mangler; +} + +void ContiguousSpace::initialize(MemRegion mr, + bool clear_space, + bool mangle_space) { - CompactibleSpace::initialize(mr, clear_space); + CompactibleSpace::initialize(mr, clear_space, mangle_space); _concurrent_iteration_safe_limit = top(); } -void ContiguousSpace::clear() { +void ContiguousSpace::clear(bool mangle_space) { set_top(bottom()); set_saved_mark(); - Space::clear(); + Space::clear(mangle_space); } bool Space::is_in(const void* p) const { @@ -271,8 +285,8 @@ bool ContiguousSpace::is_free_block(const HeapWord* p) const { return p >= _top; } -void OffsetTableContigSpace::clear() { - ContiguousSpace::clear(); +void OffsetTableContigSpace::clear(bool mangle_space) { + ContiguousSpace::clear(mangle_space); _offsets.initialize_threshold(); } @@ -288,17 +302,46 @@ void OffsetTableContigSpace::set_end(HeapWord* new_end) { Space::set_end(new_end); } +#ifndef PRODUCT + +void ContiguousSpace::set_top_for_allocations(HeapWord* v) { + mangler()->set_top_for_allocations(v); +} +void ContiguousSpace::set_top_for_allocations() { + mangler()->set_top_for_allocations(top()); +} +void ContiguousSpace::check_mangled_unused_area(HeapWord* limit) { + mangler()->check_mangled_unused_area(limit); +} + +void ContiguousSpace::check_mangled_unused_area_complete() { + mangler()->check_mangled_unused_area_complete(); +} + +// Mangled only the unused space that has not previously +// been mangled and that has not been allocated since being +// mangled. void ContiguousSpace::mangle_unused_area() { - // to-space is used for storing marks during mark-sweep - mangle_region(MemRegion(top(), end())); + mangler()->mangle_unused_area(); +} +void ContiguousSpace::mangle_unused_area_complete() { + mangler()->mangle_unused_area_complete(); } - void ContiguousSpace::mangle_region(MemRegion mr) { - debug_only(Copy::fill_to_words(mr.start(), mr.word_size(), badHeapWord)); + // Although this method uses SpaceMangler::mangle_region() which + // is not specific to a space, the when the ContiguousSpace version + // is called, it is always with regard to a space and this + // bounds checking is appropriate. + MemRegion space_mr(bottom(), end()); + assert(space_mr.contains(mr), "Mangling outside space"); + SpaceMangler::mangle_region(mr); } +#endif // NOT_PRODUCT -void CompactibleSpace::initialize(MemRegion mr, bool clear_space) { - Space::initialize(mr, clear_space); +void CompactibleSpace::initialize(MemRegion mr, + bool clear_space, + bool mangle_space) { + Space::initialize(mr, clear_space, mangle_space); _compaction_top = bottom(); _next_compaction_space = NULL; } @@ -820,8 +863,8 @@ void ContiguousSpace::allocate_temporary_filler(int factor) { } } -void EdenSpace::clear() { - ContiguousSpace::clear(); +void EdenSpace::clear(bool mangle_space) { + ContiguousSpace::clear(mangle_space); set_soft_end(end()); } @@ -878,7 +921,7 @@ OffsetTableContigSpace::OffsetTableContigSpace(BlockOffsetSharedArray* sharedOff _par_alloc_lock(Mutex::leaf, "OffsetTableContigSpace par alloc lock", true) { _offsets.set_contig_space(this); - initialize(mr, true); + initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); } diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp index 37f726e5b3f..1cecd3a06ab 100644 --- a/hotspot/src/share/vm/memory/space.hpp +++ b/hotspot/src/share/vm/memory/space.hpp @@ -131,15 +131,17 @@ class Space: public CHeapObj { return MemRegion(bottom(), saved_mark_word()); } - // Initialization - virtual void initialize(MemRegion mr, bool clear_space); - virtual void clear(); + // Initialization. These may be run to reset an existing + // Space. + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); + virtual void clear(bool mangle_space); // For detecting GC bugs. Should only be called at GC boundaries, since // some unused space may be used as scratch space during GC's. // Default implementation does nothing. We also call this when expanding // a space to satisfy an allocation request. See bug #4668531 virtual void mangle_unused_area() {} + virtual void mangle_unused_area_complete() {} virtual void mangle_region(MemRegion mr) {} // Testers @@ -354,7 +356,7 @@ private: CompactibleSpace* _next_compaction_space; public: - virtual void initialize(MemRegion mr, bool clear_space); + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); // Used temporarily during a compaction phase to hold the value // top should have when compaction is complete. @@ -724,12 +726,14 @@ protected: /* continuously, but those that weren't need to have their thresholds */ \ /* re-initialized. Also mangles unused area for debugging. */ \ if (is_empty()) { \ - clear(); \ + clear(SpaceDecorator::Mangle); \ } else { \ if (ZapUnusedHeapArea) mangle_unused_area(); \ } \ } +class GenSpaceMangler; + // A space in which the free area is contiguous. It therefore supports // faster allocation, and compaction. class ContiguousSpace: public CompactibleSpace { @@ -738,13 +742,21 @@ class ContiguousSpace: public CompactibleSpace { protected: HeapWord* _top; HeapWord* _concurrent_iteration_safe_limit; + // A helper for mangling the unused area of the space in debug builds. + GenSpaceMangler* _mangler; + + GenSpaceMangler* mangler() { return _mangler; } // Allocation helpers (return NULL if full). inline HeapWord* allocate_impl(size_t word_size, HeapWord* end_value); inline HeapWord* par_allocate_impl(size_t word_size, HeapWord* end_value); public: - virtual void initialize(MemRegion mr, bool clear_space); + + ContiguousSpace(); + ~ContiguousSpace(); + + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); // Accessors HeapWord* top() const { return _top; } @@ -753,15 +765,34 @@ class ContiguousSpace: public CompactibleSpace { void set_saved_mark() { _saved_mark_word = top(); } void reset_saved_mark() { _saved_mark_word = bottom(); } - virtual void clear(); + virtual void clear(bool mangle_space); WaterMark bottom_mark() { return WaterMark(this, bottom()); } WaterMark top_mark() { return WaterMark(this, top()); } WaterMark saved_mark() { return WaterMark(this, saved_mark_word()); } bool saved_mark_at_top() const { return saved_mark_word() == top(); } - void mangle_unused_area(); - void mangle_region(MemRegion mr); + // In debug mode mangle (write it with a particular bit + // pattern) the unused part of a space. + + // Used to save the an address in a space for later use during mangling. + void set_top_for_allocations(HeapWord* v) PRODUCT_RETURN; + // Used to save the space's current top for later use during mangling. + void set_top_for_allocations() PRODUCT_RETURN; + + // Mangle regions in the space from the current top up to the + // previously mangled part of the space. + void mangle_unused_area() PRODUCT_RETURN; + // Mangle [top, end) + void mangle_unused_area_complete() PRODUCT_RETURN; + // Mangle the given MemRegion. + void mangle_region(MemRegion mr) PRODUCT_RETURN; + + // Do some sparse checking on the area that should have been mangled. + void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; + // Check the complete area that should have been mangled. + // This code may be NULL depending on the macro DEBUG_MANGLING. + void check_mangled_unused_area_complete() PRODUCT_RETURN; // Size computations: sizes in bytes. size_t capacity() const { return byte_size(bottom(), end()); } @@ -956,7 +987,7 @@ class EdenSpace : public ContiguousSpace { void set_soft_end(HeapWord* value) { _soft_end = value; } // Override. - void clear(); + void clear(bool mangle_space); // Set both the 'hard' and 'soft' limits (_end and _soft_end). void set_end(HeapWord* value) { @@ -1000,7 +1031,7 @@ class OffsetTableContigSpace: public ContiguousSpace { void set_bottom(HeapWord* value); void set_end(HeapWord* value); - void clear(); + void clear(bool mangle_space); inline HeapWord* block_start(const void* p) const; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index f54347f0251..fd490c9c033 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -589,9 +589,15 @@ class CommandLineFlags { develop(bool, ZapJNIHandleArea, trueInDebug, \ "Zap freed JNI handle space with 0xFEFEFEFE") \ \ - develop(bool, ZapUnusedHeapArea, false, \ + develop(bool, ZapUnusedHeapArea, trueInDebug, \ "Zap unused heap space with 0xBAADBABE") \ \ + develop(bool, TraceZapUnusedHeapArea, false, \ + "Trace zapping of unused heap space") \ + \ + develop(bool, CheckZapUnusedHeapArea, false, \ + "Check zapping of unused heap space") \ + \ develop(bool, PrintVMMessages, true, \ "Print vm messages on console") \ \ diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index c46312f49d7..120ef1f43ec 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -97,8 +97,12 @@ const int SerializePageShiftCount = 3; // object size. class HeapWord { friend class VMStructs; -private: + private: char* i; +#ifdef ASSERT + public: + char* value() { return i; } +#endif }; // HeapWordSize must be 2^LogHeapWordSize. From 398aa66a77bc8086ba00eb1a36295aca912cf39c Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 11 Jul 2008 16:11:34 -0700 Subject: [PATCH 013/289] 6718283: existing uses of *_FORMAT_W() were broken by 6521491 Reviewed-by: ysr, pbk --- .../parallelScavenge/psParallelCompact.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 2b25332ab96..7a41736fb63 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -200,8 +200,8 @@ void PSParallelCompact::print_chunk_ranges() for (unsigned int id = 0; id < last_space_id; ++id) { const MutableSpace* space = _space_info[id].space(); tty->print_cr("%u %s " - SIZE_FORMAT_W("10") " " SIZE_FORMAT_W("10") " " - SIZE_FORMAT_W("10") " " SIZE_FORMAT_W("10") " ", + SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) " " + SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) " ", id, space_names[id], summary_data().addr_to_chunk_idx(space->bottom()), summary_data().addr_to_chunk_idx(space->top()), @@ -213,8 +213,8 @@ void PSParallelCompact::print_chunk_ranges() void print_generic_summary_chunk(size_t i, const ParallelCompactData::ChunkData* c) { -#define CHUNK_IDX_FORMAT SIZE_FORMAT_W("7") -#define CHUNK_DATA_FORMAT SIZE_FORMAT_W("5") +#define CHUNK_IDX_FORMAT SIZE_FORMAT_W(7) +#define CHUNK_DATA_FORMAT SIZE_FORMAT_W(5) ParallelCompactData& sd = PSParallelCompact::summary_data(); size_t dci = c->destination() ? sd.addr_to_chunk_idx(c->destination()) : 0; @@ -269,9 +269,9 @@ print_initial_summary_chunk(size_t i, const ParallelCompactData::ChunkData* c, bool newline = true) { - tty->print(SIZE_FORMAT_W("5") " " PTR_FORMAT " " - SIZE_FORMAT_W("5") " " SIZE_FORMAT_W("5") " " - SIZE_FORMAT_W("5") " " SIZE_FORMAT_W("5") " %d", + tty->print(SIZE_FORMAT_W(5) " " PTR_FORMAT " " + SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " + SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d", i, c->destination(), c->partial_obj_size(), c->live_obj_size(), c->data_size(), c->source_chunk(), c->destination_count()); @@ -326,7 +326,7 @@ print_initial_summary_data(ParallelCompactData& summary_data, } print_initial_summary_chunk(i, c, false); - tty->print_cr(" %12.10f " SIZE_FORMAT_W("10") " " SIZE_FORMAT_W("10"), + tty->print_cr(" %12.10f " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10), reclaimed_ratio, dead_to_right, live_to_right); live_to_right -= c->data_size(); @@ -338,8 +338,8 @@ print_initial_summary_data(ParallelCompactData& summary_data, print_initial_summary_chunk(i, summary_data.chunk(i)); } - tty->print_cr("max: " SIZE_FORMAT_W("4") " d2r=" SIZE_FORMAT_W("10") " " - "l2r=" SIZE_FORMAT_W("10") " max_ratio=%14.12f", + tty->print_cr("max: " SIZE_FORMAT_W(4) " d2r=" SIZE_FORMAT_W(10) " " + "l2r=" SIZE_FORMAT_W(10) " max_ratio=%14.12f", max_reclaimed_ratio_chunk, max_dead_to_right, max_live_to_right, max_reclaimed_ratio); } @@ -1121,8 +1121,8 @@ PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id, HeapWord* chunk_destination = cp->destination(); const size_t cur_deadwood = pointer_delta(dense_prefix, chunk_destination); if (TraceParallelOldGCDensePrefix && Verbose) { - tty->print_cr("c#=" SIZE_FORMAT_W("04") " dst=" PTR_FORMAT " " - "dp=" SIZE_FORMAT_W("08") " " "cdw=" SIZE_FORMAT_W("08"), + tty->print_cr("c#=" SIZE_FORMAT_W(4) " dst=" PTR_FORMAT " " + "dp=" SIZE_FORMAT_W(8) " " "cdw=" SIZE_FORMAT_W(8), sd.chunk(cp), chunk_destination, dense_prefix, cur_deadwood); } @@ -1147,7 +1147,7 @@ PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id, return dense_prefix; } if (TraceParallelOldGCDensePrefix && Verbose) { - tty->print_cr("backing up from c=" SIZE_FORMAT_W("4") " d2r=%10.8f " + tty->print_cr("backing up from c=" SIZE_FORMAT_W(4) " d2r=%10.8f " "pc_d2r=%10.8f", sd.chunk(cp), density_to_right, prev_chunk_density_to_right); } @@ -1184,7 +1184,7 @@ void PSParallelCompact::print_dense_prefix_stats(const char* const algorithm, const size_t live_to_right = new_top - cp->destination(); const size_t dead_to_right = space->top() - addr - live_to_right; - tty->print_cr("%s=" PTR_FORMAT " dpc=" SIZE_FORMAT_W("05") " " + tty->print_cr("%s=" PTR_FORMAT " dpc=" SIZE_FORMAT_W(5) " " "spl=" SIZE_FORMAT " " "d2l=" SIZE_FORMAT " d2l%%=%6.4f " "d2r=" SIZE_FORMAT " l2r=" SIZE_FORMAT @@ -2513,7 +2513,7 @@ void PSParallelCompact::enqueue_chunk_draining_tasks(GCTaskQueue* q, if (TraceParallelOldGCCompactionPhase && Verbose) { const size_t count_mod_8 = fillable_chunks & 7; if (count_mod_8 == 0) gclog_or_tty->print("fillable: "); - gclog_or_tty->print(" " SIZE_FORMAT_W("7"), cur); + gclog_or_tty->print(" " SIZE_FORMAT_W(7), cur); if (count_mod_8 == 7) gclog_or_tty->cr(); } From 038a30dde34c5e17ed802ff43397099e6d3a4b77 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 11 Jul 2008 16:11:43 -0700 Subject: [PATCH 014/289] 6483129: par compact assertion failure (new_top > bottom) Avoid computing the dense prefix if a space is empty Reviewed-by: pbk, tonyp --- .../parallelScavenge/psParallelCompact.cpp | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 7a41736fb63..27b4ea90f56 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -1524,48 +1524,53 @@ void PSParallelCompact::summarize_space(SpaceId id, bool maximum_compaction) { assert(id < last_space_id, "id out of range"); + assert(_space_info[id].dense_prefix() == _space_info[id].space()->bottom(), + "should have been set in summarize_spaces_quick()"); const MutableSpace* space = _space_info[id].space(); - HeapWord** new_top_addr = _space_info[id].new_top_addr(); - - HeapWord* dense_prefix_end = compute_dense_prefix(id, maximum_compaction); - _space_info[id].set_dense_prefix(dense_prefix_end); + if (_space_info[id].new_top() != space->bottom()) { + HeapWord* dense_prefix_end = compute_dense_prefix(id, maximum_compaction); + _space_info[id].set_dense_prefix(dense_prefix_end); #ifndef PRODUCT - if (TraceParallelOldGCDensePrefix) { - print_dense_prefix_stats("ratio", id, maximum_compaction, dense_prefix_end); - HeapWord* addr = compute_dense_prefix_via_density(id, maximum_compaction); - print_dense_prefix_stats("density", id, maximum_compaction, addr); - } + if (TraceParallelOldGCDensePrefix) { + print_dense_prefix_stats("ratio", id, maximum_compaction, + dense_prefix_end); + HeapWord* addr = compute_dense_prefix_via_density(id, maximum_compaction); + print_dense_prefix_stats("density", id, maximum_compaction, addr); + } #endif // #ifndef PRODUCT - // If dead space crosses the dense prefix boundary, it is (at least partially) - // filled with a dummy object, marked live and added to the summary data. - // This simplifies the copy/update phase and must be done before the final - // locations of objects are determined, to prevent leaving a fragment of dead - // space that is too small to fill with an object. - if (!maximum_compaction && dense_prefix_end != space->bottom()) { - fill_dense_prefix_end(id); - } + // If dead space crosses the dense prefix boundary, it is (at least + // partially) filled with a dummy object, marked live and added to the + // summary data. This simplifies the copy/update phase and must be done + // before the final locations of objects are determined, to prevent leaving + // a fragment of dead space that is too small to fill with an object. + if (!maximum_compaction && dense_prefix_end != space->bottom()) { + fill_dense_prefix_end(id); + } - // Compute the destination of each Chunk, and thus each object. - _summary_data.summarize_dense_prefix(space->bottom(), dense_prefix_end); - _summary_data.summarize(dense_prefix_end, space->end(), - dense_prefix_end, space->top(), - new_top_addr); + // Compute the destination of each Chunk, and thus each object. + _summary_data.summarize_dense_prefix(space->bottom(), dense_prefix_end); + _summary_data.summarize(dense_prefix_end, space->end(), + dense_prefix_end, space->top(), + _space_info[id].new_top_addr()); + } if (TraceParallelOldGCSummaryPhase) { const size_t chunk_size = ParallelCompactData::ChunkSize; + HeapWord* const dense_prefix_end = _space_info[id].dense_prefix(); const size_t dp_chunk = _summary_data.addr_to_chunk_idx(dense_prefix_end); const size_t dp_words = pointer_delta(dense_prefix_end, space->bottom()); - const HeapWord* nt_aligned_up = _summary_data.chunk_align_up(*new_top_addr); + HeapWord* const new_top = _space_info[id].new_top(); + const HeapWord* nt_aligned_up = _summary_data.chunk_align_up(new_top); const size_t cr_words = pointer_delta(nt_aligned_up, dense_prefix_end); tty->print_cr("id=%d cap=" SIZE_FORMAT " dp=" PTR_FORMAT " " "dp_chunk=" SIZE_FORMAT " " "dp_count=" SIZE_FORMAT " " "cr_count=" SIZE_FORMAT " " "nt=" PTR_FORMAT, id, space->capacity_in_words(), dense_prefix_end, dp_chunk, dp_words / chunk_size, - cr_words / chunk_size, *new_top_addr); + cr_words / chunk_size, new_top); } } From 26625ab7f58d0741a1a3536746a819fd4da7c7b5 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 11 Jul 2008 16:11:50 -0700 Subject: [PATCH 015/289] 6724367: par compact could clear less young gen summary data Reviewed-by: jmasa, apetrusenko --- .../parallelScavenge/psParallelCompact.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 27b4ea90f56..0b0d981fdc4 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -1639,7 +1639,7 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm, const size_t live = pointer_delta(_space_info[id].new_top(), space->bottom()); const size_t available = pointer_delta(target_space_end, *new_top_addr); - if (live <= available) { + if (live > 0 && live <= available) { // All the live data will fit. if (TraceParallelOldGCSummaryPhase) { tty->print_cr("summarizing %d into old_space @ " PTR_FORMAT, @@ -1649,16 +1649,18 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm, space->bottom(), space->top(), new_top_addr); - // Reset the new_top value for the space. - _space_info[id].set_new_top(space->bottom()); - // Clear the source_chunk field for each chunk in the space. + HeapWord* const new_top = _space_info[id].new_top(); + HeapWord* const clear_end = _summary_data.chunk_align_up(new_top); ChunkData* beg_chunk = _summary_data.addr_to_chunk_ptr(space->bottom()); - ChunkData* end_chunk = _summary_data.addr_to_chunk_ptr(space->top() - 1); - while (beg_chunk <= end_chunk) { + ChunkData* end_chunk = _summary_data.addr_to_chunk_ptr(clear_end); + while (beg_chunk < end_chunk) { beg_chunk->set_source_chunk(0); ++beg_chunk; } + + // Reset the new_top value for the space. + _space_info[id].set_new_top(space->bottom()); } } From e9e432633bdaa3b094c84f1d85ed476d5cc0eab2 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Mon, 14 Jul 2008 04:12:47 -0700 Subject: [PATCH 016/289] 6720130: NUMA allocator: The linux version should search for libnuma.so.1 Search for libnuma.so.1 on Linux and liblgrp.so.1 on Solaris. Reviewed-by: jmasa --- hotspot/src/os/linux/vm/os_linux.cpp | 2 +- hotspot/src/os/solaris/vm/os_solaris.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 73bcd1d0733..831cffcb81b 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2278,7 +2278,7 @@ void os::Linux::libnuma_init() { dlsym(RTLD_DEFAULT, "sched_getcpu"))); if (sched_getcpu() != -1) { // Does it work? - void *handle = dlopen("libnuma.so", RTLD_LAZY); + void *handle = dlopen("libnuma.so.1", RTLD_LAZY); if (handle != NULL) { set_numa_node_to_cpus(CAST_TO_FN_PTR(numa_node_to_cpus_func_t, dlsym(handle, "numa_node_to_cpus"))); diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index ce6765e8d50..99005264c7b 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -4570,7 +4570,7 @@ void os::Solaris::synchronization_init() { } void os::Solaris::liblgrp_init() { - void *handle = dlopen("liblgrp.so", RTLD_LAZY); + void *handle = dlopen("liblgrp.so.1", RTLD_LAZY); if (handle != NULL) { os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home"))); os::Solaris::set_lgrp_init(CAST_TO_FN_PTR(lgrp_init_func_t, dlsym(handle, "lgrp_init"))); From a8fc1db8c1e873443bdc011e0803f45c265528ff Mon Sep 17 00:00:00 2001 From: Chuck Rasbold Date: Wed, 16 Jul 2008 10:08:57 -0700 Subject: [PATCH 017/289] 6707044: uncommon_trap of ifnull bytecode leaves garbage on expression stack Remove call to repush_if_args() Reviewed-by: kvn, jrose --- hotspot/src/share/vm/opto/parse2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index b3e0a9aff10..e244d6a098e 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -875,6 +875,8 @@ bool Parse::seems_never_taken(float prob) { return prob < PROB_MIN; } +//-------------------------------repush_if_args-------------------------------- +// Push arguments of an "if" bytecode back onto the stack by adjusting _sp. inline void Parse::repush_if_args() { #ifndef PRODUCT if (PrintOpto && WizardMode) { @@ -906,7 +908,6 @@ void Parse::do_ifnull(BoolTest::mask btest) { if (PrintOpto && Verbose) tty->print_cr("Never-taken backedge stops compilation at bci %d",bci()); #endif - repush_if_args(); // to gather stats on loop // We need to mark this branch as taken so that if we recompile we will // see that it is possible. In the tiered system the interpreter doesn't // do profiling and by the time we get to the lower tier from the interpreter From fae39068e8e2e14e65ac5f4e906e60efc90ba241 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 16 Jul 2008 16:04:39 -0700 Subject: [PATCH 018/289] 6723160: Nightly failure: Error: meet not symmetric Add missing _instance_id settings and other EA fixes. Reviewed-by: rasbold --- hotspot/src/share/vm/adlc/formssel.cpp | 2 + hotspot/src/share/vm/opto/callnode.cpp | 58 ++------------- hotspot/src/share/vm/opto/cfgnode.cpp | 6 +- hotspot/src/share/vm/opto/compile.cpp | 44 ++++++++--- hotspot/src/share/vm/opto/escape.cpp | 23 ++++-- hotspot/src/share/vm/opto/macro.cpp | 77 +++++++++++-------- hotspot/src/share/vm/opto/macro.hpp | 2 +- hotspot/src/share/vm/opto/memnode.cpp | 4 +- hotspot/src/share/vm/opto/node.hpp | 4 + hotspot/src/share/vm/opto/type.cpp | 35 +++------ hotspot/test/compiler/6724218/Test.java | 98 +++++++++++++++++++++++++ 11 files changed, 224 insertions(+), 129 deletions(-) create mode 100644 hotspot/test/compiler/6724218/Test.java diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index 47fe6ae04eb..b45de088afb 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -3825,6 +3825,8 @@ int MatchRule::is_expensive() const { strcmp(opType,"ConvL2D")==0 || strcmp(opType,"ConvL2F")==0 || strcmp(opType,"ConvL2I")==0 || + strcmp(opType,"DecodeN")==0 || + strcmp(opType,"EncodeP")==0 || strcmp(opType,"RoundDouble")==0 || strcmp(opType,"RoundFloat")==0 || strcmp(opType,"ReverseBytesI")==0 || diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index 84015b5335c..389db14fed5 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -631,61 +631,13 @@ uint CallNode::match_edge(uint idx) const { bool CallNode::may_modify(const TypePtr *addr_t, PhaseTransform *phase) { const TypeOopPtr *adrInst_t = addr_t->isa_oopptr(); - // if not an InstPtr or not an instance type, assume the worst - if (adrInst_t == NULL || !adrInst_t->is_known_instance_field()) { + // If not an OopPtr or not an instance type, assume the worst. + // Note: currently this method is called only for instance types. + if (adrInst_t == NULL || !adrInst_t->is_known_instance()) { return true; } - Compile *C = phase->C; - int offset = adrInst_t->offset(); - assert(adrInst_t->klass_is_exact() && offset >= 0, "should be valid offset"); - ciKlass* adr_k = adrInst_t->klass(); - assert(adr_k->is_loaded() && - adr_k->is_java_klass() && - !adr_k->is_interface(), - "only non-abstract classes are expected"); - - int base_idx = C->get_alias_index(adrInst_t); - int size = BytesPerLong; // If we don't know the size, assume largest. - if (adrInst_t->isa_instptr()) { - ciField* field = C->alias_type(base_idx)->field(); - if (field != NULL) { - size = field->size_in_bytes(); - } - } else { - assert(adrInst_t->isa_aryptr(), "only arrays are expected"); - size = type2aelembytes(adr_k->as_array_klass()->element_type()->basic_type()); - } - - ciMethod * meth = is_CallStaticJava() ? as_CallStaticJava()->method() : NULL; - BCEscapeAnalyzer *bcea = (meth != NULL) ? meth->get_bcea() : NULL; - - const TypeTuple * d = tf()->domain(); - for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { - const Type* t = d->field_at(i); - Node *arg = in(i); - const Type *at = phase->type(arg); - if (at == TypePtr::NULL_PTR || at == Type::TOP) - continue; // null can't affect anything - - const TypeOopPtr *at_ptr = at->isa_oopptr(); - if (!arg->is_top() && (t->isa_oopptr() != NULL || - t->isa_ptr() && at_ptr != NULL)) { - assert(at_ptr != NULL, "expecting an OopPtr"); - ciKlass* at_k = at_ptr->klass(); - if ((adrInst_t->base() == at_ptr->base()) && - at_k->is_loaded() && - at_k->is_java_klass()) { - // If we have found an argument matching addr_t, check if the field - // at the specified offset is modified. - if ((at_k->is_interface() || adr_k == at_k || - adr_k->is_subclass_of(at_k) && !at_ptr->klass_is_exact()) && - (bcea == NULL || - bcea->is_arg_modified(i - TypeFunc::Parms, offset, size))) { - return true; - } - } - } - } + // The instance_id is set only for scalar-replaceable allocations which + // are not passed as arguments according to Escape Analysis. return false; } diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index 6087c17e0dd..0e7b2845dbc 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -713,7 +713,9 @@ PhiNode* PhiNode::split_out_instance(const TypePtr* at, PhaseIterGVN *igvn) cons assert(type() == Type::MEMORY && (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM || t->isa_oopptr() && !t->is_oopptr()->is_known_instance() && - t->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop), + t->is_oopptr()->cast_to_exactness(true) + ->is_oopptr()->cast_to_ptr_type(t_oop->ptr()) + ->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop), "bottom or raw memory required"); // Check if an appropriate node already exists. @@ -1089,6 +1091,8 @@ Node* PhiNode::unique_input(PhaseTransform* phase) { if (rc == NULL || phase->type(rc) == Type::TOP) continue; // ignore unreachable control path Node* n = in(i); + if (n == NULL) + continue; Node* un = n->uncast(); if (un == NULL || un == this || phase->type(un) == Type::TOP) { continue; // ignore if top, or in(i) and "this" are in a data cycle diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 117fa54ff1b..c57a460d45d 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -999,9 +999,14 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { int offset = tj->offset(); TypePtr::PTR ptr = tj->ptr(); + // Known instance (scalarizable allocation) alias only with itself. + bool is_known_inst = tj->isa_oopptr() != NULL && + tj->is_oopptr()->is_known_instance(); + // Process weird unsafe references. if (offset == Type::OffsetBot && (tj->isa_instptr() /*|| tj->isa_klassptr()*/)) { assert(InlineUnsafeOps, "indeterminate pointers come only from unsafe ops"); + assert(!is_known_inst, "scalarizable allocation should not have unsafe references"); tj = TypeOopPtr::BOTTOM; ptr = tj->ptr(); offset = tj->offset(); @@ -1009,14 +1014,20 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { // Array pointers need some flattening const TypeAryPtr *ta = tj->isa_aryptr(); - if( ta && _AliasLevel >= 2 ) { + if( ta && is_known_inst ) { + if ( offset != Type::OffsetBot && + offset > arrayOopDesc::length_offset_in_bytes() ) { + offset = Type::OffsetBot; // Flatten constant access into array body only + tj = ta = TypeAryPtr::make(ptr, ta->ary(), ta->klass(), true, offset, ta->instance_id()); + } + } else if( ta && _AliasLevel >= 2 ) { // For arrays indexed by constant indices, we flatten the alias // space to include all of the array body. Only the header, klass // and array length can be accessed un-aliased. if( offset != Type::OffsetBot ) { if( ta->const_oop() ) { // methodDataOop or methodOop offset = Type::OffsetBot; // Flatten constant access into array body - tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),ta->ary(),ta->klass(),false,Type::OffsetBot, ta->instance_id()); + tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),ta->ary(),ta->klass(),false,offset); } else if( offset == arrayOopDesc::length_offset_in_bytes() ) { // range is OK as-is. tj = ta = TypeAryPtr::RANGE; @@ -1030,29 +1041,29 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { ptr = TypePtr::BotPTR; } else { // Random constant offset into array body offset = Type::OffsetBot; // Flatten constant access into array body - tj = ta = TypeAryPtr::make(ptr,ta->ary(),ta->klass(),false,Type::OffsetBot, ta->instance_id()); + tj = ta = TypeAryPtr::make(ptr,ta->ary(),ta->klass(),false,offset); } } // Arrays of fixed size alias with arrays of unknown size. if (ta->size() != TypeInt::POS) { const TypeAry *tary = TypeAry::make(ta->elem(), TypeInt::POS); - tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,ta->klass(),false,offset, ta->instance_id()); + tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,ta->klass(),false,offset); } // Arrays of known objects become arrays of unknown objects. if (ta->elem()->isa_narrowoop() && ta->elem() != TypeNarrowOop::BOTTOM) { const TypeAry *tary = TypeAry::make(TypeNarrowOop::BOTTOM, ta->size()); - tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset, ta->instance_id()); + tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset); } if (ta->elem()->isa_oopptr() && ta->elem() != TypeInstPtr::BOTTOM) { const TypeAry *tary = TypeAry::make(TypeInstPtr::BOTTOM, ta->size()); - tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset, ta->instance_id()); + tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset); } // Arrays of bytes and of booleans both use 'bastore' and 'baload' so // cannot be distinguished by bytecode alone. if (ta->elem() == TypeInt::BOOL) { const TypeAry *tary = TypeAry::make(TypeInt::BYTE, ta->size()); ciKlass* aklass = ciTypeArrayKlass::make(T_BYTE); - tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,aklass,false,offset, ta->instance_id()); + tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,aklass,false,offset); } // During the 2nd round of IterGVN, NotNull castings are removed. // Make sure the Bottom and NotNull variants alias the same. @@ -1072,21 +1083,24 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { if( ptr == TypePtr::Constant ) { // No constant oop pointers (such as Strings); they alias with // unknown strings. + assert(!is_known_inst, "not scalarizable allocation"); tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset); - } else if( to->is_known_instance_field() ) { + } else if( is_known_inst ) { tj = to; // Keep NotNull and klass_is_exact for instance type } else if( ptr == TypePtr::NotNull || to->klass_is_exact() ) { // During the 2nd round of IterGVN, NotNull castings are removed. // Make sure the Bottom and NotNull variants alias the same. // Also, make sure exact and non-exact variants alias the same. - tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset, to->instance_id()); + tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset); } // Canonicalize the holder of this field ciInstanceKlass *k = to->klass()->as_instance_klass(); if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) { // First handle header references such as a LoadKlassNode, even if the // object's klass is unloaded at compile time (4965979). - tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset, to->instance_id()); + if (!is_known_inst) { // Do it only for non-instance types + tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset); + } } else if (offset < 0 || offset >= k->size_helper() * wordSize) { to = NULL; tj = TypeOopPtr::BOTTOM; @@ -1094,7 +1108,11 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { } else { ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset); if (!k->equals(canonical_holder) || tj->offset() != offset) { - tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, false, NULL, offset, to->instance_id()); + if( is_known_inst ) { + tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, NULL, offset, to->instance_id()); + } else { + tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, false, NULL, offset); + } } } } @@ -1280,7 +1298,9 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr assert(flat != TypePtr::BOTTOM, "cannot alias-analyze an untyped ptr"); if (flat->isa_oopptr() && !flat->isa_klassptr()) { const TypeOopPtr* foop = flat->is_oopptr(); - const TypePtr* xoop = foop->cast_to_exactness(!foop->klass_is_exact())->is_ptr(); + // Scalarizable allocations have exact klass always. + bool exact = !foop->klass_is_exact() || foop->is_known_instance(); + const TypePtr* xoop = foop->cast_to_exactness(exact)->is_ptr(); assert(foop == flatten_alias_type(xoop), "exactness must not affect alias type"); } assert(flat == flatten_alias_type(flat), "exact bit doesn't matter"); diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index 795741284b0..8a779f59431 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -717,12 +717,17 @@ Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArra } } } - if (is_instance && result->is_Phi()) { + if (result->is_Phi()) { PhiNode *mphi = result->as_Phi(); assert(mphi->bottom_type() == Type::MEMORY, "memory phi required"); const TypePtr *t = mphi->adr_type(); if (C->get_alias_index(t) != alias_idx) { + // Create a new Phi with the specified alias index type. result = split_memory_phi(mphi, alias_idx, orig_phis, phase); + } else if (!is_instance) { + // Push all non-instance Phis on the orig_phis worklist to update inputs + // during Phase 4 if needed. + orig_phis.append_if_missing(mphi); } } // the result is either MemNode, PhiNode, InitializeNode. @@ -859,10 +864,14 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) !n->is_CheckCastPP()) // not unique CheckCastPP. continue; // The inline code for Object.clone() casts the allocation result to - // java.lang.Object and then to the the actual type of the allocated + // java.lang.Object and then to the actual type of the allocated // object. Detect this case and use the second cast. + // Also detect j.l.reflect.Array.newInstance(jobject, jint) case when + // the allocation result is cast to java.lang.Object and then + // to the actual Array type. if (alloc->is_Allocate() && n->as_Type()->type() == TypeInstPtr::NOTNULL - && igvn->type(alloc->in(AllocateNode::KlassNode)) != TypeKlassPtr::OBJECT) { + && (alloc->is_AllocateArray() || + igvn->type(alloc->in(AllocateNode::KlassNode)) != TypeKlassPtr::OBJECT)) { Node *cast2 = NULL; for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node *use = n->fast_out(i); @@ -878,7 +887,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) } } set_escape_state(n->_idx, es); - // in order for an object to be stackallocatable, it must be: + // in order for an object to be scalar-replaceable, it must be: // - a direct allocation (not a call returning an object) // - non-escaping // - eligible to be a unique type @@ -888,7 +897,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) const TypeOopPtr *t = igvn->type(n)->isa_oopptr(); if (t == NULL) continue; // not a TypeInstPtr - tinst = t->cast_to_instance_id(ni); + tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni); igvn->hash_delete(n); igvn->set_type(n, tinst); n->raise_bottom_type(tinst); @@ -1204,8 +1213,8 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist) // to recursively process Phi's encounted on the input memory // chains as is done in split_memory_phi() since they will // also be processed here. - while (orig_phis.length() != 0) { - PhiNode *phi = orig_phis.pop(); + for (int j = 0; j < orig_phis.length(); j++) { + PhiNode *phi = orig_phis.at(j); int alias_idx = _compile->get_alias_index(phi->adr_type()); igvn->hash_delete(phi); for (uint i = 1; i < phi->req(); i++) { diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index cd38a4be324..3e036249edd 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -231,8 +231,7 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me } else { return mem; } - if (mem == orig_mem) - return mem; + assert(mem != orig_mem, "dead memory loop"); } } @@ -241,21 +240,44 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me // on the input paths. // Note: this function is recursive, its depth is limied by the "level" argument // Returns the computed Phi, or NULL if it cannot compute it. -Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, int level) { - - if (level <= 0) { - return NULL; - } +Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level) { + assert(mem->is_Phi(), "sanity"); int alias_idx = C->get_alias_index(adr_t); int offset = adr_t->offset(); int instance_id = adr_t->instance_id(); + // Check if an appropriate value phi already exists. + Node* region = mem->in(0); + for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { + Node* phi = region->fast_out(k); + if (phi->is_Phi() && phi != mem && + phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { + return phi; + } + } + // Check if an appropriate new value phi already exists. + Node* new_phi = NULL; + uint size = value_phis->size(); + for (uint i=0; i < size; i++) { + if ( mem->_idx == value_phis->index_at(i) ) { + return value_phis->node_at(i); + } + } + + if (level <= 0) { + return NULL; + } Node *start_mem = C->start()->proj_out(TypeFunc::Memory); Node *alloc_mem = alloc->in(TypeFunc::Memory); uint length = mem->req(); GrowableArray values(length, length, NULL); + // create a new Phi for the value + PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); + transform_later(phi); + value_phis->push(phi, mem->_idx); + for (uint j = 1; j < length; j++) { Node *in = mem->in(j); if (in == NULL || in->is_top()) { @@ -280,33 +302,17 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * } else if(val->is_Proj() && val->in(0) == alloc) { values.at_put(j, _igvn.zerocon(ft)); } else if (val->is_Phi()) { - // Check if an appropriate node already exists. - Node* region = val->in(0); - Node* old_phi = NULL; - for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) { - Node* phi = region->fast_out(k); - if (phi->is_Phi() && phi != val && - phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) { - old_phi = phi; - break; - } - } - if (old_phi == NULL) { - val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, level-1); - if (val == NULL) { - return NULL; - } - values.at_put(j, val); - } else { - values.at_put(j, old_phi); + val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, value_phis, level-1); + if (val == NULL) { + return NULL; } + values.at_put(j, val); } else { return NULL; // unknown node on this path } } } - // create a new Phi for the value - PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset); + // Set Phi's inputs for (uint j = 1; j < length; j++) { if (values.at(j) == mem) { phi->init_req(j, phi); @@ -314,7 +320,6 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * phi->init_req(j, values.at(j)); } } - transform_later(phi); return phi; } @@ -329,7 +334,8 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type Node *start_mem = C->start()->proj_out(TypeFunc::Memory); Node *alloc_ctrl = alloc->in(TypeFunc::Control); Node *alloc_mem = alloc->in(TypeFunc::Memory); - VectorSet visited(Thread::current()->resource_area()); + Arena *a = Thread::current()->resource_area(); + VectorSet visited(a); bool done = sfpt_mem == alloc_mem; @@ -389,9 +395,18 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type return mem->in(MemNode::ValueIn); } else if (mem->is_Phi()) { // attempt to produce a Phi reflecting the values on the input paths of the Phi - Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, 8); + Node_Stack value_phis(a, 8); + Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, 8); if (phi != NULL) { return phi; + } else { + // Kill all new Phis + while(value_phis.is_nonempty()) { + Node* n = value_phis.node(); + _igvn.hash_delete(n); + _igvn.subsume_node(n, C->top()); + value_phis.pop(); + } } } } diff --git a/hotspot/src/share/vm/opto/macro.hpp b/hotspot/src/share/vm/opto/macro.hpp index 0f784aafc02..89ed2bd2f47 100644 --- a/hotspot/src/share/vm/opto/macro.hpp +++ b/hotspot/src/share/vm/opto/macro.hpp @@ -79,7 +79,7 @@ private: const TypeFunc* slow_call_type, address slow_call_address); Node *value_from_mem(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc); - Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc, int level); + Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level); bool eliminate_allocate_node(AllocateNode *alloc); bool can_eliminate_allocation(AllocateNode *alloc, GrowableArray & safepoints); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 5015d99c483..8388753e937 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -135,7 +135,9 @@ Node *MemNode::optimize_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGV const TypePtr *t = mphi->adr_type(); if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM || t->isa_oopptr() && !t->is_oopptr()->is_known_instance() && - t->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop) { + t->is_oopptr()->cast_to_exactness(true) + ->is_oopptr()->cast_to_ptr_type(t_oop->ptr()) + ->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop) { // clone the Phi with our address type result = mphi->split_out_instance(t_adr, igvn); } else { diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index 7f78b426b1c..e027265bf67 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -1399,6 +1399,10 @@ public: uint index() const { return _inode_top->indx; } + uint index_at(uint i) const { + assert(_inodes + i <= _inode_top, "in range"); + return _inodes[i].indx; + } void set_node(Node *n) { _inode_top->node = n; } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index bb6c959388f..3a77c9da4f0 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -2218,7 +2218,7 @@ const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const { return make(ptr, _offset); } -//-----------------------------cast_to_instance------------------------------- +//-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeOopPtr::cast_to_instance_id(int instance_id) const { // There are no instances of a general oop. // Return self unchanged. @@ -2610,8 +2610,7 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, // Ptr is never Null assert( ptr != Null, "NULL pointers are not typed" ); - if ( instance_id > 0 ) - xk = true; // instances are always exactly typed + assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = false; if (ptr == Constant) { // Note: This case includes meta-object constants, such as methods. @@ -2650,16 +2649,10 @@ const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const { return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id); } -//-----------------------------cast_to_instance------------------------------- +//-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; - bool exact = _klass_is_exact; - PTR ptr_t = _ptr; - if ( instance_id > 0 ) { // instances are always exactly typed - if (UseExactTypes) exact = true; - ptr_t = NotNull; - } - return make(ptr_t, klass(), exact, const_oop(), _offset, instance_id); + return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id); } //------------------------------xmeet_unloaded--------------------------------- @@ -2899,6 +2892,7 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const { xk = above_centerline(ptr) ? tinst_xk : false; // Watch out for Constant vs. AnyNull interface. if (ptr == Constant) ptr = NotNull; // forget it was a constant + instance_id = InstanceBot; } ciObject* o = NULL; // the Constant value, if any if (ptr == Constant) { @@ -2989,6 +2983,7 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const { // class hierarchy - which means we have to fall to at least NotNull. if( ptr == TopPTR || ptr == AnyNull || ptr == Constant ) ptr = NotNull; + instance_id = InstanceBot; // Now we find the LCA of Java classes ciKlass* k = this_klass->least_common_ancestor(tinst_klass); @@ -3101,8 +3096,7 @@ const TypeAryPtr *TypeAryPtr::make( PTR ptr, const TypeAry *ary, ciKlass* k, boo assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); if (!xk) xk = ary->ary_must_be_exact(); - if ( instance_id > 0 ) - xk = true; // instances are always exactly typed + assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id))->hashcons(); } @@ -3113,8 +3107,7 @@ const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ci "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); if (!xk) xk = (o != NULL) || ary->ary_must_be_exact(); - if ( instance_id > 0 ) - xk = true; // instances are always exactly typed + assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id))->hashcons(); } @@ -3134,16 +3127,10 @@ const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const { return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id); } -//-----------------------------cast_to_instance------------------------------- +//-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; - bool exact = _klass_is_exact; - PTR ptr_t = _ptr; - if ( instance_id > 0 ) { // instances are always exactly typed - if (UseExactTypes) exact = true; - ptr_t = NotNull; - } - return make(ptr_t, const_oop(), _ary, klass(), exact, _offset, instance_id); + return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id); } //-----------------------------narrow_size_type------------------------------- @@ -3300,6 +3287,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { } else { // Something like byte[int+] meets char[int+]. // This must fall to bottom, not (int[-128..65535])[int+]. + instance_id = InstanceBot; tary = TypeAry::make(Type::BOTTOM, tary->_size); } } @@ -3316,6 +3304,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { if( tap->const_oop() != NULL && !o->equals(tap->const_oop()) ) { ptr = NotNull; o = NULL; + instance_id = InstanceBot; } } else if( above_centerline(_ptr) ) { o = tap->const_oop(); diff --git a/hotspot/test/compiler/6724218/Test.java b/hotspot/test/compiler/6724218/Test.java new file mode 100644 index 00000000000..c2835168567 --- /dev/null +++ b/hotspot/test/compiler/6724218/Test.java @@ -0,0 +1,98 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6724218 + * @summary Fix raise_LCA_above_marks() early termination + * @run main/othervm -Xbatch -XX:CompileCommand=exclude,Test.update Test + */ + +public class Test { + Test next = null; + Object value = null; + + static boolean _closed = false; + static int size = 0; + static Test list = null; + static int cache_size = 0; + static Test cache = null; + + Object get(int i) { + Test t = list; + list = t.next; + size -= 1; + Object o = t.value; + if (i > 0) { + t.next = cache; + t.value = null; + cache = t; + cache_size = +1; + } + return o; + } + + void update() { + // Exclude compilation of this one. + if (size == 0) { + Test t; + if (cache_size > 0) { + t = cache; + cache = t.next; + cache_size = -1; + } else { + t = new Test(); + } + t.value = new Object(); + t.next = list; + list = t; + size += 1; + } + } + + synchronized Object test(int i) { + while (true) { + if (_closed) { + return null; + } else if (size > 0) { + return get(i); + } + update(); + } + } + + public static void main(String argv[]) throws Exception { + Test t = new Test(); + int lim = 500000; + Object o; + for (int j = 0; j < lim; j++) { + o = t.test(j&1); + if (o == null) { + throw new Exception("*** Failed on iteration " + j); + } + if ((j&1) == 0) { + t.update(); + } + } + } +} From 1193f0f9dbe9e365e86f1865d828a86bccbc39ce Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 17 Jul 2008 10:26:33 -0700 Subject: [PATCH 019/289] 6723228: NUMA allocator: assert(lgrp_id != -1, "No lgrp_id set") 6723229: NUMA allocator: assert(lgrp_num > 0, "There should be at least one locality group") The fix takes care of the assertion triggered during TLAB resizing after reconfiguration. Also it now handles a defect in the topology graph, in which a single leaf node doesn't have memory. Reviewed-by: jmasa --- hotspot/src/os/solaris/vm/os_solaris.cpp | 6 ++++ .../vm/gc_implementation/shared/gcUtil.hpp | 12 +++++++ .../shared/mutableNUMASpace.cpp | 32 +++++++++++++++++-- .../shared/mutableNUMASpace.hpp | 1 + 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 99005264c7b..6a8d173691d 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2658,6 +2658,12 @@ size_t os::numa_get_leaf_groups(int *ids, size_t size) { top += r; cur++; } + if (bottom == 0) { + // Handle a situation, when the OS reports no memory available. + // Assume UMA architecture. + ids[0] = 0; + return 1; + } return bottom; } diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp index 83fdf871de7..a6596e7e99f 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp @@ -58,6 +58,12 @@ class AdaptiveWeightedAverage : public CHeapObj { _average(0.0), _sample_count(0), _weight(weight), _last_sample(0.0) { } + void clear() { + _average = 0; + _sample_count = 0; + _last_sample = 0; + } + // Accessors float average() const { return _average; } unsigned weight() const { return _weight; } @@ -115,6 +121,12 @@ class AdaptivePaddedAverage : public AdaptiveWeightedAverage { float deviation() const { return _deviation; } unsigned padding() const { return _padding; } + void clear() { + AdaptiveWeightedAverage::clear(); + _padded_avg = 0; + _deviation = 0; + } + // Override void sample(float new_sample); }; diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp index 20ca6d3e31f..50cfe16c887 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @@ -141,7 +141,20 @@ size_t MutableNUMASpace::free_in_words() const { size_t MutableNUMASpace::tlab_capacity(Thread *thr) const { guarantee(thr != NULL, "No thread"); int lgrp_id = thr->lgrp_id(); - assert(lgrp_id != -1, "No lgrp_id set"); + if (lgrp_id == -1) { + // This case can occur after the topology of the system has + // changed. Thread can change their location, the new home + // group will be determined during the first allocation + // attempt. For now we can safely assume that all spaces + // have equal size because the whole space will be reinitialized. + if (lgrp_spaces()->length() > 0) { + return capacity_in_bytes() / lgrp_spaces()->length(); + } else { + assert(false, "There should be at least one locality group"); + return 0; + } + } + // That's the normal case, where we know the locality group of the thread. int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); if (i == -1) { return 0; @@ -150,9 +163,17 @@ size_t MutableNUMASpace::tlab_capacity(Thread *thr) const { } size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const { + // Please see the comments for tlab_capacity(). guarantee(thr != NULL, "No thread"); int lgrp_id = thr->lgrp_id(); - assert(lgrp_id != -1, "No lgrp_id set"); + if (lgrp_id == -1) { + if (lgrp_spaces()->length() > 0) { + return free_in_bytes() / lgrp_spaces()->length(); + } else { + assert(false, "There should be at least one locality group"); + return 0; + } + } int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); if (i == -1) { return 0; @@ -250,10 +271,15 @@ void MutableNUMASpace::free_region(MemRegion mr) { void MutableNUMASpace::update() { if (update_layout(false)) { // If the topology has changed, make all chunks zero-sized. + // And clear the alloc-rate statistics. + // In future we may want to handle this more gracefully in order + // to avoid the reallocation of the pages as much as possible. for (int i = 0; i < lgrp_spaces()->length(); i++) { - MutableSpace *s = lgrp_spaces()->at(i)->space(); + LGRPSpace *ls = lgrp_spaces()->at(i); + MutableSpace *s = ls->space(); s->set_end(s->bottom()); s->set_top(s->bottom()); + ls->clear_alloc_rate(); } // A NUMA space is never mangled initialize(region(), diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp index 54a01299beb..61ee6d2bcc1 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp @@ -112,6 +112,7 @@ class MutableNUMASpace : public MutableSpace { int lgrp_id() const { return _lgrp_id; } MutableSpace* space() const { return _space; } AdaptiveWeightedAverage* alloc_rate() const { return _alloc_rate; } + void clear_alloc_rate() { _alloc_rate->clear(); } SpaceStats* space_stats() { return &_space_stats; } void clear_space_stats() { _space_stats = SpaceStats(); } From e91ae90285a36fff3584aaf5b2017f8b762de829 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 18 Jul 2008 18:26:22 +0400 Subject: [PATCH 020/289] 6552812: Add HSL tab to JColorChooser Reviewed-by: peterz, avu --- .../plaf/basic/resources/basic.properties | 33 +- .../plaf/basic/resources/basic_de.properties | 33 +- .../plaf/basic/resources/basic_es.properties | 33 +- .../plaf/basic/resources/basic_fr.properties | 33 +- .../plaf/basic/resources/basic_it.properties | 33 +- .../plaf/basic/resources/basic_ja.properties | 33 +- .../plaf/basic/resources/basic_ko.properties | 33 +- .../plaf/basic/resources/basic_sv.properties | 33 +- .../basic/resources/basic_zh_CN.properties | 33 +- .../basic/resources/basic_zh_TW.properties | 33 +- .../ColorChooserComponentFactory.java | 19 +- .../swing/colorchooser/ColorChooserPanel.java | 182 ++++ .../javax/swing/colorchooser/ColorModel.java | 102 +++ .../swing/colorchooser/ColorModelCMYK.java | 94 ++ .../swing/colorchooser/ColorModelHSL.java | 188 ++++ .../swing/colorchooser/ColorModelHSV.java | 138 +++ .../javax/swing/colorchooser/ColorPanel.java | 210 +++++ .../colorchooser/DefaultHSBChooserPanel.java | 801 ------------------ .../colorchooser/DefaultRGBChooserPanel.java | 294 ------- .../swing/colorchooser/DiagramComponent.java | 160 ++++ .../swing/colorchooser/SlidingSpinner.java | 118 +++ .../swing/colorchooser/SyntheticImage.java | 166 ---- .../swing/colorchooser/ValueFormatter.java | 151 ++++ .../swing/plaf/basic/BasicColorChooserUI.java | 6 +- .../swing/JColorChooser/Test6524757.java | 166 ++-- .../swing/JColorChooser/Test6559154.java | 75 ++ 26 files changed, 1726 insertions(+), 1474 deletions(-) create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/ColorModel.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/ColorModelCMYK.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSL.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSV.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/ColorPanel.java delete mode 100644 jdk/src/share/classes/javax/swing/colorchooser/DefaultHSBChooserPanel.java delete mode 100644 jdk/src/share/classes/javax/swing/colorchooser/DefaultRGBChooserPanel.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/DiagramComponent.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/SlidingSpinner.java delete mode 100644 jdk/src/share/classes/javax/swing/colorchooser/SyntheticImage.java create mode 100644 jdk/src/share/classes/javax/swing/colorchooser/ValueFormatter.java create mode 100644 jdk/test/javax/swing/JColorChooser/Test6559154.java diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties index 6087def3607..4dac249bfa0 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=Sample Text Sample Text ColorChooser.swatchesNameText=Swatches ColorChooser.swatchesMnemonic=83 -ColorChooser.swatchesDisplayedMnemonicIndex=0 ColorChooser.swatchesRecentText=Recent: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=Red ColorChooser.rgbRedMnemonic=68 ColorChooser.rgbGreenText=Green ColorChooser.rgbGreenMnemonic=78 ColorChooser.rgbBlueText=Blue ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties index 93660548035..b3455977738 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_de.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=90 ColorChooser.sampleText=Beispieltext Beispieltext ColorChooser.swatchesNameText=Muster ColorChooser.swatchesMnemonic=77 -ColorChooser.swatchesDisplayedMnemonicIndex=0 ColorChooser.swatchesRecentText=Aktuell: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=Rot ColorChooser.rgbRedMnemonic=82 ColorChooser.rgbGreenText=Gr\u00fcn ColorChooser.rgbGreenMnemonic=78 ColorChooser.rgbBlueText=Blau ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties index b553b26f065..75877dd6560 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_es.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=Texto de ejemplo Texto de ejemplo ColorChooser.swatchesNameText=Muestras ColorChooser.swatchesMnemonic=77 -ColorChooser.swatchesDisplayedMnemonicIndex=0 ColorChooser.swatchesRecentText=Reciente: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=V -ColorChooser.hsbBlueText=A +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=Rojo ColorChooser.rgbRedMnemonic=74 ColorChooser.rgbGreenText=Verde ColorChooser.rgbGreenMnemonic=86 ColorChooser.rgbBlueText=Azul ColorChooser.rgbBlueMnemonic=76 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties index b18de0274a8..333a1a82fa1 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_fr.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=Echantillon de texte Echantillon de texte ColorChooser.swatchesNameText=Echantillons ColorChooser.swatchesMnemonic=69 -ColorChooser.swatchesDisplayedMnemonicIndex=0 ColorChooser.swatchesRecentText=Dernier : -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=V -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RVB ColorChooser.rgbMnemonic=86 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=Rouge ColorChooser.rgbRedMnemonic=71 ColorChooser.rgbGreenText=Vert ColorChooser.rgbGreenMnemonic=84 ColorChooser.rgbBlueText=Bleu ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties index 1c9f3790e6f..7bc69dbcf5e 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_it.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=Testo di prova Testo di prova ColorChooser.swatchesNameText=Colori campione ColorChooser.swatchesMnemonic=67 -ColorChooser.swatchesDisplayedMnemonicIndex=0 ColorChooser.swatchesRecentText=Recenti: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=Rosso ColorChooser.rgbRedMnemonic=79 ColorChooser.rgbGreenText=Verde ColorChooser.rgbGreenMnemonic=69 ColorChooser.rgbBlueText=Blu ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties index 1b5a131cabd..5603e9aa1bc 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=\u30b5\u30f3\u30d7\u30eb\u30c6\u30ad\u30b9\u30c8 \u30b5\u30f3\u30d7\u30eb\u30c6\u30ad\u30b9\u30c8 ColorChooser.swatchesNameText=\u30b5\u30f3\u30d7\u30eb(S) ColorChooser.swatchesMnemonic=83 -ColorChooser.swatchesDisplayedMnemonicIndex=5 ColorChooser.swatchesRecentText=\u6700\u65b0: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=\u8d64(D) ColorChooser.rgbRedMnemonic=68 ColorChooser.rgbGreenText=\u7dd1(N) ColorChooser.rgbGreenMnemonic=78 ColorChooser.rgbBlueText=\u9752(B) ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties index 9b873a43a61..f3866d01f31 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=\uc0d8\ud50c \ud14d\uc2a4\ud2b8 \uc0d8\ud50c \ud14d\uc2a4\ud2b8 ColorChooser.swatchesNameText=\uacac\ubcf8(S) ColorChooser.swatchesMnemonic=83 -ColorChooser.swatchesDisplayedMnemonicIndex=3 ColorChooser.swatchesRecentText=\ucd5c\uadfc \ubaa9\ub85d: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=\ube68\uac04\uc0c9(D) ColorChooser.rgbRedMnemonic=68 ColorChooser.rgbGreenText=\ub179\uc0c9(N) ColorChooser.rgbGreenMnemonic=78 ColorChooser.rgbBlueText=\ud30c\ub780\uc0c9(B) ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties index 2b8561b812e..17ef3b2be26 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_sv.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=84 ColorChooser.sampleText=Exempeltext Exempeltext ColorChooser.swatchesNameText=Prov ColorChooser.swatchesMnemonic=80 -ColorChooser.swatchesDisplayedMnemonicIndex=0 ColorChooser.swatchesRecentText=Tidigare: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=R\u00f6d ColorChooser.rgbRedMnemonic=82 ColorChooser.rgbGreenText=Gr\u00f6n ColorChooser.rgbGreenMnemonic=71 ColorChooser.rgbBlueText=Bl\u00e5 ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties index 7ef35330d86..b030c20a944 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=\u6837\u54c1\u6587\u672c \u6837\u54c1\u6587\u672c ColorChooser.swatchesNameText=\u6837\u54c1(S) ColorChooser.swatchesMnemonic=83 -ColorChooser.swatchesDisplayedMnemonicIndex=3 ColorChooser.swatchesRecentText=\u6700\u8fd1: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=\u7ea2 ColorChooser.rgbRedMnemonic=68 ColorChooser.rgbGreenText=\u7eff ColorChooser.rgbGreenMnemonic=78 ColorChooser.rgbBlueText=\u84dd ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties index dba0d76de28..47f99f0dcc9 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties @@ -101,30 +101,41 @@ ColorChooser.resetMnemonic=82 ColorChooser.sampleText=\u7bc4\u4f8b\u6587\u5b57 \u7bc4\u4f8b\u6587\u5b57 ColorChooser.swatchesNameText=\u8abf\u8272\u677f(S) ColorChooser.swatchesMnemonic=83 -ColorChooser.swatchesDisplayedMnemonicIndex=4 ColorChooser.swatchesRecentText=\u6700\u65b0\u9078\u64c7: -ColorChooser.hsbNameText=HSB # Each of the ColorChooser types can define a mnemonic, as a KeyEvent.VK_XXX # constant, and an index into the text to render the mnemonic as. The # mnemonic is xxxMnemonic and the index of the character to underline is # xxxDisplayedMnemonicIndex. -ColorChooser.hsbMnemonic=72 -ColorChooser.hsbDisplayedMnemonicIndex=0 -ColorChooser.hsbHueText=H -ColorChooser.hsbSaturationText=S -ColorChooser.hsbBrightnessText=B -ColorChooser.hsbRedText=R -ColorChooser.hsbGreenText=G -ColorChooser.hsbBlueText=B +ColorChooser.hsvNameText=HSV +ColorChooser.hsvMnemonic=72 +ColorChooser.hsvHueText=Hue +ColorChooser.hsvSaturationText=Saturation +ColorChooser.hsvValueText=Value +ColorChooser.hsvTransparencyText=Transparency +ColorChooser.hslNameText=HSL +ColorChooser.hslMnemonic=76 +ColorChooser.hslHueText=Hue +ColorChooser.hslSaturationText=Saturation +ColorChooser.hslLightnessText=Lightness +ColorChooser.hslTransparencyText=Transparency ColorChooser.rgbNameText=RGB ColorChooser.rgbMnemonic=71 -ColorChooser.rgbDisplayedMnemonicIndex=1 ColorChooser.rgbRedText=\u7d05\u8272(D) ColorChooser.rgbRedMnemonic=68 ColorChooser.rgbGreenText=\u7da0\u8272(N) ColorChooser.rgbGreenMnemonic=78 ColorChooser.rgbBlueText=\u85cd\u8272(B) ColorChooser.rgbBlueMnemonic=66 +ColorChooser.rgbAlphaText=Alpha +ColorChooser.rgbHexCodeText=Color Code +ColorChooser.rgbHexCodeMnemonic=67 +ColorChooser.cmykNameText=CMYK +ColorChooser.cmykMnemonic=77 +ColorChooser.cmykCyanText=Cyan +ColorChooser.cmykMagentaText=Magenta +ColorChooser.cmykYellowText=Yellow +ColorChooser.cmykBlackText=Black +ColorChooser.cmykAlphaText=Alpha ############ OPTION PANE STRINGS ############# # Mnemonic keys correspond to KeyEvent.VK_XXX constant diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java index b36c6524d8a..0ee01e6cb5a 100644 --- a/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserComponentFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 1998-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ package javax.swing.colorchooser; -import javax.swing.*; - - +import javax.swing.JComponent; /** * A class designed to produce preconfigured "accessory" objects to @@ -49,16 +47,17 @@ public class ColorChooserComponentFactory { private ColorChooserComponentFactory() { } // can't instantiate - public static AbstractColorChooserPanel[] getDefaultChooserPanels() { - AbstractColorChooserPanel[] choosers = { new DefaultSwatchChooserPanel(), - new DefaultHSBChooserPanel(), - new DefaultRGBChooserPanel() }; - return choosers; + return new AbstractColorChooserPanel[] { + new DefaultSwatchChooserPanel(), + new ColorChooserPanel(new ColorModelHSV()), + new ColorChooserPanel(new ColorModelHSL()), + new ColorChooserPanel(new ColorModel()), + new ColorChooserPanel(new ColorModelCMYK()), + }; } public static JComponent getPreviewPanel() { return new DefaultPreviewPanel(); } - } diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java new file mode 100644 index 00000000000..46b5351c695 --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java @@ -0,0 +1,182 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.SwingConstants; + +final class ColorChooserPanel extends AbstractColorChooserPanel implements PropertyChangeListener { + + private static final int MASK = 0xFF000000; + private final ColorModel model; + private final ColorPanel panel; + private final DiagramComponent slider; + private final DiagramComponent diagram; + private final JFormattedTextField text; + private final JLabel label; + + ColorChooserPanel(ColorModel model) { + this.model = model; + this.panel = new ColorPanel(this.model); + this.slider = new DiagramComponent(this.panel, false); + this.diagram = new DiagramComponent(this.panel, true); + this.text = new JFormattedTextField(); + this.label = new JLabel(null, null, SwingConstants.RIGHT); + ValueFormatter.init(6, true, this.text); + } + + @Override + public void updateChooser() { + Color color = getColorFromModel(); + this.panel.setColor(color); + this.text.setValue(Integer.valueOf(color.getRGB())); + this.slider.repaint(); + this.diagram.repaint(); + } + + @Override + protected void buildChooser() { + if (0 == getComponentCount()) { + setLayout(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 3; + gbc.gridwidth = 2; + gbc.weighty = 1.0; + gbc.anchor = GridBagConstraints.NORTH; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.insets.top = 10; + gbc.insets.right = 10; + add(this.panel, gbc); + + gbc.gridwidth = 1; + gbc.weightx = 1.0; + gbc.weighty = 0.0; + gbc.anchor = GridBagConstraints.CENTER; + gbc.insets.right = 5; + gbc.insets.bottom = 10; + add(this.label, gbc); + + gbc.gridx = 4; + gbc.weightx = 0.0; + gbc.insets.right = 10; + add(this.text, gbc); + + gbc.gridx = 2; + gbc.gridheight = 2; + gbc.anchor = GridBagConstraints.NORTH; + gbc.ipadx = this.text.getPreferredSize().height; + gbc.ipady = getPreferredSize().height; + add(this.slider, gbc); + + gbc.gridx = 1; + gbc.insets.left = 10; + gbc.ipadx = gbc.ipady; + add(this.diagram, gbc); + + this.label.setLabelFor(this.text); + this.text.addPropertyChangeListener("value", this); // NON-NLS: the property name + this.slider.setBorder(this.text.getBorder()); + this.diagram.setBorder(this.text.getBorder()); + + setInheritsPopupMenu(this, true); // CR:4966112 + } + String label = this.model.getText(this, "HexCode"); // NON-NLS: suffix + boolean visible = label != null; + this.text.setVisible(visible); + this.label.setVisible(visible); + if (visible) { + this.label.setText(label); + int mnemonic = this.model.getInteger(this, "HexCodeMnemonic"); // NON-NLS: suffix + if (mnemonic > 0) { + this.label.setDisplayedMnemonic(mnemonic); + mnemonic = this.model.getInteger(this, "HexCodeMnemonicIndex"); // NON-NLS: suffix + if (mnemonic >= 0) { + this.label.setDisplayedMnemonicIndex(mnemonic); + } + } + } + this.panel.buildPanel(); + } + + @Override + public String getDisplayName() { + return this.model.getText(this, "Name"); // NON-NLS: suffix + } + + @Override + public int getMnemonic() { + return this.model.getInteger(this, "Mnemonic"); // NON-NLS: suffix + } + + @Override + public int getDisplayedMnemonicIndex() { + return this.model.getInteger(this, "DisplayedMnemonicIndex"); // NON-NLS: suffix + } + + @Override + public Icon getSmallDisplayIcon() { + return null; + } + + @Override + public Icon getLargeDisplayIcon() { + return null; + } + + public void propertyChange(PropertyChangeEvent event) { + Object object = event.getNewValue(); + if (object instanceof Integer) { + int value = MASK & getColorFromModel().getRGB() | (Integer) object; + getColorSelectionModel().setSelectedColor(new Color(value, true)); + } + this.text.selectAll(); + } + + /** + * Allows to show context popup for all components recursively. + * + * @param component the root component of the tree + * @param value whether or not the popup menu is inherited + */ + private static void setInheritsPopupMenu(JComponent component, boolean value) { + component.setInheritsPopupMenu(value); + for (Object object : component.getComponents()) { + if (object instanceof JComponent) { + setInheritsPopupMenu((JComponent) object, value); + } + } + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorModel.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorModel.java new file mode 100644 index 00000000000..955ed162663 --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorModel.java @@ -0,0 +1,102 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +import java.awt.Component; +import javax.swing.UIManager; + +class ColorModel { + + private final String prefix; + private final String[] labels; + + ColorModel(String name, String... labels) { + this.prefix = "ColorChooser." + name; // NON-NLS: default prefix + this.labels = labels; + } + + ColorModel() { + this("rgb", "Red", "Green", "Blue", "Alpha"); // NON-NLS: components + } + + void setColor(int color, float[] model) { + model[0] = normalize(color >> 16); + model[1] = normalize(color >> 8); + model[2] = normalize(color); + model[3] = normalize(color >> 24); + } + + int getColor(float[] model) { + return to8bit(model[2]) | (to8bit(model[1]) << 8) | (to8bit(model[0]) << 16) | (to8bit(model[3]) << 24); + } + + int getCount() { + return this.labels.length; + } + + int getMinimum(int index) { + return 0; + } + + int getMaximum(int index) { + return 255; + } + + float getDefault(int index) { + return 0.0f; + } + + final String getLabel(Component component, int index) { + return getText(component, this.labels[index]); + } + + private static float normalize(int value) { + return (float) (value & 0xFF) / 255.0f; + } + + private static int to8bit(float value) { + return (int) (255.0f * value); + } + + final String getText(Component component, String suffix) { + return UIManager.getString(this.prefix + suffix + "Text", component.getLocale()); // NON-NLS: default postfix + } + + final int getInteger(Component component, String suffix) { + Object value = UIManager.get(this.prefix + suffix, component.getLocale()); + if (value instanceof Integer) { + return (Integer) value; + } + if (value instanceof String) { + try { + return Integer.parseInt((String) value); + } + catch (NumberFormatException exception) { + } + } + return -1; + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorModelCMYK.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorModelCMYK.java new file mode 100644 index 00000000000..77a7ca55594 --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorModelCMYK.java @@ -0,0 +1,94 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +final class ColorModelCMYK extends ColorModel { + + ColorModelCMYK() { + super("cmyk", "Cyan", "Magenta", "Yellow", "Black", "Alpha"); // NON-NLS: components + } + + @Override + void setColor(int color, float[] space) { + super.setColor(color, space); + space[4] = space[3]; + RGBtoCMYK(space, space); + } + + @Override + int getColor(float[] space) { + CMYKtoRGB(space, space); + space[3] = space[4]; + return super.getColor(space); + } + + /** + * Converts CMYK components of a color to a set of RGB components. + * + * @param cmyk a float array with length equal to + * the number of CMYK components + * @param rgb a float array with length of at least 3 + * that contains RGB components of a color + * @return a float array that contains RGB components + */ + private static float[] CMYKtoRGB(float[] cmyk, float[] rgb) { + if (rgb == null) { + rgb = new float[3]; + } + rgb[0] = 1.0f + cmyk[0] * cmyk[3] - cmyk[3] - cmyk[0]; + rgb[1] = 1.0f + cmyk[1] * cmyk[3] - cmyk[3] - cmyk[1]; + rgb[2] = 1.0f + cmyk[2] * cmyk[3] - cmyk[3] - cmyk[2]; + return rgb; + } + + /** + * Converts RGB components of a color to a set of CMYK components. + * + * @param rgb a float array with length of at least 3 + * that contains RGB components of a color + * @param cmyk a float array with length equal to + * the number of CMYK components + * @return a float array that contains CMYK components + */ + private static float[] RGBtoCMYK(float[] rgb, float[] cmyk) { + if (cmyk == null) { + cmyk = new float[4]; + } + float max = ColorModelHSL.max(rgb[0], rgb[1], rgb[2]); + if (max > 0.0f) { + cmyk[0] = 1.0f - rgb[0] / max; + cmyk[1] = 1.0f - rgb[1] / max; + cmyk[2] = 1.0f - rgb[2] / max; + } + else { + cmyk[0] = 0.0f; + cmyk[1] = 0.0f; + cmyk[2] = 0.0f; + } + cmyk[3] = 1.0f - max; + return cmyk; + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSL.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSL.java new file mode 100644 index 00000000000..85b0c8e5da4 --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSL.java @@ -0,0 +1,188 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +final class ColorModelHSL extends ColorModel { + + ColorModelHSL() { + super("hsl", "Hue", "Saturation", "Lightness", "Transparency"); // NON-NLS: components + } + + @Override + void setColor(int color, float[] space) { + super.setColor(color, space); + RGBtoHSL(space, space); + space[3] = 1.0f - space[3]; + } + + @Override + int getColor(float[] space) { + space[3] = 1.0f - space[3]; + HSLtoRGB(space, space); + return super.getColor(space); + } + + @Override + int getMaximum(int index) { + return (index == 0) ? 360 : 100; + } + + @Override + float getDefault(int index) { + return (index == 0) ? -1.0f : (index == 2) ? 0.5f : 1.0f; + } + + /** + * Converts HSL components of a color to a set of RGB components. + * + * @param hsl a float array with length equal to + * the number of HSL components + * @param rgb a float array with length of at least 3 + * that contains RGB components of a color + * @return a float array that contains RGB components + */ + private static float[] HSLtoRGB(float[] hsl, float[] rgb) { + if (rgb == null) { + rgb = new float[3]; + } + float hue = hsl[0]; + float saturation = hsl[1]; + float lightness = hsl[2]; + + if (saturation > 0.0f) { + hue = (hue < 1.0f) ? hue * 6.0f : 0.0f; + float q = lightness + saturation * ((lightness > 0.5f) ? 1.0f - lightness : lightness); + float p = 2.0f * lightness - q; + rgb[0]= normalize(q, p, (hue < 4.0f) ? (hue + 2.0f) : (hue - 4.0f)); + rgb[1]= normalize(q, p, hue); + rgb[2]= normalize(q, p, (hue < 2.0f) ? (hue + 4.0f) : (hue - 2.0f)); + } + else { + rgb[0] = lightness; + rgb[1] = lightness; + rgb[2] = lightness; + } + return rgb; + } + + /** + * Converts RGB components of a color to a set of HSL components. + * + * @param rgb a float array with length of at least 3 + * that contains RGB components of a color + * @param hsl a float array with length equal to + * the number of HSL components + * @return a float array that contains HSL components + */ + private static float[] RGBtoHSL(float[] rgb, float[] hsl) { + if (hsl == null) { + hsl = new float[3]; + } + float max = max(rgb[0], rgb[1], rgb[2]); + float min = min(rgb[0], rgb[1], rgb[2]); + + float summa = max + min; + float saturation = max - min; + if (saturation > 0.0f) { + saturation /= (summa > 1.0f) + ? 2.0f - summa + : summa; + } + hsl[0] = getHue(rgb[0], rgb[1], rgb[2], max, min); + hsl[1] = saturation; + hsl[2] = summa / 2.0f; + return hsl; + } + + /** + * Returns the smaller of three color components. + * + * @param red the red component of the color + * @param green the green component of the color + * @param blue the blue component of the color + * @return the smaller of {@code red}, {@code green} and {@code blue} + */ + static float min(float red, float green, float blue) { + float min = (red < green) ? red : green; + return (min < blue) ? min : blue; + } + + /** + * Returns the larger of three color components. + * + * @param red the red component of the color + * @param green the green component of the color + * @param blue the blue component of the color + * @return the larger of {@code red}, {@code green} and {@code blue} + */ + static float max(float red, float green, float blue) { + float max = (red > green) ? red : green; + return (max > blue) ? max : blue; + } + + /** + * Calculates the hue component for HSL and HSV color spaces. + * + * @param red the red component of the color + * @param green the green component of the color + * @param blue the blue component of the color + * @param max the larger of {@code red}, {@code green} and {@code blue} + * @param min the smaller of {@code red}, {@code green} and {@code blue} + * @return the hue component + */ + static float getHue(float red, float green, float blue, float max, float min) { + float hue = max - min; + if (hue > 0.0f) { + if (max == red) { + hue = (green - blue) / hue; + if (hue < 0.0f) { + hue += 6.0f; + } + } + else if (max == green) { + hue = 2.0f + (blue - red) / hue; + } + else /*max == blue*/ { + hue = 4.0f + (red - green) / hue; + } + hue /= 6.0f; + } + return hue; + } + + private static float normalize(float q, float p, float color) { + if (color < 1.0f) { + return p + (q - p) * color; + } + if (color < 3.0f) { + return q; + } + if (color < 4.0f) { + return p + (q - p) * (4.0f - color); + } + return p; + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSV.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSV.java new file mode 100644 index 00000000000..e33eef77dfe --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorModelHSV.java @@ -0,0 +1,138 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +final class ColorModelHSV extends ColorModel { + + ColorModelHSV() { + super("hsv", "Hue", "Saturation", "Value", "Transparency"); // NON-NLS: components + } + + @Override + void setColor(int color, float[] space) { + super.setColor(color, space); + RGBtoHSV(space, space); + space[3] = 1.0f - space[3]; + } + + @Override + int getColor(float[] space) { + space[3] = 1.0f - space[3]; + HSVtoRGB(space, space); + return super.getColor(space); + } + + @Override + int getMaximum(int index) { + return (index == 0) ? 360 : 100; + } + + @Override + float getDefault(int index) { + return (index == 0) ? -1.0f : 1.0f; + } + + /** + * Converts HSV components of a color to a set of RGB components. + * + * @param hsv a float array with length equal to + * the number of HSV components + * @param rgb a float array with length of at least 3 + * that contains RGB components of a color + * @return a float array that contains RGB components + */ + private static float[] HSVtoRGB(float[] hsv, float[] rgb) { + if (rgb == null) { + rgb = new float[3]; + } + float hue = hsv[0]; + float saturation = hsv[1]; + float value = hsv[2]; + + rgb[0] = value; + rgb[1] = value; + rgb[2] = value; + + if (saturation > 0.0f) { + hue = (hue < 1.0f) ? hue * 6.0f : 0.0f; + int integer = (int) hue; + float f = hue - (float) integer; + switch (integer) { + case 0: + rgb[1] *= 1.0f - saturation * (1.0f - f); + rgb[2] *= 1.0f - saturation; + break; + case 1: + rgb[0] *= 1.0f - saturation * f; + rgb[2] *= 1.0f - saturation; + break; + case 2: + rgb[0] *= 1.0f - saturation; + rgb[2] *= 1.0f - saturation * (1.0f - f); + break; + case 3: + rgb[0] *= 1.0f - saturation; + rgb[1] *= 1.0f - saturation * f; + break; + case 4: + rgb[0] *= 1.0f - saturation * (1.0f - f); + rgb[1] *= 1.0f - saturation; + break; + case 5: + rgb[1] *= 1.0f - saturation; + rgb[2] *= 1.0f - saturation * f; + break; + } + } + return rgb; + } + + /** + * Converts RGB components of a color to a set of HSV components. + * + * @param rgb a float array with length of at least 3 + * that contains RGB components of a color + * @param hsv a float array with length equal to + * the number of HSV components + * @return a float array that contains HSV components + */ + private static float[] RGBtoHSV(float[] rgb, float[] hsv) { + if (hsv == null) { + hsv = new float[3]; + } + float max = ColorModelHSL.max(rgb[0], rgb[1], rgb[2]); + float min = ColorModelHSL.min(rgb[0], rgb[1], rgb[2]); + + float saturation = max - min; + if (saturation > 0.0f) { + saturation /= max; + } + hsv[0] = ColorModelHSL.getHue(rgb[0], rgb[1], rgb[2], max, min); + hsv[1] = saturation; + hsv[2] = max; + return hsv; + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorPanel.java new file mode 100644 index 00000000000..6e9329dbefb --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorPanel.java @@ -0,0 +1,210 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +import java.awt.Color; +import java.awt.ContainerOrderFocusTraversalPolicy; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.ButtonGroup; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.border.EmptyBorder; + +final class ColorPanel extends JPanel implements ActionListener { + + private final SlidingSpinner[] spinners = new SlidingSpinner[5]; + private final float[] values = new float[this.spinners.length]; + + private final ColorModel model; + private Color color; + private int x = 1; + private int y = 2; + private int z; + + ColorPanel(ColorModel model) { + super(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.HORIZONTAL; + + gbc.gridx = 1; + ButtonGroup group = new ButtonGroup(); + EmptyBorder border = null; + for (int i = 0; i < this.spinners.length; i++) { + if (i < 3) { + JRadioButton button = new JRadioButton(); + if (i == 0) { + Insets insets = button.getInsets(); + insets.left = button.getPreferredSize().width; + border = new EmptyBorder(insets); + button.setSelected(true); + gbc.insets.top = 5; + } + add(button, gbc); + group.add(button); + button.setActionCommand(Integer.toString(i)); + button.addActionListener(this); + this.spinners[i] = new SlidingSpinner(this, button); + } + else { + JLabel label = new JLabel(); + add(label, gbc); + label.setBorder(border); + label.setFocusable(false); + this.spinners[i] = new SlidingSpinner(this, label); + } + } + gbc.gridx = 2; + gbc.weightx = 1.0; + gbc.insets.top = 0; + gbc.insets.left = 5; + for (SlidingSpinner spinner : this.spinners) { + add(spinner.getSlider(), gbc); + gbc.insets.top = 5; + } + gbc.gridx = 3; + gbc.weightx = 0.0; + gbc.insets.top = 0; + for (SlidingSpinner spinner : this.spinners) { + add(spinner.getSpinner(), gbc); + gbc.insets.top = 5; + } + setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy()); + setFocusTraversalPolicyProvider(true); + setFocusable(false); + + this.model = model; + } + + public void actionPerformed(ActionEvent event) { + try { + this.z = Integer.parseInt(event.getActionCommand()); + this.y = (this.z != 2) ? 2 : 1; + this.x = (this.z != 0) ? 0 : 1; + getParent().repaint(); + } + catch (NumberFormatException exception) { + } + } + + void buildPanel() { + int count = this.model.getCount(); + this.spinners[4].setVisible(count > 4); + for (int i = 0; i < count; i++) { + Object object = this.spinners[i].getLabel(); + if (object instanceof JRadioButton) { + JRadioButton button = (JRadioButton) object; + button.setText(this.model.getLabel(this, i)); + } + else if (object instanceof JLabel) { + JLabel label = (JLabel) object; + label.setText(this.model.getLabel(this, i)); + } + this.spinners[i].setRange(this.model.getMinimum(i), this.model.getMaximum(i)); + this.spinners[i].setValue(this.values[i]); + } + } + + void colorChanged() { + this.color = new Color(getColor(0), true); + Object parent = getParent(); + if (parent instanceof ColorChooserPanel) { + ColorChooserPanel chooser = (ColorChooserPanel) parent; + chooser.getColorSelectionModel().setSelectedColor(this.color); + chooser.repaint(); + } + } + + float getValueX() { + return this.spinners[this.x].getValue(); + } + + float getValueY() { + return 1.0f - this.spinners[this.y].getValue(); + } + + float getValueZ() { + return 1.0f - this.spinners[this.z].getValue(); + } + + void setValue(float z) { + this.spinners[this.z].setValue(1.0f - z); + colorChanged(); + } + + void setValue(float x, float y) { + this.spinners[this.x].setValue(x); + this.spinners[this.y].setValue(1.0f - y); + colorChanged(); + } + + int getColor(float z) { + setDefaultValue(this.x); + setDefaultValue(this.y); + this.values[this.z] = 1.0f - z; + return getColor(3); + } + + int getColor(float x, float y) { + this.values[this.x] = x; + this.values[this.y] = 1.0f - y; + setValue(this.z); + return getColor(3); + } + + void setColor(Color color) { + if (!color.equals(this.color)) { + this.color = color; + this.model.setColor(color.getRGB(), this.values); + for (int i = 0; i < this.model.getCount(); i++) { + this.spinners[i].setValue(this.values[i]); + } + } + } + + private int getColor(int index) { + while (index < this.model.getCount()) { + setValue(index++); + } + return this.model.getColor(this.values); + } + + private void setValue(int index) { + this.values[index] = this.spinners[index].getValue(); + } + + private void setDefaultValue(int index) { + float value = this.model.getDefault(index); + this.values[index] = (value < 0.0f) + ? this.spinners[index].getValue() + : value; + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/DefaultHSBChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/DefaultHSBChooserPanel.java deleted file mode 100644 index 89759e247a4..00000000000 --- a/jdk/src/share/classes/javax/swing/colorchooser/DefaultHSBChooserPanel.java +++ /dev/null @@ -1,801 +0,0 @@ -/* - * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package javax.swing.colorchooser; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import javax.swing.event.*; -import javax.swing.border.*; -import java.awt.image.*; -import java.util.Locale; - -/** - * Implements the default HSB Color chooser - * - * @author Tom Santos - * @author Steve Wilson - * @author Mark Davidson - * @author Shannon Hickey - */ -class DefaultHSBChooserPanel extends AbstractColorChooserPanel implements ChangeListener, HierarchyListener { - - private transient HSBImage palette; - private transient HSBImage sliderPalette; - - private transient Image paletteImage; - private transient Image sliderPaletteImage; - - private JSlider slider; - private JSpinner hField; - private JSpinner sField; - private JSpinner bField; - - private JTextField redField; - private JTextField greenField; - private JTextField blueField; - - private boolean isAdjusting = false; // Flag which indicates that values are set internally - private Point paletteSelection = new Point(); - private JLabel paletteLabel; - private JLabel sliderPaletteLabel; - - private JRadioButton hRadio; - private JRadioButton sRadio; - private JRadioButton bRadio; - - private static final int PALETTE_DIMENSION = 200; - private static final int MAX_HUE_VALUE = 359; - private static final int MAX_SATURATION_VALUE = 100; - private static final int MAX_BRIGHTNESS_VALUE = 100; - - private int currentMode = HUE_MODE; - - private static final int HUE_MODE = 0; - private static final int SATURATION_MODE = 1; - private static final int BRIGHTNESS_MODE = 2; - - public DefaultHSBChooserPanel() { - } - - private void addPaletteListeners() { - paletteLabel.addMouseListener(new MouseAdapter() { - public void mousePressed(MouseEvent e ) { - float[] hsb = new float[3]; - palette.getHSBForLocation( e.getX(), e.getY(), hsb ); - updateHSB( hsb[0], hsb[1], hsb[2] ); - } - }); - - paletteLabel.addMouseMotionListener(new MouseMotionAdapter() { - public void mouseDragged( MouseEvent e ){ - int labelWidth = paletteLabel.getWidth(); - - int labelHeight = paletteLabel.getHeight(); - int x = e.getX(); - int y = e.getY(); - - if ( x >= labelWidth ) { - x = labelWidth - 1; - } - - if ( y >= labelHeight ) { - y = labelHeight - 1; - } - - if ( x < 0 ) { - x = 0; - } - - if ( y < 0 ) { - y = 0; - } - - float[] hsb = new float[3]; - palette.getHSBForLocation( x, y, hsb ); - updateHSB( hsb[0], hsb[1], hsb[2] ); - } - }); - } - - private void updatePalette( float h, float s, float b ) { - int x = 0; - int y = 0; - - switch ( currentMode ) { - case HUE_MODE: - if ( h != palette.getHue() ) { - palette.setHue( h ); - palette.nextFrame(); - } - x = PALETTE_DIMENSION - (int)(s * PALETTE_DIMENSION); - y = PALETTE_DIMENSION - (int)(b * PALETTE_DIMENSION); - break; - case SATURATION_MODE: - if ( s != palette.getSaturation() ) { - palette.setSaturation( s ); - palette.nextFrame(); - } - x = (int)(h * PALETTE_DIMENSION); - y = PALETTE_DIMENSION - (int)(b * PALETTE_DIMENSION); - break; - case BRIGHTNESS_MODE: - if ( b != palette.getBrightness() ) { - palette.setBrightness( b ); - palette.nextFrame(); - } - x = (int)(h * PALETTE_DIMENSION); - y = PALETTE_DIMENSION - (int)(s * PALETTE_DIMENSION); - break; - } - - paletteSelection.setLocation( x, y ); - paletteLabel.repaint(); - } - - private void updateSlider( float h, float s, float b ) { - // Update the slider palette if necessary. - // When the slider is the hue slider or the hue hasn't changed, - // the hue of the palette will not need to be updated. - if (currentMode != HUE_MODE && h != sliderPalette.getHue() ) { - sliderPalette.setHue( h ); - sliderPalette.nextFrame(); - } - - float value = 0f; - - switch ( currentMode ) { - case HUE_MODE: - value = h; - break; - case SATURATION_MODE: - value = s; - break; - case BRIGHTNESS_MODE: - value = b; - break; - } - - slider.setValue( Math.round(value * (slider.getMaximum())) ); - } - - private void updateHSBTextFields( float hue, float saturation, float brightness ) { - int h = Math.round(hue * 359); - int s = Math.round(saturation * 100); - int b = Math.round(brightness * 100); - - if (((Integer)hField.getValue()).intValue() != h) { - hField.setValue(new Integer(h)); - } - if (((Integer)sField.getValue()).intValue() != s) { - sField.setValue(new Integer(s)); - } - if (((Integer)bField.getValue()).intValue() != b) { - bField.setValue(new Integer(b)); - } - } - - /** - * Updates the values of the RGB fields to reflect the new color change - */ - private void updateRGBTextFields( Color color ) { - redField.setText(String.valueOf(color.getRed())); - greenField.setText(String.valueOf(color.getGreen())); - blueField.setText(String.valueOf(color.getBlue())); - } - - /** - * Main internal method of updating the ui controls and the color model. - */ - private void updateHSB( float h, float s, float b ) { - if ( !isAdjusting ) { - isAdjusting = true; - - updatePalette( h, s, b ); - updateSlider( h, s, b ); - updateHSBTextFields( h, s, b ); - - Color color = Color.getHSBColor(h, s, b); - updateRGBTextFields( color ); - - getColorSelectionModel().setSelectedColor( color ); - - isAdjusting = false; - } - } - - /** - * Invoked automatically when the model's state changes. - * It is also called by installChooserPanel to allow - * you to set up the initial state of your chooser. - * Override this method to update your ChooserPanel. - */ - public void updateChooser() { - if ( !isAdjusting ) { - float[] hsb = getHSBColorFromModel(); - updateHSB( hsb[0], hsb[1], hsb[2] ); - } - } - - public void installChooserPanel(JColorChooser enclosingChooser) { - super.installChooserPanel(enclosingChooser); - setInheritsPopupMenu(true); - addHierarchyListener(this); - } - - /** - * Invoked when the panel is removed from the chooser. - */ - public void uninstallChooserPanel(JColorChooser enclosingChooser) { - super.uninstallChooserPanel(enclosingChooser); - cleanupPalettesIfNecessary(); - removeAll(); - removeHierarchyListener(this); - } - - /** - * Returns an float array containing the HSB values of the selected color from - * the ColorSelectionModel - */ - private float[] getHSBColorFromModel() { - Color color = getColorFromModel(); - float[] hsb = new float[3]; - Color.RGBtoHSB( color.getRed(), color.getGreen(), color.getBlue(), hsb ); - - return hsb; - } - - /** - * Builds a new chooser panel. - */ - protected void buildChooser() { - setLayout(new BorderLayout()); - JComponent spp = buildSliderPalettePanel(); - spp.setInheritsPopupMenu(true); - add(spp, BorderLayout.BEFORE_LINE_BEGINS); - - JPanel controlHolder = new JPanel(new SmartGridLayout(1,3)); - JComponent hsbControls = buildHSBControls(); - hsbControls.setInheritsPopupMenu(true); - controlHolder.add(hsbControls); - - controlHolder.add(new JLabel(" ")); // spacer - - JComponent rgbControls = buildRGBControls(); - rgbControls.setInheritsPopupMenu(true); - controlHolder.add(rgbControls); - controlHolder.setInheritsPopupMenu(true); - - controlHolder.setBorder(new EmptyBorder( 10, 5, 10, 5)); - add( controlHolder, BorderLayout.CENTER); - } - - /** - * Creates the panel with the uneditable RGB field - */ - private JComponent buildRGBControls() { - JPanel panel = new JPanel(new SmartGridLayout(2,3)); - panel.setInheritsPopupMenu(true); - - Color color = getColorFromModel(); - redField = new JTextField( String.valueOf(color.getRed()), 3 ); - redField.setEditable(false); - redField.setHorizontalAlignment( JTextField.RIGHT ); - redField.setInheritsPopupMenu(true); - - greenField = new JTextField(String.valueOf(color.getGreen()), 3 ); - greenField.setEditable(false); - greenField.setHorizontalAlignment( JTextField.RIGHT ); - greenField.setInheritsPopupMenu(true); - - blueField = new JTextField( String.valueOf(color.getBlue()), 3 ); - blueField.setEditable(false); - blueField.setHorizontalAlignment( JTextField.RIGHT ); - blueField.setInheritsPopupMenu(true); - - Locale locale = getLocale(); - String redString = UIManager.getString("ColorChooser.hsbRedText", locale); - String greenString = UIManager.getString("ColorChooser.hsbGreenText", locale); - String blueString = UIManager.getString("ColorChooser.hsbBlueText", locale); - - panel.add( new JLabel(redString) ); - panel.add( redField ); - panel.add( new JLabel(greenString) ); - panel.add( greenField ); - panel.add( new JLabel(blueString) ); - panel.add( blueField ); - - return panel; - } - - /** - * Creates the panel with the editable HSB fields and the radio buttons. - */ - private JComponent buildHSBControls() { - - Locale locale = getLocale(); - String hueString = UIManager.getString("ColorChooser.hsbHueText", locale); - String saturationString = UIManager.getString("ColorChooser.hsbSaturationText", locale); - String brightnessString = UIManager.getString("ColorChooser.hsbBrightnessText", locale); - - RadioButtonHandler handler = new RadioButtonHandler(); - - hRadio = new JRadioButton(hueString); - hRadio.addActionListener(handler); - hRadio.setSelected(true); - hRadio.setInheritsPopupMenu(true); - - sRadio = new JRadioButton(saturationString); - sRadio.addActionListener(handler); - sRadio.setInheritsPopupMenu(true); - - bRadio = new JRadioButton(brightnessString); - bRadio.addActionListener(handler); - bRadio.setInheritsPopupMenu(true); - - ButtonGroup group = new ButtonGroup(); - group.add(hRadio); - group.add(sRadio); - group.add(bRadio); - - float[] hsb = getHSBColorFromModel(); - - hField = new JSpinner(new SpinnerNumberModel((int)(hsb[0] * 359), 0, 359, 1)); - sField = new JSpinner(new SpinnerNumberModel((int)(hsb[1] * 100), 0, 100, 1)); - bField = new JSpinner(new SpinnerNumberModel((int)(hsb[2] * 100), 0, 100, 1)); - - hField.addChangeListener(this); - sField.addChangeListener(this); - bField.addChangeListener(this); - - hField.setInheritsPopupMenu(true); - sField.setInheritsPopupMenu(true); - bField.setInheritsPopupMenu(true); - - JPanel panel = new JPanel( new SmartGridLayout(2, 3) ); - - panel.add(hRadio); - panel.add(hField); - panel.add(sRadio); - panel.add(sField); - panel.add(bRadio); - panel.add(bField); - panel.setInheritsPopupMenu(true); - - return panel; - } - - /** - * Handler for the radio button classes. - */ - private class RadioButtonHandler implements ActionListener { - public void actionPerformed(ActionEvent evt) { - Object obj = evt.getSource(); - - if (obj instanceof JRadioButton) { - JRadioButton button = (JRadioButton)obj; - if (button == hRadio) { - setMode(HUE_MODE); - } else if (button == sRadio) { - setMode(SATURATION_MODE); - } else if (button == bRadio) { - setMode(BRIGHTNESS_MODE); - } - } - } - } - - private void setMode(int mode) { - if (currentMode == mode) { - return; - } - - isAdjusting = true; // Ensure no events propagate from changing slider value. - currentMode = mode; - - float[] hsb = getHSBColorFromModel(); - - switch (currentMode) { - case HUE_MODE: - slider.setInverted(true); - slider.setMaximum(MAX_HUE_VALUE); - palette.setValues(HSBImage.HSQUARE, hsb[0], 1.0f, 1.0f); - sliderPalette.setValues(HSBImage.HSLIDER, 0f, 1.0f, 1.0f); - break; - case SATURATION_MODE: - slider.setInverted(false); - slider.setMaximum(MAX_SATURATION_VALUE); - palette.setValues(HSBImage.SSQUARE, hsb[0], hsb[1], 1.0f); - sliderPalette.setValues(HSBImage.SSLIDER, hsb[0], 1.0f, 1.0f); - break; - case BRIGHTNESS_MODE: - slider.setInverted(false); - slider.setMaximum(MAX_BRIGHTNESS_VALUE); - palette.setValues(HSBImage.BSQUARE, hsb[0], 1.0f, hsb[2]); - sliderPalette.setValues(HSBImage.BSLIDER, hsb[0], 1.0f, 1.0f); - break; - } - - isAdjusting = false; - - palette.nextFrame(); - sliderPalette.nextFrame(); - - updateChooser(); - } - - protected JComponent buildSliderPalettePanel() { - - // This slider has to have a minimum of 0. A lot of math in this file is simplified due to this. - slider = new JSlider(JSlider.VERTICAL, 0, MAX_HUE_VALUE, 0); - slider.setInverted(true); - slider.setPaintTrack(false); - slider.setPreferredSize(new Dimension(slider.getPreferredSize().width, PALETTE_DIMENSION + 15)); - slider.addChangeListener(this); - slider.setInheritsPopupMenu(true); - // We're not painting ticks, but need to ask UI classes to - // paint arrow shape anyway, if possible. - slider.putClientProperty("Slider.paintThumbArrowShape", Boolean.TRUE); - paletteLabel = createPaletteLabel(); - addPaletteListeners(); - sliderPaletteLabel = new JLabel(); - - JPanel panel = new JPanel(); - panel.add( paletteLabel ); - panel.add( slider ); - panel.add( sliderPaletteLabel ); - - initializePalettesIfNecessary(); - - return panel; - } - - private void initializePalettesIfNecessary() { - if (palette != null) { - return; - } - - float[] hsb = getHSBColorFromModel(); - - switch(currentMode){ - case HUE_MODE: - palette = new HSBImage(HSBImage.HSQUARE, PALETTE_DIMENSION, PALETTE_DIMENSION, hsb[0], 1.0f, 1.0f); - sliderPalette = new HSBImage(HSBImage.HSLIDER, 16, PALETTE_DIMENSION, 0f, 1.0f, 1.0f); - break; - case SATURATION_MODE: - palette = new HSBImage(HSBImage.SSQUARE, PALETTE_DIMENSION, PALETTE_DIMENSION, 1.0f, hsb[1], 1.0f); - sliderPalette = new HSBImage(HSBImage.SSLIDER, 16, PALETTE_DIMENSION, 1.0f, 0f, 1.0f); - break; - case BRIGHTNESS_MODE: - palette = new HSBImage(HSBImage.BSQUARE, PALETTE_DIMENSION, PALETTE_DIMENSION, 1.0f, 1.0f, hsb[2]); - sliderPalette = new HSBImage(HSBImage.BSLIDER, 16, PALETTE_DIMENSION, 1.0f, 1.0f, 0f); - break; - } - paletteImage = Toolkit.getDefaultToolkit().createImage(palette); - sliderPaletteImage = Toolkit.getDefaultToolkit().createImage(sliderPalette); - - paletteLabel.setIcon(new ImageIcon(paletteImage)); - sliderPaletteLabel.setIcon(new ImageIcon(sliderPaletteImage)); - } - - private void cleanupPalettesIfNecessary() { - if (palette == null) { - return; - } - - palette.aborted = true; - sliderPalette.aborted = true; - - palette.nextFrame(); - sliderPalette.nextFrame(); - - palette = null; - sliderPalette = null; - - paletteImage = null; - sliderPaletteImage = null; - - paletteLabel.setIcon(null); - sliderPaletteLabel.setIcon(null); - } - - protected JLabel createPaletteLabel() { - return new JLabel() { - protected void paintComponent( Graphics g ) { - super.paintComponent( g ); - g.setColor( Color.white ); - g.drawOval( paletteSelection.x - 4, paletteSelection.y - 4, 8, 8 ); - } - }; - } - - public String getDisplayName() { - return UIManager.getString("ColorChooser.hsbNameText", getLocale()); - } - - /** - * Provides a hint to the look and feel as to the - * KeyEvent.VK constant that can be used as a mnemonic to - * access the panel. A return value <= 0 indicates there is no mnemonic. - *

- * The return value here is a hint, it is ultimately up to the look - * and feel to honor the return value in some meaningful way. - *

- * This implementation looks up the value from the default - * ColorChooser.hsbMnemonic, or if it - * isn't available (or not an Integer) returns -1. - * The lookup for the default is done through the UIManager: - * UIManager.get("ColorChooser.rgbMnemonic");. - * - * @return KeyEvent.VK constant identifying the mnemonic; <= 0 for no - * mnemonic - * @see #getDisplayedMnemonicIndex - * @since 1.4 - */ - public int getMnemonic() { - return getInt("ColorChooser.hsbMnemonic", -1); - } - - /** - * Provides a hint to the look and feel as to the index of the character in - * getDisplayName that should be visually identified as the - * mnemonic. The look and feel should only use this if - * getMnemonic returns a value > 0. - *

- * The return value here is a hint, it is ultimately up to the look - * and feel to honor the return value in some meaningful way. For example, - * a look and feel may wish to render each - * AbstractColorChooserPanel in a JTabbedPane, - * and further use this return value to underline a character in - * the getDisplayName. - *

- * This implementation looks up the value from the default - * ColorChooser.rgbDisplayedMnemonicIndex, or if it - * isn't available (or not an Integer) returns -1. - * The lookup for the default is done through the UIManager: - * UIManager.get("ColorChooser.hsbDisplayedMnemonicIndex");. - * - * @return Character index to render mnemonic for; -1 to provide no - * visual identifier for this panel. - * @see #getMnemonic - * @since 1.4 - */ - public int getDisplayedMnemonicIndex() { - return getInt("ColorChooser.hsbDisplayedMnemonicIndex", -1); - } - - public Icon getSmallDisplayIcon() { - return null; - } - - public Icon getLargeDisplayIcon() { - return null; - } - - /** - * Class for the slider and palette images. - */ - class HSBImage extends SyntheticImage { - protected float h = .0f; - protected float s = .0f; - protected float b = .0f; - protected float[] hsb = new float[3]; - - protected boolean isDirty = true; - protected int cachedY; - protected int cachedColor; - protected int type; - - private static final int HSQUARE = 0; - private static final int SSQUARE = 1; - private static final int BSQUARE = 2; - private static final int HSLIDER = 3; - private static final int SSLIDER = 4; - private static final int BSLIDER = 5; - - protected HSBImage(int type, int width, int height, float h, float s, float b) { - super(width, height); - setValues(type, h, s, b); - } - - public void setValues(int type, float h, float s, float b) { - this.type = type; - cachedY = -1; - cachedColor = 0; - setHue( h ); - setSaturation( s ); - setBrightness( b ); - } - - public final void setHue( float hue ) { - h = hue; - } - - public final void setSaturation( float saturation ) { - s = saturation; - } - - public final void setBrightness( float brightness ) { - b = brightness; - } - - public final float getHue() { - return h; - } - - public final float getSaturation() { - return s; - } - - public final float getBrightness() { - return b; - } - - protected boolean isStatic() { - return false; - } - - public synchronized void nextFrame() { - isDirty = true; - notifyAll(); - } - - public synchronized void addConsumer(ImageConsumer ic) { - isDirty = true; - super.addConsumer(ic); - } - - private int getRGBForLocation( int x, int y ) { - if (type >= HSLIDER && y == cachedY) { - return cachedColor; - } - - getHSBForLocation( x, y, hsb ); - cachedY = y; - cachedColor = Color.HSBtoRGB( hsb[0], hsb[1], hsb[2] ); - - return cachedColor; - } - - public void getHSBForLocation( int x, int y, float[] hsbArray ) { - switch (type) { - case HSQUARE: { - float saturationStep = ((float)x) / width; - float brightnessStep = ((float)y) / height; - hsbArray[0] = h; - hsbArray[1] = s - saturationStep; - hsbArray[2] = b - brightnessStep; - break; - } - case SSQUARE: { - float brightnessStep = ((float)y) / height; - float step = 1.0f / ((float)width); - hsbArray[0] = x * step; - hsbArray[1] = s; - hsbArray[2] = 1.0f - brightnessStep; - break; - } - case BSQUARE: { - float saturationStep = ((float)y) / height; - float step = 1.0f / ((float)width); - hsbArray[0] = x * step; - hsbArray[1] = 1.0f - saturationStep; - hsbArray[2] = b; - break; - } - case HSLIDER: { - float step = 1.0f / ((float)height); - hsbArray[0] = y * step; - hsbArray[1] = s; - hsbArray[2] = b; - break; - } - case SSLIDER: { - float saturationStep = ((float)y) / height; - hsbArray[0] = h; - hsbArray[1] = s - saturationStep; - hsbArray[2] = b; - break; - } - case BSLIDER: { - float brightnessStep = ((float)y) / height; - hsbArray[0] = h; - hsbArray[1] = s; - hsbArray[2] = b - brightnessStep; - break; - } - } - } - - /** - * Overriden method from SyntheticImage - */ - protected void computeRow( int y, int[] row ) { - if ( y == 0 ) { - synchronized ( this ) { - try { - while ( !isDirty ) { - wait(); - } - } catch (InterruptedException ie) { - } - isDirty = false; - } - } - - if (aborted) { - return; - } - - for ( int i = 0; i < row.length; ++i ) { - row[i] = getRGBForLocation( i, y ); - } - } - } - - public void stateChanged(ChangeEvent e) { - if (e.getSource() == slider) { - boolean modelIsAdjusting = slider.getModel().getValueIsAdjusting(); - - if (!modelIsAdjusting && !isAdjusting) { - int sliderValue = slider.getValue(); - int sliderRange = slider.getMaximum(); - float value = (float)sliderValue / (float)sliderRange; - - float[] hsb = getHSBColorFromModel(); - - switch ( currentMode ){ - case HUE_MODE: - updateHSB(value, hsb[1], hsb[2]); - break; - case SATURATION_MODE: - updateHSB(hsb[0], value, hsb[2]); - break; - case BRIGHTNESS_MODE: - updateHSB(hsb[0], hsb[1], value); - break; - } - } - } else if (e.getSource() instanceof JSpinner) { - float hue = ((Integer)hField.getValue()).floatValue() / 359f; - float saturation = ((Integer)sField.getValue()).floatValue() / 100f; - float brightness = ((Integer)bField.getValue()).floatValue() / 100f; - - updateHSB(hue, saturation, brightness); - } - } - - public void hierarchyChanged(HierarchyEvent he) { - if ((he.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) { - if (isDisplayable()) { - initializePalettesIfNecessary(); - } else { - cleanupPalettesIfNecessary(); - } - } - } - -} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/DefaultRGBChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/DefaultRGBChooserPanel.java deleted file mode 100644 index 28850dffaac..00000000000 --- a/jdk/src/share/classes/javax/swing/colorchooser/DefaultRGBChooserPanel.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package javax.swing.colorchooser; - -import javax.swing.*; -import javax.swing.event.*; -import java.awt.*; -import java.util.Locale; - -/** - * The standard RGB chooser. - *

- * Warning: - * Serialized objects of this class will not be compatible with - * future Swing releases. The current serialization support is - * appropriate for short term storage or RMI between applications running - * the same version of Swing. As of 1.4, support for long term storage - * of all JavaBeansTM - * has been added to the java.beans package. - * Please see {@link java.beans.XMLEncoder}. - * - * @author Steve Wilson - * @author Mark Davidson - * @see JColorChooser - * @see AbstractColorChooserPanel - */ -class DefaultRGBChooserPanel extends AbstractColorChooserPanel implements ChangeListener { - - protected JSlider redSlider; - protected JSlider greenSlider; - protected JSlider blueSlider; - protected JSpinner redField; - protected JSpinner blueField; - protected JSpinner greenField; - - private final int minValue = 0; - private final int maxValue = 255; - - private boolean isAdjusting = false; // indicates the fields are being set internally - - public DefaultRGBChooserPanel() { - super(); - setInheritsPopupMenu(true); - } - - /** - * Sets the values of the controls to reflect the color - */ - private void setColor( Color newColor ) { - int red = newColor.getRed(); - int blue = newColor.getBlue(); - int green = newColor.getGreen(); - - if (redSlider.getValue() != red) { - redSlider.setValue(red); - } - if (greenSlider.getValue() != green) { - greenSlider.setValue(green); - } - if (blueSlider.getValue() != blue) { - blueSlider.setValue(blue); - } - - if (((Integer)redField.getValue()).intValue() != red) - redField.setValue(new Integer(red)); - if (((Integer)greenField.getValue()).intValue() != green) - greenField.setValue(new Integer(green)); - if (((Integer)blueField.getValue()).intValue() != blue ) - blueField.setValue(new Integer(blue)); - } - - public String getDisplayName() { - return UIManager.getString("ColorChooser.rgbNameText", getLocale()); - } - - /** - * Provides a hint to the look and feel as to the - * KeyEvent.VK constant that can be used as a mnemonic to - * access the panel. A return value <= 0 indicates there is no mnemonic. - *

- * The return value here is a hint, it is ultimately up to the look - * and feel to honor the return value in some meaningful way. - *

- * This implementation looks up the value from the default - * ColorChooser.rgbMnemonic, or if it - * isn't available (or not an Integer) returns -1. - * The lookup for the default is done through the UIManager: - * UIManager.get("ColorChooser.rgbMnemonic");. - * - * @return KeyEvent.VK constant identifying the mnemonic; <= 0 for no - * mnemonic - * @see #getDisplayedMnemonicIndex - * @since 1.4 - */ - public int getMnemonic() { - return getInt("ColorChooser.rgbMnemonic", -1); - } - - /** - * Provides a hint to the look and feel as to the index of the character in - * getDisplayName that should be visually identified as the - * mnemonic. The look and feel should only use this if - * getMnemonic returns a value > 0. - *

- * The return value here is a hint, it is ultimately up to the look - * and feel to honor the return value in some meaningful way. For example, - * a look and feel may wish to render each - * AbstractColorChooserPanel in a JTabbedPane, - * and further use this return value to underline a character in - * the getDisplayName. - *

- * This implementation looks up the value from the default - * ColorChooser.rgbDisplayedMnemonicIndex, or if it - * isn't available (or not an Integer) returns -1. - * The lookup for the default is done through the UIManager: - * UIManager.get("ColorChooser.rgbDisplayedMnemonicIndex");. - * - * @return Character index to render mnemonic for; -1 to provide no - * visual identifier for this panel. - * @see #getMnemonic - * @since 1.4 - */ - public int getDisplayedMnemonicIndex() { - return getInt("ColorChooser.rgbDisplayedMnemonicIndex", -1); - } - - public Icon getSmallDisplayIcon() { - return null; - } - - public Icon getLargeDisplayIcon() { - return null; - } - - /** - * The background color, foreground color, and font are already set to the - * defaults from the defaults table before this method is called. - */ - public void installChooserPanel(JColorChooser enclosingChooser) { - super.installChooserPanel(enclosingChooser); - } - - protected void buildChooser() { - - Locale locale = getLocale(); - String redString = UIManager.getString("ColorChooser.rgbRedText", locale); - String greenString = UIManager.getString("ColorChooser.rgbGreenText", locale); - String blueString = UIManager.getString("ColorChooser.rgbBlueText", locale); - - setLayout( new BorderLayout() ); - Color color = getColorFromModel(); - - - JPanel enclosure = new JPanel(); - enclosure.setLayout( new SmartGridLayout( 3, 3 ) ); - enclosure.setInheritsPopupMenu(true); - - // The panel that holds the sliders - - add( enclosure, BorderLayout.CENTER ); - // sliderPanel.setBorder(new LineBorder(Color.black)); - - // The row for the red value - JLabel l = new JLabel(redString); - l.setDisplayedMnemonic(getInt("ColorChooser.rgbRedMnemonic", -1)); - enclosure.add(l); - redSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, color.getRed()); - redSlider.setMajorTickSpacing( 85 ); - redSlider.setMinorTickSpacing( 17 ); - redSlider.setPaintTicks( true ); - redSlider.setPaintLabels( true ); - redSlider.setInheritsPopupMenu(true); - enclosure.add( redSlider ); - redField = new JSpinner( - new SpinnerNumberModel(color.getRed(), minValue, maxValue, 1)); - l.setLabelFor(redSlider); - redField.setInheritsPopupMenu(true); - JPanel redFieldHolder = new JPanel(new CenterLayout()); - redFieldHolder.setInheritsPopupMenu(true); - redField.addChangeListener(this); - redFieldHolder.add(redField); - enclosure.add(redFieldHolder); - - - // The row for the green value - l = new JLabel(greenString); - l.setDisplayedMnemonic(getInt("ColorChooser.rgbGreenMnemonic", -1)); - enclosure.add(l); - greenSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, color.getGreen()); - greenSlider.setMajorTickSpacing( 85 ); - greenSlider.setMinorTickSpacing( 17 ); - greenSlider.setPaintTicks( true ); - greenSlider.setPaintLabels( true ); - greenSlider.setInheritsPopupMenu(true); - enclosure.add(greenSlider); - greenField = new JSpinner( - new SpinnerNumberModel(color.getGreen(), minValue, maxValue, 1)); - l.setLabelFor(greenSlider); - greenField.setInheritsPopupMenu(true); - JPanel greenFieldHolder = new JPanel(new CenterLayout()); - greenFieldHolder.add(greenField); - greenFieldHolder.setInheritsPopupMenu(true); - greenField.addChangeListener(this); - enclosure.add(greenFieldHolder); - - // The slider for the blue value - l = new JLabel(blueString); - l.setDisplayedMnemonic(getInt("ColorChooser.rgbBlueMnemonic", -1)); - enclosure.add(l); - blueSlider = new JSlider(JSlider.HORIZONTAL, 0, 255, color.getBlue()); - blueSlider.setMajorTickSpacing( 85 ); - blueSlider.setMinorTickSpacing( 17 ); - blueSlider.setPaintTicks( true ); - blueSlider.setPaintLabels( true ); - blueSlider.setInheritsPopupMenu(true); - enclosure.add(blueSlider); - blueField = new JSpinner( - new SpinnerNumberModel(color.getBlue(), minValue, maxValue, 1)); - l.setLabelFor(blueSlider); - blueField.setInheritsPopupMenu(true); - JPanel blueFieldHolder = new JPanel(new CenterLayout()); - blueFieldHolder.add(blueField); - blueField.addChangeListener(this); - blueFieldHolder.setInheritsPopupMenu(true); - enclosure.add(blueFieldHolder); - - redSlider.addChangeListener( this ); - greenSlider.addChangeListener( this ); - blueSlider.addChangeListener( this ); - - redSlider.putClientProperty("JSlider.isFilled", Boolean.TRUE); - greenSlider.putClientProperty("JSlider.isFilled", Boolean.TRUE); - blueSlider.putClientProperty("JSlider.isFilled", Boolean.TRUE); - } - - public void uninstallChooserPanel(JColorChooser enclosingChooser) { - super.uninstallChooserPanel(enclosingChooser); - removeAll(); - } - - public void updateChooser() { - if (!isAdjusting) { - isAdjusting = true; - - setColor(getColorFromModel()); - - isAdjusting = false; - } - } - - public void stateChanged( ChangeEvent e ) { - if ( e.getSource() instanceof JSlider && !isAdjusting) { - - int red = redSlider.getValue(); - int green = greenSlider.getValue(); - int blue = blueSlider.getValue() ; - Color color = new Color (red, green, blue); - - getColorSelectionModel().setSelectedColor(color); - } else if (e.getSource() instanceof JSpinner && !isAdjusting) { - - int red = ((Integer)redField.getValue()).intValue(); - int green = ((Integer)greenField.getValue()).intValue(); - int blue = ((Integer)blueField.getValue()).intValue(); - Color color = new Color (red, green, blue); - - getColorSelectionModel().setSelectedColor(color); - } - } - -} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/DiagramComponent.java b/jdk/src/share/classes/javax/swing/colorchooser/DiagramComponent.java new file mode 100644 index 00000000000..04905589e99 --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/DiagramComponent.java @@ -0,0 +1,160 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.image.BufferedImage; +import javax.swing.JComponent; + +final class DiagramComponent extends JComponent implements MouseListener, MouseMotionListener { + + private final ColorPanel panel; + private final boolean diagram; + + private final Insets insets = new Insets(0, 0, 0, 0); + + private int width; + private int height; + + private int[] array; + private BufferedImage image; + + DiagramComponent(ColorPanel panel, boolean diagram) { + this.panel = panel; + this.diagram = diagram; + addMouseListener(this); + addMouseMotionListener(this); + } + + @Override + protected void paintComponent(Graphics g) { + getInsets(this.insets); + this.width = getWidth() - this.insets.left - this.insets.right; + this.height = getHeight() - this.insets.top - this.insets.bottom; + + boolean update = (this.image == null) + || (this.width != this.image.getWidth()) + || (this.height != this.image.getHeight()); + if (update) { + int size = this.width * this.height; + if ((this.array == null) || (this.array.length < size)) { + this.array = new int[size]; + } + this.image = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB); + } + { + float dx = 1.0f / (float) (this.width - 1); + float dy = 1.0f / (float) (this.height - 1); + + int offset = 0; + float y = 0.0f; + for (int h = 0; h < this.height; h++, y += dy) { + if (this.diagram) { + float x = 0.0f; + for (int w = 0; w < this.width; w++, x += dx, offset++) { + this.array[offset] = this.panel.getColor(x, y); + } + } + else { + int color = this.panel.getColor(y); + for (int w = 0; w < this.width; w++, offset++) { + this.array[offset] = color; + } + } + } + } + this.image.setRGB(0, 0, this.width, this.height, this.array, 0, this.width); + g.drawImage(this.image, this.insets.left, this.insets.top, this.width, this.height, this); + if (isEnabled()) { + this.width--; + this.height--; + g.setXORMode(Color.WHITE); + g.setColor(Color.BLACK); + if (this.diagram) { + int x = getValue(this.panel.getValueX(), this.insets.left, this.width); + int y = getValue(this.panel.getValueY(), this.insets.top, this.height); + g.drawLine(x - 8, y, x + 8, y); + g.drawLine(x, y - 8, x, y + 8); + } + else { + int z = getValue(this.panel.getValueZ(), this.insets.top, this.height); + g.drawLine(this.insets.left, z, this.insets.left + this.width, z); + } + g.setPaintMode(); + } + } + + public void mousePressed(MouseEvent event) { + mouseDragged(event); + } + + public void mouseReleased(MouseEvent event) { + } + + public void mouseClicked(MouseEvent event) { + } + + public void mouseEntered(MouseEvent event) { + } + + public void mouseExited(MouseEvent event) { + } + + public void mouseMoved(MouseEvent event) { + } + + public void mouseDragged(MouseEvent event) { + if (isEnabled()) { + float y = getValue(event.getY(), this.insets.top, this.height); + if (this.diagram) { + float x = getValue(event.getX(), this.insets.left, this.width); + this.panel.setValue(x, y); + } + else { + this.panel.setValue(y); + } + } + } + + private static int getValue(float value, int min, int max) { + return min + (int) (value * (float) (max)); + } + + private static float getValue(int value, int min, int max) { + if (min < value) { + value -= min; + return (value < max) + ? (float) value / (float) max + : 1.0f; + } + return 0.0f; + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/SlidingSpinner.java b/jdk/src/share/classes/javax/swing/colorchooser/SlidingSpinner.java new file mode 100644 index 00000000000..99e9bf29858 --- /dev/null +++ b/jdk/src/share/classes/javax/swing/colorchooser/SlidingSpinner.java @@ -0,0 +1,118 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.swing.colorchooser; + +import javax.swing.JComponent; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.JSpinner.DefaultEditor; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +final class SlidingSpinner implements ChangeListener { + + private final ColorPanel panel; + private final JComponent label; + private final SpinnerNumberModel model = new SpinnerNumberModel(); + private final JSlider slider = new JSlider(); + private final JSpinner spinner = new JSpinner(this.model); + private float value; + private boolean internal; + + SlidingSpinner(ColorPanel panel, JComponent label) { + this.panel = panel; + this.label = label; + this.slider.addChangeListener(this); + this.spinner.addChangeListener(this); + DefaultEditor editor = (DefaultEditor) this.spinner.getEditor(); + ValueFormatter.init(3, false, editor.getTextField()); + editor.setFocusable(false); + this.spinner.setFocusable(false); + } + + JComponent getLabel() { + return this.label; + } + + JSlider getSlider() { + return this.slider; + } + + JSpinner getSpinner() { + return this.spinner; + } + + float getValue() { + return this.value; + } + + void setValue(float value) { + int min = this.slider.getMinimum(); + int max = this.slider.getMaximum(); + this.internal = true; + this.slider.setValue(min + (int) (value * (float) (max - min))); + this.spinner.setValue(Integer.valueOf(this.slider.getValue())); + this.internal = false; + this.value = value; + } + + void setRange(int min, int max) { + this.internal = true; + this.slider.setMinimum(min); + this.slider.setMaximum(max); + this.model.setMinimum(Integer.valueOf(min)); + this.model.setMaximum(Integer.valueOf(max)); + this.internal = false; + } + + void setVisible(boolean visible) { + this.label.setVisible(visible); + this.slider.setVisible(visible); + this.spinner.setVisible(visible); + } + + public void stateChanged(ChangeEvent event) { + if (!this.internal) { + if (this.spinner == event.getSource()) { + Object value = this.spinner.getValue(); + if (value instanceof Integer) { + this.internal = true; + this.slider.setValue((Integer) value); + this.internal = false; + } + } + int value = this.slider.getValue(); + this.internal = true; + this.spinner.setValue(Integer.valueOf(value)); + this.internal = false; + int min = this.slider.getMinimum(); + int max = this.slider.getMaximum(); + this.value = (float) (value - min) / (float) (max - min); + this.panel.colorChanged(); + } + } +} diff --git a/jdk/src/share/classes/javax/swing/colorchooser/SyntheticImage.java b/jdk/src/share/classes/javax/swing/colorchooser/SyntheticImage.java deleted file mode 100644 index cec69e9c39d..00000000000 --- a/jdk/src/share/classes/javax/swing/colorchooser/SyntheticImage.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package javax.swing.colorchooser; - -import java.awt.*; -import java.awt.image.*; - -/** A helper class to make computing synthetic images a little easier. - * All you need to do is define a subclass that overrides computeRow - * to compute a row of the image. It is passed the y coordinate of the - * row and an array into which to put the pixels in - * - * standard ARGB format. - *

Normal usage looks something like this: - *

 Image i = createImage(new SyntheticImage(200, 100) {
- *       protected void computeRow(int y, int[] row) {
- *         for(int i = width; --i>=0; ) {
- *             int grey = i*255/(width-1);
- *             row[i] = (255<<24)|(grey<<16)|(grey<<8)|grey;
- *         }
- *       }
- *   }
- *  
This creates a image 200 pixels wide and 100 pixels high - * that is a horizontal grey ramp, going from black on the left to - * white on the right. - *

- * If the image is to be a movie, override isStatic to return false, - * y cycling back to 0 is computeRow's signal that the next - * frame has started. It is acceptable (expected?) for computeRow(0,r) - * to pause until the appropriate time to start the next frame. - * - * @author James Gosling - */ -abstract class SyntheticImage implements ImageProducer { - private SyntheticImageGenerator root; - protected int width=10, height=100; - static final ColorModel cm = ColorModel.getRGBdefault(); - public static final int pixMask = 0xFF; - private Thread runner; - protected SyntheticImage() { } - protected SyntheticImage(int w, int h) { width = w; height = h; } - protected void computeRow(int y, int[] row) { - int p = 255-255*y/(height-1); - p = (pixMask<<24)|(p<<16)|(p<<8)|p; - for (int i = row.length; --i>=0; ) row[i] = p; - } - public synchronized void addConsumer(ImageConsumer ic){ - for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) - if (ics.ic == ic) return; - root = new SyntheticImageGenerator(ic, root, this); - } - public synchronized boolean isConsumer(ImageConsumer ic){ - for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) - if (ics.ic == ic) return true; - return false; - } - public synchronized void removeConsumer(ImageConsumer ic) { - SyntheticImageGenerator prev = null; - for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) { - if (ics.ic == ic) { - ics.useful = false; - if (prev!=null) prev.next = ics.next; - else root = ics.next; - return; - } - prev = ics; - } - } - public synchronized void startProduction(ImageConsumer ic) { - addConsumer(ic); - for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) - if (ics.useful && !ics.isAlive()) - ics.start(); - } - protected boolean isStatic() { return true; } - public void nextFrame(int param) {}//Override if !isStatic - public void requestTopDownLeftRightResend(ImageConsumer ic){} - - protected volatile boolean aborted = false; -} - -class SyntheticImageGenerator extends Thread { - ImageConsumer ic; - boolean useful; - SyntheticImageGenerator next; - SyntheticImage parent; - SyntheticImageGenerator(ImageConsumer ic, SyntheticImageGenerator next, - SyntheticImage parent) { - super("SyntheticImageGenerator"); - this.ic = ic; - this.next = next; - this.parent = parent; - useful = true; - setDaemon(true); - } - public void run() { - ImageConsumer ic = this.ic; - int w = parent.width; - int h = parent.height; - int hints = ic.SINGLEPASS|ic.COMPLETESCANLINES|ic.TOPDOWNLEFTRIGHT; - if (parent.isStatic()) - hints |= ic.SINGLEFRAME; - ic.setHints(hints); - ic.setDimensions(w, h); - ic.setProperties(null); - ic.setColorModel(parent.cm); - - if (useful) { - int[] row=new int[w]; - doPrivileged( new Runnable() { - public void run() { - Thread.currentThread().setPriority(Thread.MIN_PRIORITY); - } - }); - - do { - for (int y = 0; y>= 4; + } + return new String(array).toUpperCase(ENGLISH); + } + throw new ParseException("illegal object", 0); + } + + @Override + protected DocumentFilter getDocumentFilter() { + return this.filter; + } + + public void focusGained(FocusEvent event) { + Object source = event.getSource(); + if (source instanceof JFormattedTextField) { + this.text = (JFormattedTextField) source; + SwingUtilities.invokeLater(this); + } + } + + public void focusLost(FocusEvent event) { + } + + public void run() { + if (this.text != null) { + this.text.selectAll(); + } + } + + private boolean isValid(int length) { + return (0 <= length) && (length <= this.length); + } + + private boolean isValid(String text) { + int length = text.length(); + for (int i = 0; i < length; i++) { + char ch = text.charAt(i); + if (Character.digit(ch, this.radix) < 0) { + return false; + } + } + return true; + } +} diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java index fd63e7fcbb6..09f9372b9c3 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -299,8 +299,10 @@ public class BasicColorChooserUI extends ColorChooserUI tabbedPane.addTab(name, centerWrapper); if (mnemonic > 0) { tabbedPane.setMnemonicAt(i, mnemonic); - tabbedPane.setDisplayedMnemonicIndexAt( - i, newPanels[i].getDisplayedMnemonicIndex()); + int index = newPanels[i].getDisplayedMnemonicIndex(); + if (index >= 0) { + tabbedPane.setDisplayedMnemonicIndexAt(i, index); + } } } } diff --git a/jdk/test/javax/swing/JColorChooser/Test6524757.java b/jdk/test/javax/swing/JColorChooser/Test6524757.java index 0389efc70ad..dc7fa06ce59 100644 --- a/jdk/test/javax/swing/JColorChooser/Test6524757.java +++ b/jdk/test/javax/swing/JColorChooser/Test6524757.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,14 +34,13 @@ import java.awt.Dimension; import java.util.ArrayList; import java.util.List; import java.util.Locale; -import javax.swing.JButton; +import javax.swing.AbstractButton; import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JRadioButton; import javax.swing.UIManager; import javax.swing.WindowConstants; import javax.swing.colorchooser.AbstractColorChooserPanel; @@ -59,31 +58,41 @@ public class Test6524757 { "ColorChooser.swatchesNameText", // NON-NLS: string key from DefaultSwatchChooserPanel "ColorChooser.swatchesMnemonic", // NON-NLS: string key from DefaultSwatchChooserPanel:int - "ColorChooser.swatchesDisplayedMnemonicIndex", // NON-NLS: int key from DefaultSwatchChooserPanel "ColorChooser.swatchesSwatchSize", // NON-NLS: dimension key from DefaultSwatchChooserPanel "ColorChooser.swatchesRecentText", // NON-NLS: string key from DefaultSwatchChooserPanel "ColorChooser.swatchesRecentSwatchSize", // NON-NLS: dimension key from DefaultSwatchChooserPanel //NotAvail: "ColorChooser.swatchesDefaultRecentColor", // NON-NLS: color key from DefaultSwatchChooserPanel - "ColorChooser.hsbNameText", // NON-NLS: string key from DefaultHSBChooserPanel - "ColorChooser.hsbMnemonic", // NON-NLS: int key from DefaultHSBChooserPanel - "ColorChooser.hsbDisplayedMnemonicIndex", // NON-NLS: int key from DefaultHSBChooserPanel - "ColorChooser.hsbHueText", // NON-NLS: string key from DefaultHSBChooserPanel - "ColorChooser.hsbSaturationText", // NON-NLS: string key from DefaultHSBChooserPanel - "ColorChooser.hsbBrightnessText", // NON-NLS: string key from DefaultHSBChooserPanel - "ColorChooser.hsbRedText", // NON-NLS: string key from DefaultHSBChooserPanel - "ColorChooser.hsbGreenText", // NON-NLS: string key from DefaultHSBChooserPanel - "ColorChooser.hsbBlueText", // NON-NLS: string key from DefaultHSBChooserPanel + "ColorChooser.hsvNameText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hsvMnemonic", // NON-NLS: int key from HSV ColorChooserPanel + "ColorChooser.hsvHueText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hsvSaturationText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hsvValueText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hsvTransparencyText", // NON-NLS: string key from HSV ColorChooserPanel - "ColorChooser.rgbNameText", // NON-NLS: string key from DefaultRGBChooserPanel - "ColorChooser.rgbMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel - "ColorChooser.rgbDisplayedMnemonicIndex", // NON-NLS: int key from DefaultRGBChooserPanel - "ColorChooser.rgbRedText", // NON-NLS: string key from DefaultRGBChooserPanel - "ColorChooser.rgbGreenText", // NON-NLS: string key from DefaultRGBChooserPanel - "ColorChooser.rgbBlueText", // NON-NLS: string key from DefaultRGBChooserPanel - "ColorChooser.rgbRedMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel - "ColorChooser.rgbGreenMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel - "ColorChooser.rgbBlueMnemonic", // NON-NLS: int key from DefaultRGBChooserPanel + "ColorChooser.hslNameText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hslMnemonic", // NON-NLS: int key from HSV ColorChooserPanel + "ColorChooser.hslHueText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hslSaturationText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hslLightnessText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.hslTransparencyText", // NON-NLS: string key from HSV ColorChooserPanel + + "ColorChooser.rgbNameText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.rgbMnemonic", // NON-NLS: int key from HSV ColorChooserPanel + "ColorChooser.rgbRedText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.rgbGreenText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.rgbBlueText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.rgbAlphaText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.rgbHexCodeText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.rgbHexCodeMnemonic", // NON-NLS: int key from HSV ColorChooserPanel + + "ColorChooser.cmykNameText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.cmykMnemonic", // NON-NLS: int key from HSV ColorChooserPanel + "ColorChooser.cmykCyanText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.cmykMagentaText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.cmykYellowText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.cmykBlackText", // NON-NLS: string key from HSV ColorChooserPanel + "ColorChooser.cmykAlphaText", // NON-NLS: string key from HSV ColorChooserPanel }; private static final Object[] KOREAN = convert(Locale.KOREAN, KEYS); private static final Object[] FRENCH = convert(Locale.FRENCH, KEYS); @@ -91,19 +100,15 @@ public class Test6524757 { public static void main(String[] args) { // it affects Swing because it is not initialized Locale.setDefault(Locale.KOREAN); - Object[] korean = create(); + validate(KOREAN, create()); // it does not affect Swing because it is initialized Locale.setDefault(Locale.CANADA); - Object[] canada = create(); + validate(KOREAN, create()); // it definitely should affect Swing JComponent.setDefaultLocale(Locale.FRENCH); - Object[] french = create(); - - validate(KOREAN, korean); - validate(KOREAN, canada); - validate(FRENCH, french); + validate(FRENCH, create()); } private static void validate(Object[] expected, Object[] actual) { @@ -153,10 +158,47 @@ public class Test6524757 { // process all values List list = new ArrayList(KEYS.length); - addMain(list, dialog); - addSwatch(list, chooser); - addHSB(list, chooser); - addRGB(list, chooser); + + Component component = getC(getC(dialog.getLayeredPane(), 0), 1); + AbstractButton ok = (AbstractButton) getC(component, 0); + AbstractButton cancel = (AbstractButton) getC(component, 1); + AbstractButton reset = (AbstractButton) getC(component, 2); + list.add(ok.getText()); + list.add(cancel.getText()); + list.add(reset.getText()); + list.add(Integer.valueOf(reset.getMnemonic())); + + for (int i = 0; i < 5; i++) { + AbstractColorChooserPanel panel = (AbstractColorChooserPanel) getC(getC(getC(chooser, 0), i), 0); + list.add(panel.getDisplayName()); + list.add(Integer.valueOf(panel.getMnemonic())); + if (i == 0) { + JLabel label = (JLabel) getC(getC(panel, 0), 1); + JPanel upper = (JPanel) getC(getC(getC(panel, 0), 0), 0); + JPanel lower = (JPanel) getC(getC(getC(panel, 0), 2), 0); + addSize(list, upper, 1, 1, 31, 9); + list.add(label.getText()); + addSize(list, lower, 1, 1, 5, 7); + } + else { + Component container = getC(panel, 0); + for (int j = 0; j < 3; j++) { + AbstractButton button = (AbstractButton) getC(container, j); + list.add(button.getText()); + } + JLabel label = (JLabel) getC(container, 3); + list.add(label.getText()); + if (i == 4) { + label = (JLabel) getC(container, 4); + list.add(label.getText()); + } + if (i == 3) { + label = (JLabel) getC(panel, 1); + list.add(label.getText()); + list.add(Integer.valueOf(label.getDisplayedMnemonic())); + } + } + } // close dialog dialog.setVisible(false); @@ -169,56 +211,6 @@ public class Test6524757 { return list.toArray(); } - private static void addMain(List list, JDialog dialog) { - Component component = getC(getC(dialog.getLayeredPane(), 0), 1); - JButton ok = (JButton) getC(component, 0); - JButton cancel = (JButton) getC(component, 1); - JButton reset = (JButton) getC(component, 2); - list.add(ok.getText()); - list.add(cancel.getText()); - list.add(reset.getText()); - list.add(Integer.valueOf(reset.getMnemonic())); - } - - private static void addSwatch(List list, JColorChooser chooser) { - Component component = addPanel(list, chooser, 0); - JLabel label = (JLabel) getC(getC(component, 0), 1); - JPanel upper = (JPanel) getC(getC(getC(component, 0), 0), 0); - JPanel lower = (JPanel) getC(getC(getC(component, 0), 2), 0); - addSize(list, upper, 1, 1, 31, 9); - list.add(label.getText()); - addSize(list, lower, 1, 1, 5, 7); - } - - private static void addHSB(List list, JColorChooser chooser) { - Component component = addPanel(list, chooser, 1); - JRadioButton h = (JRadioButton) getC(getC(getC(component, 1), 0), 0); - JRadioButton s = (JRadioButton) getC(getC(getC(component, 1), 0), 2); - JRadioButton b = (JRadioButton) getC(getC(getC(component, 1), 0), 4); - list.add(h.getText()); - list.add(s.getText()); - list.add(b.getText()); - JLabel red = (JLabel) getC(getC(getC(component, 1), 2), 0); - JLabel green = (JLabel) getC(getC(getC(component, 1), 2), 2); - JLabel blue = (JLabel) getC(getC(getC(component, 1), 2), 4); - list.add(red.getText()); - list.add(green.getText()); - list.add(blue.getText()); - } - - private static void addRGB(List list, JColorChooser chooser) { - Component component = addPanel(list, chooser, 2); - JLabel red = (JLabel) getC(getC(component, 0), 0); - JLabel green = (JLabel) getC(getC(component, 0), 3); - JLabel blue = (JLabel) getC(getC(component, 0), 6); - list.add(red.getText()); - list.add(green.getText()); - list.add(blue.getText()); - list.add(Integer.valueOf(red.getDisplayedMnemonic())); - list.add(Integer.valueOf(green.getDisplayedMnemonic())); - list.add(Integer.valueOf(blue.getDisplayedMnemonic())); - } - private static void addSize(List list, Component component, int x, int y, int w, int h) { Dimension size = component.getPreferredSize(); int width = (size.width + 1) / w - x; @@ -226,14 +218,6 @@ public class Test6524757 { list.add(new Dimension(width, height)); } - private static Component addPanel(List list, JColorChooser chooser, int index) { - AbstractColorChooserPanel panel = (AbstractColorChooserPanel) getC(getC(getC(chooser, 0), index), 0); - list.add(panel.getDisplayName()); - list.add(Integer.valueOf(panel.getMnemonic())); - list.add(Integer.valueOf(panel.getDisplayedMnemonicIndex())); - return panel; - } - private static Component getC(Component component, int index) { Container container = (Container) component; return container.getComponent(index); diff --git a/jdk/test/javax/swing/JColorChooser/Test6559154.java b/jdk/test/javax/swing/JColorChooser/Test6559154.java new file mode 100644 index 00000000000..e84d90539d4 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test6559154.java @@ -0,0 +1,75 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6559154 + * @summary Tests EDT hanging + * @author Sergey Malenkov + */ + +import java.awt.Component; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JColorChooser; +import javax.swing.JDialog; +import javax.swing.SwingUtilities; +import javax.swing.Timer; + +public class Test6559154 implements ActionListener, Runnable { + + private JDialog dialog; + + public void actionPerformed(ActionEvent event) { + if (this.dialog != null) { + this.dialog.dispose(); + } + } + + public void run() { + Timer timer = new Timer(1000, this); + timer.setRepeats(false); + timer.start(); + + JColorChooser chooser = new JColorChooser(); + setEnabledRecursive(chooser, false); + + this.dialog = new JDialog(); + this.dialog.add(chooser); + this.dialog.setVisible(true); + } + + private static void setEnabledRecursive(Container container, boolean enabled) { + for (Component component : container.getComponents()) { + component.setEnabled(enabled); + if (component instanceof Container) { + setEnabledRecursive((Container) component, enabled); + } + } + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Test6559154()); + } +} From 7f530b42c8dc1ad26f21e4b1a7cff18fd8f21158 Mon Sep 17 00:00:00 2001 From: Igor Kushnirskiy Date: Mon, 21 Jul 2008 10:21:42 -0400 Subject: [PATCH 021/289] 6668281: NullPointerException in DefaultTableCellHeaderRenderer.getColumnSortOrder() Reviewed-by: alexp --- .../com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java index e2217e0f35a..0f2b39d8937 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTableHeaderUI.java @@ -124,7 +124,7 @@ public class WindowsTableHeaderUI extends BasicTableHeaderUI { setIcon(null); sortIcon = null; SortOrder sortOrder = - getColumnSortOrder(header.getTable(), column); + getColumnSortOrder(table, column); if (sortOrder != null) { switch (sortOrder) { case ASCENDING: From a44852b8fe9e4cfe0ce204d61870c382998e18d8 Mon Sep 17 00:00:00 2001 From: Mikhail Lapshin Date: Mon, 21 Jul 2008 19:58:43 +0400 Subject: [PATCH 022/289] 6607130: REGRESSION: JComboBox cell editor isn't hidden if the same value is selected with keyboard JComboBox cell editor now hides if the same value is selected with keyboard Reviewed-by: peterz, alexp --- .../swing/plaf/basic/BasicComboBoxUI.java | 12 +- .../swing/JComboBox/6607130/bug6607130.java | 149 ++++++++++++++++++ 2 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/swing/JComboBox/6607130/bug6607130.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java index f073eeda816..c49387fd91f 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -1509,15 +1509,21 @@ public class BasicComboBoxUI extends ComboBoxUI { || ui.isTableCellEditor) { Object listItem = ui.popup.getList().getSelectedValue(); if (listItem != null) { - comboBox.getModel().setSelectedItem(listItem); - // Ensure that JComboBox.actionPerformed() - // doesn't set editor value as selected item + // Use the selected value from popup + // to set the selected item in combo box, + // but ensure before that JComboBox.actionPerformed() + // won't use editor's value to set the selected item comboBox.getEditor().setItem(listItem); + comboBox.setSelectedItem(listItem); } } comboBox.setPopupVisible(false); } else { + // Hide combo box if it is a table cell editor + if (ui.isTableCellEditor && !comboBox.isEditable()) { + comboBox.setSelectedItem(comboBox.getSelectedItem()); + } // Call the default button binding. // This is a pretty messy way of passing an event through // to the root pane. diff --git a/jdk/test/javax/swing/JComboBox/6607130/bug6607130.java b/jdk/test/javax/swing/JComboBox/6607130/bug6607130.java new file mode 100644 index 00000000000..5d465c9d79d --- /dev/null +++ b/jdk/test/javax/swing/JComboBox/6607130/bug6607130.java @@ -0,0 +1,149 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6607130 + * @summary Checks that JComboBox cell editor is hidden if the same + * item is selected with keyboard. + * Also checks that JComboBox cell editor is hidden if F2 and then + * ENTER were pressed. + * @author Mikhail Lapshin + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.table.DefaultTableModel; +import java.awt.*; +import java.awt.event.KeyEvent; + +public class bug6607130 { + private JFrame frame; + private JComboBox cb; + private Robot robot; + + public static void main(String[] args) throws Exception { + final bug6607130 test = new bug6607130(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + test.setupUI(); + } + }); + test.test(); + } finally { + if (test.frame != null) { + test.frame.dispose(); + } + } + } + + public bug6607130() throws AWTException { + robot = new Robot(); + } + + private void setupUI() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + DefaultTableModel model = new DefaultTableModel(1, 1); + JTable table = new JTable(model); + + cb = new JComboBox(new String[]{"one", "two", "three"}); + table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(cb)); + frame.add(table); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void test() throws Exception { + realSync(); + test1(); + realSync(); + checkResult("First test"); + test2(); + realSync(); + checkResult("Second test"); + } + + private void test1() throws Exception { + // Select 'one' + hitKey(KeyEvent.VK_TAB); + realSync(); + hitKey(KeyEvent.VK_F2); + realSync(); + hitKey(KeyEvent.VK_DOWN); + realSync(); + hitKey(KeyEvent.VK_DOWN); + realSync(); + hitKey(KeyEvent.VK_ENTER); + realSync(); + + // Select 'one' again + hitKey(KeyEvent.VK_F2); + realSync(); + hitKey(KeyEvent.VK_DOWN); + realSync(); + hitKey(KeyEvent.VK_ENTER); + realSync(); + } + + private void test2() throws Exception { + // Press F2 and then press ENTER + // Editor should be shown and then closed + hitKey(KeyEvent.VK_F2); + realSync(); + hitKey(KeyEvent.VK_ENTER); + realSync(); + } + + private void checkResult(String testName) { + if (!cb.isShowing()) { + System.out.println(testName + " passed"); + } else { + System.out.println(testName + " failed"); + throw new RuntimeException("JComboBox is showing " + + "after item selection."); + } + } + + private static void realSync() { + ((SunToolkit) (Toolkit.getDefaultToolkit())).realSync(); + } + + public void hitKey(int keycode) { + robot.keyPress(keycode); + robot.keyRelease(keycode); + delay(); + } + + private void delay() { + try { + Thread.sleep(1000); + } catch(InterruptedException ie) { + ie.printStackTrace(); + } + } +} From fcbf2d124562828671e68f0d2275334bda16d2a7 Mon Sep 17 00:00:00 2001 From: Chuck Rasbold Date: Mon, 21 Jul 2008 13:37:05 -0700 Subject: [PATCH 023/289] 6726504: handle do_ifxxx calls in parser more uniformly Make do_ifnull() handling similar to do_if() Reviewed-by: jrose, kvn --- hotspot/src/share/vm/opto/parse.hpp | 2 +- hotspot/src/share/vm/opto/parse2.cpp | 36 +++++++++++----------------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index 10b3fe2ca14..bf344cb6f5f 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -479,7 +479,7 @@ class Parse : public GraphKit { float branch_prediction(float &cnt, BoolTest::mask btest, int target_bci); bool seems_never_taken(float prob); - void do_ifnull(BoolTest::mask btest); + void do_ifnull(BoolTest::mask btest, Node* c); void do_if(BoolTest::mask btest, Node* c); void repush_if_args(); void adjust_map_after_if(BoolTest::mask btest, Node* c, float prob, diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index e244d6a098e..a71c7726a2b 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -894,7 +894,7 @@ inline void Parse::repush_if_args() { } //----------------------------------do_ifnull---------------------------------- -void Parse::do_ifnull(BoolTest::mask btest) { +void Parse::do_ifnull(BoolTest::mask btest, Node *c) { int target_bci = iter().get_dest(); Block* branch_block = successor_for_bci(target_bci); @@ -906,8 +906,9 @@ void Parse::do_ifnull(BoolTest::mask btest) { // (An earlier version of do_ifnull omitted this trap for OSR methods.) #ifndef PRODUCT if (PrintOpto && Verbose) - tty->print_cr("Never-taken backedge stops compilation at bci %d",bci()); + tty->print_cr("Never-taken edge stops compilation at bci %d",bci()); #endif + repush_if_args(); // to gather stats on loop // We need to mark this branch as taken so that if we recompile we will // see that it is possible. In the tiered system the interpreter doesn't // do profiling and by the time we get to the lower tier from the interpreter @@ -928,14 +929,6 @@ void Parse::do_ifnull(BoolTest::mask btest) { maybe_add_safepoint(target_bci); explicit_null_checks_inserted++; - Node* a = null(); - Node* b = pop(); - Node* c = _gvn.transform( new (C, 3) CmpPNode(b, a) ); - - // Make a cast-away-nullness that is control dependent on the test - const Type *t = _gvn.type(b); - const Type *t_not_null = t->join(TypePtr::NOTNULL); - Node *cast = new (C, 2) CastPPNode(b,t_not_null); // Generate real control flow Node *tst = _gvn.transform( new (C, 2) BoolNode( c, btest ) ); @@ -997,7 +990,7 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { if (prob == PROB_UNKNOWN) { #ifndef PRODUCT if (PrintOpto && Verbose) - tty->print_cr("Never-taken backedge stops compilation at bci %d",bci()); + tty->print_cr("Never-taken edge stops compilation at bci %d",bci()); #endif repush_if_args(); // to gather stats on loop // We need to mark this branch as taken so that if we recompile we will @@ -1016,6 +1009,9 @@ void Parse::do_if(BoolTest::mask btest, Node* c) { return; } + // If this is a backwards branch in the bytecodes, add Safepoint + maybe_add_safepoint(target_bci); + // Sanity check the probability value assert(0.0f < prob && prob < 1.0f,"Bad probability in Parser"); @@ -2101,18 +2097,18 @@ void Parse::do_one_bytecode() { break; } - case Bytecodes::_ifnull: - do_ifnull(BoolTest::eq); - break; - case Bytecodes::_ifnonnull: - do_ifnull(BoolTest::ne); + case Bytecodes::_ifnull: btest = BoolTest::eq; goto handle_if_null; + case Bytecodes::_ifnonnull: btest = BoolTest::ne; goto handle_if_null; + handle_if_null: + a = null(); + b = pop(); + c = _gvn.transform( new (C, 3) CmpPNode(b, a) ); + do_ifnull(btest, c); break; case Bytecodes::_if_acmpeq: btest = BoolTest::eq; goto handle_if_acmp; case Bytecodes::_if_acmpne: btest = BoolTest::ne; goto handle_if_acmp; handle_if_acmp: - // If this is a backwards branch in the bytecodes, add Safepoint - maybe_add_safepoint(iter().get_dest()); a = pop(); b = pop(); c = _gvn.transform( new (C, 3) CmpPNode(b, a) ); @@ -2126,8 +2122,6 @@ void Parse::do_one_bytecode() { case Bytecodes::_ifgt: btest = BoolTest::gt; goto handle_ifxx; case Bytecodes::_ifge: btest = BoolTest::ge; goto handle_ifxx; handle_ifxx: - // If this is a backwards branch in the bytecodes, add Safepoint - maybe_add_safepoint(iter().get_dest()); a = _gvn.intcon(0); b = pop(); c = _gvn.transform( new (C, 3) CmpINode(b, a) ); @@ -2141,8 +2135,6 @@ void Parse::do_one_bytecode() { case Bytecodes::_if_icmpgt: btest = BoolTest::gt; goto handle_if_icmp; case Bytecodes::_if_icmpge: btest = BoolTest::ge; goto handle_if_icmp; handle_if_icmp: - // If this is a backwards branch in the bytecodes, add Safepoint - maybe_add_safepoint(iter().get_dest()); a = pop(); b = pop(); c = _gvn.transform( new (C, 3) CmpINode( b, a ) ); From f3eff961d36d7e4c1e00e1b5b1bcf97ceb6c01c4 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 23 Jul 2008 19:55:30 -0700 Subject: [PATCH 024/289] 6726015: JavaCompiler: replace desugarLater by compileStates Reviewed-by: mcimadamore --- .../sun/tools/javac/main/JavaCompiler.java | 96 ++++++++++--------- langtools/test/tools/javac/6199662/Tree.java | 2 +- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 402c2998275..1ab7c1096e0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -63,6 +63,7 @@ import static com.sun.tools.javac.util.ListBuffer.lb; // TEMP, until we have a more efficient way to save doc comment info import com.sun.tools.javac.parser.DocCommentScanner; +import java.util.HashMap; import java.util.Queue; import javax.lang.model.SourceVersion; @@ -444,7 +445,25 @@ public class JavaCompiler implements ClassReader.SourceCompleter { */ public Todo todo; - private Set> deferredSugar = new HashSet>(); + protected enum CompileState { + TODO(0), + ATTR(1), + FLOW(2); + CompileState(int value) { + this.value = value; + } + boolean isDone(CompileState other) { + return value >= other.value; + } + private int value; + }; + protected class CompileStates extends HashMap,CompileState> { + boolean isDone(Env env, CompileState cs) { + CompileState ecs = get(env); + return ecs != null && ecs.isDone(cs); + } + } + private CompileStates compileStates = new CompileStates(); /** The set of currently compiled inputfiles, needed to ensure * we don't accidentally overwrite an input file when -s is set. @@ -1039,6 +1058,9 @@ public class JavaCompiler implements ClassReader.SourceCompleter { * @returns the attributed parse tree */ public Env attribute(Env env) { + if (compileStates.isDone(env, CompileState.ATTR)) + return env; + if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[attribute " + env.enclClass.sym + "]"); if (verbose) @@ -1055,6 +1077,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { env.toplevel.sourcefile); try { attr.attribClass(env.tree.pos(), env.enclClass.sym); + compileStates.put(env, CompileState.ATTR); } finally { log.useSource(prev); @@ -1094,7 +1117,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { if (errorCount() > 0) return; - if (relax || deferredSugar.contains(env)) { + if (relax || compileStates.isDone(env, CompileState.FLOW)) { results.append(env); return; } @@ -1109,6 +1132,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { make.at(Position.FIRSTPOS); TreeMaker localMake = make.forToplevel(env.toplevel); flow.analyzeTree(env.tree, localMake); + compileStates.put(env, CompileState.FLOW); if (errorCount() > 0) return; @@ -1146,7 +1170,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { * the current implicitSourcePolicy is taken into account. * The preparation stops as soon as an error is found. */ - protected void desugar(Env env, Queue, JCClassDecl>> results) { + protected void desugar(final Env env, Queue, JCClassDecl>> results) { if (errorCount() > 0) return; @@ -1155,13 +1179,30 @@ public class JavaCompiler implements ClassReader.SourceCompleter { return; } - if (desugarLater(env)) { - if (verboseCompilePolicy) - log.printLines(log.noticeWriter, "[defer " + env.enclClass.sym + "]"); - todo.append(env); - return; + /** + * As erasure (TransTypes) destroys information needed in flow analysis, + * including information in supertypes, we need to ensure that supertypes + * are processed through attribute and flow before subtypes are translated. + */ + class ScanNested extends TreeScanner { + Set> dependencies = new HashSet>(); + public void visitClassDef(JCClassDecl node) { + Type st = types.supertype(node.sym.type); + if (st.tag == TypeTags.CLASS) { + ClassSymbol c = st.tsym.outermostClass(); + Env stEnv = enter.getEnv(c); + if (stEnv != null && env != stEnv) + dependencies.add(stEnv); + } + super.visitClassDef(node); + } + } + ScanNested scanner = new ScanNested(); + scanner.scan(env.tree); + for (Env dep: scanner.dependencies) { + if (!compileStates.isDone(dep, CompileState.FLOW)) + flow(attribute(dep)); } - deferredSugar.remove(env); if (verboseCompilePolicy) log.printLines(log.noticeWriter, "[desugar " + env.enclClass.sym + "]"); @@ -1234,43 +1275,6 @@ public class JavaCompiler implements ClassReader.SourceCompleter { } - /** - * Determine if a class needs to be desugared later. As erasure - * (TransTypes) destroys information needed in flow analysis, we - * need to ensure that supertypes are translated before derived - * types are translated. - */ - public boolean desugarLater(final Env env) { - if (compilePolicy == CompilePolicy.BY_FILE) - return false; - if (!devVerbose && deferredSugar.contains(env)) - // guarantee that compiler terminates - return false; - class ScanNested extends TreeScanner { - Set externalSupers = new HashSet(); - public void visitClassDef(JCClassDecl node) { - Type st = types.supertype(node.sym.type); - if (st.tag == TypeTags.CLASS) { - ClassSymbol c = st.tsym.outermostClass(); - Env stEnv = enter.getEnv(c); - if (stEnv != null && env != stEnv) - externalSupers.add(st.tsym); - } - super.visitClassDef(node); - } - } - ScanNested scanner = new ScanNested(); - scanner.scan(env.tree); - if (scanner.externalSupers.isEmpty()) - return false; - if (!deferredSugar.add(env) && devVerbose) { - throw new AssertionError(env.enclClass.sym + " was deferred, " + - "second time has these external super types " + - scanner.externalSupers); - } - return true; - } - /** Generates the source or class file for a list of classes. * The decision to generate a source file or a class file is * based upon the compiler's options. diff --git a/langtools/test/tools/javac/6199662/Tree.java b/langtools/test/tools/javac/6199662/Tree.java index add54d1013e..70346183770 100644 --- a/langtools/test/tools/javac/6199662/Tree.java +++ b/langtools/test/tools/javac/6199662/Tree.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6199662 6325201 + * @bug 6199662 6325201 6726015 * @summary javac: compilation success depends on compilation order * * @compile Tree.java TreeScanner.java TreeInfo.java From fec04e0a18d65269afafe0785688c0c82d3bbf47 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 24 Jul 2008 10:35:38 +0100 Subject: [PATCH 025/289] 6651719: Compiler crashes possibly during forward reference of TypeParameter Compiler should apply capture conversion when checking for bound conformance Reviewed-by: jjg --- .../com/sun/tools/javac/comp/Check.java | 34 +++++++++++++------ .../generics/wildcards/6651719/T6651719a.java | 33 ++++++++++++++++++ .../wildcards/6651719/T6651719b.java} | 25 +++++--------- 3 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 langtools/test/tools/javac/generics/wildcards/6651719/T6651719a.java rename langtools/test/tools/javac/{capture/Capture4.java => generics/wildcards/6651719/T6651719b.java} (72%) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 59b909c7b96..efdb075d121 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -422,9 +422,7 @@ public class Check { * @param bs The bound. */ private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { - if (a.isUnbound()) { - return; - } else if (a.tag != WILDCARD) { + if (!(a instanceof CapturedType)) { a = types.upperBound(a); for (List l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { if (!types.isSubtype(a, l.head)) { @@ -432,11 +430,24 @@ public class Check { return; } } - } else if (a.isExtendsBound()) { - if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings)) - log.error(pos, "not.within.bounds", a); - } else if (a.isSuperBound()) { - if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound())) + } + else { + CapturedType ct = (CapturedType)a; + boolean ok = false; + switch (ct.wildcard.kind) { + case EXTENDS: + ok = types.isCastable(bs.getUpperBound(), + types.upperBound(a), + Warner.noWarnings); + break; + case SUPER: + ok = !types.notSoftSubtype(types.lowerBound(a), + bs.getUpperBound()); + break; + case UNBOUND: + ok = true; + } + if (!ok) log.error(pos, "not.within.bounds", a); } } @@ -776,7 +787,7 @@ public class Check { public void visitTypeApply(JCTypeApply tree) { if (tree.type.tag == CLASS) { List formals = tree.type.tsym.type.getTypeArguments(); - List actuals = tree.type.getTypeArguments(); + List actuals = types.capture(tree.type).getTypeArguments(); List args = tree.arguments; List forms = formals; ListBuffer tvars_buf = new ListBuffer(); @@ -792,7 +803,7 @@ public class Check { // bounds substed with actuals. tvars_buf.append(types.substBound(((TypeVar)forms.head), formals, - Type.removeBounds(actuals))); + actuals)); args = args.tail; forms = forms.tail; @@ -811,10 +822,11 @@ public class Check { tvars = tvars_buf.toList(); while (args.nonEmpty() && tvars.nonEmpty()) { checkExtends(args.head.pos(), - args.head.type, + actuals.head, tvars.head); args = args.tail; tvars = tvars.tail; + actuals = actuals.tail; } // Check that this type is either fully parameterized, or diff --git a/langtools/test/tools/javac/generics/wildcards/6651719/T6651719a.java b/langtools/test/tools/javac/generics/wildcards/6651719/T6651719a.java new file mode 100644 index 00000000000..28bdcf4257b --- /dev/null +++ b/langtools/test/tools/javac/generics/wildcards/6651719/T6651719a.java @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6651719 + * @summary Compiler crashes possibly during forward reference of TypeParameter + * @compile T6651719a.java + */ + +public class T6651719a { + T6651719a, ? extends T6651719a> crash = null; +} diff --git a/langtools/test/tools/javac/capture/Capture4.java b/langtools/test/tools/javac/generics/wildcards/6651719/T6651719b.java similarity index 72% rename from langtools/test/tools/javac/capture/Capture4.java rename to langtools/test/tools/javac/generics/wildcards/6651719/T6651719b.java index 2f82f41cf70..f14e4799638 100644 --- a/langtools/test/tools/javac/capture/Capture4.java +++ b/langtools/test/tools/javac/generics/wildcards/6651719/T6651719b.java @@ -1,5 +1,5 @@ /* - * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,22 +23,15 @@ /* * @test - * @bug 4916650 - * @summary wildcards versus recursive F-bounds - * @author gafter - * - * @compile -source 1.5 Capture4.java + * @bug 6651719 + * @summary Compiler crashes possibly during forward reference of TypeParameter + * @compile T6651719b.java */ +import java.util.*; -package capture4; - -class WildcardFBoundCheck { - interface I4 {} - - static class C4, Y extends I4> {} - - WildcardFBoundCheck() - { - C4,?> x2; // <> +public class T6651719b { + void m(T t, List> list) {} + void test(List> list) { + m("", list); } } From 9879011723a68c11a4cc9d96f613148ba26af31a Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Thu, 24 Jul 2008 11:12:41 +0100 Subject: [PATCH 026/289] 6594284: NPE thrown when calling a method on an intersection type Javac should report an error when the capture of an actual type parameter does not exist Reviewed-by: jjg --- .../com/sun/tools/javac/code/Type.java | 9 ++++ .../com/sun/tools/javac/code/Types.java | 2 +- .../com/sun/tools/javac/comp/Check.java | 48 +++++++++++-------- .../test/tools/javac/capture/T6594284.java | 43 +++++++++++++++++ 4 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 langtools/test/tools/javac/capture/T6594284.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java index b3115da9b2f..4c8e78cc294 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java @@ -979,6 +979,10 @@ public class Type implements PrimitiveType { return TypeKind.TYPEVAR; } + public boolean isCaptured() { + return false; + } + public R accept(TypeVisitor v, P p) { return v.visitTypeVariable(this, p); } @@ -1014,6 +1018,11 @@ public class Type implements PrimitiveType { return lower; } + @Override + public boolean isCaptured() { + return true; + } + @Override public String toString() { return "capture#" diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index cc86c636f29..36a605d5eb1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -835,7 +835,7 @@ public class Types { }; public boolean isCaptureOf(Type s, WildcardType t) { - if (s.tag != TYPEVAR || !(s instanceof CapturedType)) + if (s.tag != TYPEVAR || !((TypeVar)s).isCaptured()) return false; return isSameWildcard(t, ((CapturedType)s).wildcard); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index efdb075d121..44fbc6ba9ea 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -422,7 +422,34 @@ public class Check { * @param bs The bound. */ private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) { - if (!(a instanceof CapturedType)) { + if (a.tag == TYPEVAR && ((TypeVar)a).isCaptured()) { + CapturedType ct = (CapturedType)a; + boolean ok; + if (ct.bound.isErroneous()) {//capture doesn't exist + ok = false; + } + else { + switch (ct.wildcard.kind) { + case EXTENDS: + ok = types.isCastable(bs.getUpperBound(), + types.upperBound(a), + Warner.noWarnings); + break; + case SUPER: + ok = !types.notSoftSubtype(types.lowerBound(a), + bs.getUpperBound()); + break; + case UNBOUND: + ok = true; + break; + default: + throw new AssertionError("Invalid bound kind"); + } + } + if (!ok) + log.error(pos, "not.within.bounds", a); + } + else { a = types.upperBound(a); for (List l = types.getBounds(bs); l.nonEmpty(); l = l.tail) { if (!types.isSubtype(a, l.head)) { @@ -431,25 +458,6 @@ public class Check { } } } - else { - CapturedType ct = (CapturedType)a; - boolean ok = false; - switch (ct.wildcard.kind) { - case EXTENDS: - ok = types.isCastable(bs.getUpperBound(), - types.upperBound(a), - Warner.noWarnings); - break; - case SUPER: - ok = !types.notSoftSubtype(types.lowerBound(a), - bs.getUpperBound()); - break; - case UNBOUND: - ok = true; - } - if (!ok) - log.error(pos, "not.within.bounds", a); - } } /** Check that type is different from 'void'. diff --git a/langtools/test/tools/javac/capture/T6594284.java b/langtools/test/tools/javac/capture/T6594284.java new file mode 100644 index 00000000000..71112f7044d --- /dev/null +++ b/langtools/test/tools/javac/capture/T6594284.java @@ -0,0 +1,43 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6594284 + * @summary NPE thrown when calling a method on an intersection type + * @author Maurizio Cimadamore + * + * @compile/fail T6594284.java + */ + +public class T6594284 { + class A{ public void a(){}} + class B extends A{ public void b(){}} + interface I{ void i();} + interface I1 { void i1(); } + class E extends B implements I{ public void i(){};} + + class C{ + C arg; + } +} From c3732ffc5d459769b969da2ae7c5b90d36d3d523 Mon Sep 17 00:00:00 2001 From: Mikhail Lapshin Date: Thu, 24 Jul 2008 14:34:02 +0400 Subject: [PATCH 027/289] 6725409: Unable to localize JInternalFrame system menu during run-time Use of the static final constants replaced by direct calls of UIManager.getString(). Reviewed-by: alexp --- .../basic/BasicInternalFrameTitlePane.java | 19 +- .../JInternalFrame/6725409/bug6725409.java | 162 ++++++++++++++++++ 2 files changed, 175 insertions(+), 6 deletions(-) create mode 100644 jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java index 344a4b2b512..d8f25731266 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java @@ -86,6 +86,7 @@ public class BasicInternalFrameTitlePane extends JComponent protected Action moveAction; protected Action sizeAction; + // These constants are not used in JDK code protected static final String CLOSE_CMD = UIManager.getString("InternalFrameTitlePane.closeButtonText"); protected static final String ICONIFY_CMD = @@ -600,7 +601,8 @@ public class BasicInternalFrameTitlePane extends JComponent */ public class CloseAction extends AbstractAction { public CloseAction() { - super(CLOSE_CMD); + super(UIManager.getString( + "InternalFrameTitlePane.closeButtonText")); } public void actionPerformed(ActionEvent e) { @@ -616,7 +618,8 @@ public class BasicInternalFrameTitlePane extends JComponent */ public class MaximizeAction extends AbstractAction { public MaximizeAction() { - super(MAXIMIZE_CMD); + super(UIManager.getString( + "InternalFrameTitlePane.maximizeButtonText")); } public void actionPerformed(ActionEvent evt) { @@ -644,7 +647,8 @@ public class BasicInternalFrameTitlePane extends JComponent */ public class IconifyAction extends AbstractAction { public IconifyAction() { - super(ICONIFY_CMD); + super(UIManager.getString( + "InternalFrameTitlePane.minimizeButtonText")); } public void actionPerformed(ActionEvent e) { @@ -664,7 +668,8 @@ public class BasicInternalFrameTitlePane extends JComponent */ public class RestoreAction extends AbstractAction { public RestoreAction() { - super(RESTORE_CMD); + super(UIManager.getString( + "InternalFrameTitlePane.restoreButtonText")); } public void actionPerformed(ActionEvent evt) { @@ -690,7 +695,8 @@ public class BasicInternalFrameTitlePane extends JComponent */ public class MoveAction extends AbstractAction { public MoveAction() { - super(MOVE_CMD); + super(UIManager.getString( + "InternalFrameTitlePane.moveButtonText")); } public void actionPerformed(ActionEvent e) { @@ -723,7 +729,8 @@ public class BasicInternalFrameTitlePane extends JComponent */ public class SizeAction extends AbstractAction { public SizeAction() { - super(SIZE_CMD); + super(UIManager.getString( + "InternalFrameTitlePane.sizeButtonText")); } public void actionPerformed(ActionEvent e) { diff --git a/jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java b/jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java new file mode 100644 index 00000000000..b118fed88be --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/6725409/bug6725409.java @@ -0,0 +1,162 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6725409 + * @summary Checks that JInternalFrame's system menu + * can be localized during run-time + * @author Mikhail Lapshin + */ + +import javax.swing.*; +import java.awt.*; + +public class bug6725409 { + private JFrame frame; + private JInternalFrame iFrame; + private TestTitlePane testTitlePane; + private boolean passed; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel( + new com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel()); + } catch(UnsupportedLookAndFeelException e) { + System.out.println("The test is for Windows LaF only"); + System.exit(0); + } + + final bug6725409 bug6725409 = new bug6725409(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + bug6725409.setupUIStep1(); + } + }); + realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + bug6725409.setupUIStep2(); + } + }); + realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + bug6725409.test(); + } + }); + realSync(); + bug6725409.checkResult(); + } finally { + if (bug6725409.frame != null) { + bug6725409.frame.dispose(); + } + } + } + + private void setupUIStep1() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JDesktopPane desktop = new JDesktopPane(); + iFrame = new JInternalFrame("Internal Frame", true, true, true, true); + iFrame.setSize(200, 100); + desktop.add(iFrame); + frame.add(desktop); + iFrame.setVisible(true); + + frame.setSize(500, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private void setupUIStep2() { + UIManager.put("InternalFrameTitlePane.restoreButtonText", + "CUSTOM.restoreButtonText"); + UIManager.put("InternalFrameTitlePane.moveButtonText", + "CUSTOM.moveButtonText"); + UIManager.put("InternalFrameTitlePane.sizeButtonText", + "CUSTOM.sizeButtonText"); + UIManager.put("InternalFrameTitlePane.minimizeButtonText", + "CUSTOM.minimizeButtonText"); + UIManager.put("InternalFrameTitlePane.maximizeButtonText", + "CUSTOM.maximizeButtonText"); + UIManager.put("InternalFrameTitlePane.closeButtonText", + "CUSTOM.closeButtonText"); + SwingUtilities.updateComponentTreeUI(frame); + } + + // The test depends on the order of the menu items in + // WindowsInternalFrameTitlePane.systemPopupMenu + private void test() { + testTitlePane = new TestTitlePane(iFrame); + passed = true; + checkMenuItemText(0, "CUSTOM.restoreButtonText"); + checkMenuItemText(1, "CUSTOM.moveButtonText"); + checkMenuItemText(2, "CUSTOM.sizeButtonText"); + checkMenuItemText(3, "CUSTOM.minimizeButtonText"); + checkMenuItemText(4, "CUSTOM.maximizeButtonText"); + // Skip separator + checkMenuItemText(6, "CUSTOM.closeButtonText"); + } + + private void checkMenuItemText(int index, String text) { + JMenuItem menuItem = (JMenuItem) + testTitlePane.getSystemPopupMenu().getComponent(index); + if (!text.equals(menuItem.getText())) { + passed = false; + } + } + + private void checkResult() { + if (passed) { + System.out.println("Test passed"); + } else { + throw new RuntimeException("Unable to localize " + + "JInternalFrame's system menu during run-time"); + } + } + + private static void realSync() { + ((sun.awt.SunToolkit) (Toolkit.getDefaultToolkit())).realSync(); + } + + // Extend WindowsInternalFrameTitlePane to get access to systemPopupMenu + private class TestTitlePane extends + com.sun.java.swing.plaf.windows.WindowsInternalFrameTitlePane { + private JPopupMenu systemPopupMenu; + + public TestTitlePane(JInternalFrame f) { + super(f); + } + + public JPopupMenu getSystemPopupMenu() { + return systemPopupMenu; + } + + protected void addSystemMenuItems(JPopupMenu menu) { + super.addSystemMenuItems(menu); + systemPopupMenu = menu; + } + } +} From 02a6cd79141120a36b79ee2e64c72b11f8269ab8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 24 Jul 2008 14:51:13 +0400 Subject: [PATCH 028/289] 4778988: CompoundBorder.isBorderOpaque() has incorrect documentation Reviewed-by: peterz, rupashka --- .../share/classes/javax/swing/border/CompoundBorder.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/border/CompoundBorder.java b/jdk/src/share/classes/javax/swing/border/CompoundBorder.java index f736cf90278..46ac44e50c0 100644 --- a/jdk/src/share/classes/javax/swing/border/CompoundBorder.java +++ b/jdk/src/share/classes/javax/swing/border/CompoundBorder.java @@ -79,10 +79,13 @@ public class CompoundBorder extends AbstractBorder { } /** - * Returns whether or not this compound border is opaque. - * Returns true if both the inside and outside borders are - * non-null and opaque; returns false otherwise. + * Returns whether or not the compound border is opaque. + * + * @return {@code true} if the inside and outside borders + * are each either {@code null} or opaque; + * or {@code false} otherwise */ + @Override public boolean isBorderOpaque() { return (outsideBorder == null || outsideBorder.isBorderOpaque()) && (insideBorder == null || insideBorder.isBorderOpaque()); From 8ad3454b18021915cf22eacd3a87ede111620cb6 Mon Sep 17 00:00:00 2001 From: Florian Brunner Date: Thu, 24 Jul 2008 16:43:36 +0400 Subject: [PATCH 029/289] 6722802: Code improvement and warnings removing from the javax.swing.text package Removed unnecessary castings and other warnings Reviewed-by: peterz --- .../javax/swing/text/AbstractDocument.java | 29 +++-- .../javax/swing/text/AsyncBoxView.java | 12 +-- .../javax/swing/text/ComponentView.java | 5 +- .../javax/swing/text/DefaultCaret.java | 5 +- .../javax/swing/text/DefaultFormatter.java | 4 +- .../javax/swing/text/DefaultHighlighter.java | 20 ++-- .../swing/text/DefaultStyledDocument.java | 97 ++++++++--------- .../javax/swing/text/ElementIterator.java | 20 ++-- .../classes/javax/swing/text/FlowView.java | 6 +- .../classes/javax/swing/text/GapContent.java | 14 +-- .../swing/text/InternationalFormatter.java | 9 +- .../javax/swing/text/JTextComponent.java | 73 ++++++------- .../classes/javax/swing/text/LayoutQueue.java | 6 +- .../javax/swing/text/MaskFormatter.java | 6 +- .../javax/swing/text/NumberFormatter.java | 18 +--- .../javax/swing/text/PlainDocument.java | 4 +- .../javax/swing/text/SegmentCache.java | 6 +- .../javax/swing/text/SimpleAttributeSet.java | 6 +- .../javax/swing/text/StringContent.java | 10 +- .../javax/swing/text/StyleContext.java | 38 +++---- .../classes/javax/swing/text/TableView.java | 11 +- .../classes/javax/swing/text/TextAction.java | 8 +- .../javax/swing/text/TextLayoutStrategy.java | 12 +-- .../classes/javax/swing/text/ZoneView.java | 10 +- .../javax/swing/text/html/AccessibleHTML.java | 42 ++++---- .../classes/javax/swing/text/html/CSS.java | 71 ++++++------ .../classes/javax/swing/text/html/HTML.java | 18 ++-- .../javax/swing/text/html/HTMLDocument.java | 69 ++++++------ .../javax/swing/text/html/HTMLEditorKit.java | 25 +++-- .../javax/swing/text/html/HTMLWriter.java | 33 +++--- .../classes/javax/swing/text/html/Map.java | 18 ++-- .../swing/text/html/MinimalHTMLWriter.java | 8 +- .../swing/text/html/OptionListModel.java | 9 +- .../javax/swing/text/html/StyleSheet.java | 102 +++++++++--------- .../javax/swing/text/html/TableView.java | 10 +- .../swing/text/html/parser/AttributeList.java | 2 +- .../javax/swing/text/html/parser/DTD.java | 28 +++-- .../javax/swing/text/html/parser/Element.java | 4 +- .../javax/swing/text/html/parser/Entity.java | 4 +- .../javax/swing/text/html/parser/Parser.java | 14 ++- .../swing/text/html/parser/TagStack.java | 16 --- .../swing/text/rtf/MockAttributeSet.java | 2 +- .../javax/swing/text/rtf/RTFAttributes.java | 13 ++- .../javax/swing/text/rtf/RTFGenerator.java | 42 ++++---- .../javax/swing/text/rtf/RTFParser.java | 2 +- .../javax/swing/text/rtf/RTFReader.java | 102 +++++++++--------- 46 files changed, 499 insertions(+), 564 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/text/AbstractDocument.java b/jdk/src/share/classes/javax/swing/text/AbstractDocument.java index 406350a9b10..a5cbdc2396c 100644 --- a/jdk/src/share/classes/javax/swing/text/AbstractDocument.java +++ b/jdk/src/share/classes/javax/swing/text/AbstractDocument.java @@ -123,15 +123,15 @@ public abstract class AbstractDocument implements Document, Serializable { if (defaultI18NProperty == null) { // determine default setting for i18n support - Object o = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { + String o = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public String run() { return System.getProperty(I18NProperty); } } ); if (o != null) { - defaultI18NProperty = Boolean.valueOf((String)o); + defaultI18NProperty = Boolean.valueOf(o); } else { defaultI18NProperty = Boolean.FALSE; } @@ -163,7 +163,7 @@ public abstract class AbstractDocument implements Document, Serializable { */ public Dictionary getDocumentProperties() { if (documentProperties == null) { - documentProperties = new Hashtable(2); + documentProperties = new Hashtable(2); } return documentProperties; } @@ -467,8 +467,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @since 1.4 */ public DocumentListener[] getDocumentListeners() { - return (DocumentListener[])listenerList.getListeners( - DocumentListener.class); + return listenerList.getListeners(DocumentListener.class); } /** @@ -508,8 +507,7 @@ public abstract class AbstractDocument implements Document, Serializable { * @since 1.4 */ public UndoableEditListener[] getUndoableEditListeners() { - return (UndoableEditListener[])listenerList.getListeners( - UndoableEditListener.class); + return listenerList.getListeners(UndoableEditListener.class); } /** @@ -610,7 +608,7 @@ public abstract class AbstractDocument implements Document, Serializable { DefaultDocumentEvent chng = new DefaultDocumentEvent(offs, len, DocumentEvent.EventType.REMOVE); - boolean isComposedTextElement = false; + boolean isComposedTextElement; // Check whether the position of interest is the composed text isComposedTextElement = Utilities.isComposedTextElement(this, offs); @@ -1051,7 +1049,7 @@ public abstract class AbstractDocument implements Document, Serializable { byte levels[] = calculateBidiLevels( firstPStart, lastPEnd ); - Vector newElements = new Vector(); + Vector newElements = new Vector(); // Calculate the first span of characters in the affected range with // the same bidi level. If this level is the same as the level of the @@ -1831,7 +1829,6 @@ public abstract class AbstractDocument implements Document, Serializable { } out.println("["+contentStr+"]"); } catch (BadLocationException e) { - ; } } else { @@ -2460,7 +2457,7 @@ public abstract class AbstractDocument implements Document, Serializable { if(nchildren == 0) return null; - Vector tempVector = new Vector(nchildren); + Vector tempVector = new Vector(nchildren); for(int counter = 0; counter < nchildren; counter++) tempVector.addElement(children[counter]); @@ -2749,7 +2746,7 @@ public abstract class AbstractDocument implements Document, Serializable { // if the number of changes gets too great, start using // a hashtable for to locate the change for a given element. if ((changeLookup == null) && (edits.size() > 10)) { - changeLookup = new Hashtable(); + changeLookup = new Hashtable(); int n = edits.size(); for (int i = 0; i < n; i++) { Object o = edits.elementAt(i); @@ -2918,7 +2915,7 @@ public abstract class AbstractDocument implements Document, Serializable { */ public DocumentEvent.ElementChange getChange(Element elem) { if (changeLookup != null) { - return (DocumentEvent.ElementChange) changeLookup.get(elem); + return changeLookup.get(elem); } int n = edits.size(); for (int i = 0; i < n; i++) { @@ -2937,7 +2934,7 @@ public abstract class AbstractDocument implements Document, Serializable { private int offset; private int length; - private Hashtable changeLookup; + private Hashtable changeLookup; private DocumentEvent.EventType type; } diff --git a/jdk/src/share/classes/javax/swing/text/AsyncBoxView.java b/jdk/src/share/classes/javax/swing/text/AsyncBoxView.java index 54a0e973553..ae11bde8122 100644 --- a/jdk/src/share/classes/javax/swing/text/AsyncBoxView.java +++ b/jdk/src/share/classes/javax/swing/text/AsyncBoxView.java @@ -25,6 +25,7 @@ package javax.swing.text; import java.util.*; +import java.util.List; import java.awt.*; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; @@ -58,7 +59,7 @@ public class AsyncBoxView extends View { */ public AsyncBoxView(Element elem, int axis) { super(elem); - stats = new ArrayList(); + stats = new ArrayList(); this.axis = axis; locator = new ChildLocator(); flushTask = new FlushTask(); @@ -197,7 +198,7 @@ public class AsyncBoxView extends View { protected ChildState getChildState(int index) { synchronized(stats) { if ((index >= 0) && (index < stats.size())) { - return (ChildState) stats.get(index); + return stats.get(index); } return null; } @@ -357,7 +358,7 @@ public class AsyncBoxView extends View { synchronized(stats) { // remove the replaced state records for (int i = 0; i < length; i++) { - ChildState cs = (ChildState)stats.remove(offset); + ChildState cs = stats.remove(offset); float csSpan = cs.getMajorSpan(); cs.getChildView().setParent(null); @@ -863,7 +864,7 @@ public class AsyncBoxView extends View { /** * The children and their layout statistics. */ - java.util.List stats; + List stats; /** * Current span along the major axis. This @@ -1110,7 +1111,7 @@ public class AsyncBoxView extends View { */ int updateChildOffsets(float targetOffset) { int n = getViewCount(); - int targetIndex = n - 1;; + int targetIndex = n - 1; int pos = lastValidOffset.getChildView().getStartOffset(); int startIndex = getViewIndex(pos, Position.Bias.Forward); float start = lastValidOffset.getMajorOffset(); @@ -1394,7 +1395,6 @@ public class AsyncBoxView extends View { private float min; private float pref; private float max; - private float align; private boolean minorValid; // major axis diff --git a/jdk/src/share/classes/javax/swing/text/ComponentView.java b/jdk/src/share/classes/javax/swing/text/ComponentView.java index 62e4bd02acb..085d999675d 100644 --- a/jdk/src/share/classes/javax/swing/text/ComponentView.java +++ b/jdk/src/share/classes/javax/swing/text/ComponentView.java @@ -27,6 +27,7 @@ package javax.swing.text; import java.awt.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Set; import javax.swing.SwingUtilities; import javax.swing.event.*; @@ -434,7 +435,7 @@ public class ComponentView extends View { /** * Shows or hides this component depending on the value of parameter * b. - * @param b If true, shows this component; + * @param b If true, shows this component; * otherwise, hides this component. * @see #isVisible * @since JDK1.1 @@ -480,7 +481,7 @@ public class ComponentView extends View { return yalign; } - public java.util.Set getFocusTraversalKeys(int id) { + public Set getFocusTraversalKeys(int id) { return KeyboardFocusManager.getCurrentKeyboardFocusManager(). getDefaultFocusTraversalKeys(id); } diff --git a/jdk/src/share/classes/javax/swing/text/DefaultCaret.java b/jdk/src/share/classes/javax/swing/text/DefaultCaret.java index 22ec280ba09..e0e15681188 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultCaret.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultCaret.java @@ -774,8 +774,7 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou * @since 1.4 */ public ChangeListener[] getChangeListeners() { - return (ChangeListener[])listenerList.getListeners( - ChangeListener.class); + return listenerList.getListeners(ChangeListener.class); } /** @@ -1330,7 +1329,7 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou if (this.dot != this.mark && component != null) { Clipboard clip = getSystemSelection(); if (clip != null) { - String selectedText = null; + String selectedText; if (component instanceof JPasswordField && component.getClientProperty("JPasswordField.cutCopyAllowed") != Boolean.TRUE) { diff --git a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java index 79419047273..51dab601ca1 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java @@ -68,7 +68,7 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter private boolean commitOnEdit; /** Class used to create new instances. */ - private Class valueClass; + private Class valueClass; /** NavigationFilter that forwards calls back to DefaultFormatter. */ private NavigationFilter navigationFilter; @@ -231,7 +231,7 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter * @return Object representation of text */ public Object stringToValue(String string) throws ParseException { - Class vc = getValueClass(); + Class vc = getValueClass(); JFormattedTextField ftf = getFormattedTextField(); if (vc == null && ftf != null) { diff --git a/jdk/src/share/classes/javax/swing/text/DefaultHighlighter.java b/jdk/src/share/classes/javax/swing/text/DefaultHighlighter.java index 9e3202130d3..028b24c0ea6 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultHighlighter.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultHighlighter.java @@ -56,7 +56,7 @@ public class DefaultHighlighter extends LayeredHighlighter { // PENDING(prinz) - should cull ranges not visible int len = highlights.size(); for (int i = 0; i < len; i++) { - HighlightInfo info = (HighlightInfo) highlights.elementAt(i); + HighlightInfo info = highlights.elementAt(i); if (!(info instanceof LayeredHighlightInfo)) { // Avoid allocing unless we need it. Rectangle a = component.getBounds(); @@ -66,7 +66,7 @@ public class DefaultHighlighter extends LayeredHighlighter { a.width -= insets.left + insets.right; a.height -= insets.top + insets.bottom; for (; i < len; i++) { - info = (HighlightInfo)highlights.elementAt(i); + info = highlights.elementAt(i); if (!(info instanceof LayeredHighlightInfo)) { Highlighter.HighlightPainter p = info.getPainter(); p.paint(g, info.getStartOffset(), info.getEndOffset(), @@ -159,7 +159,7 @@ public class DefaultHighlighter extends LayeredHighlighter { int p0 = -1; int p1 = -1; for (int i = 0; i < len; i++) { - HighlightInfo hi = (HighlightInfo)highlights.elementAt(i); + HighlightInfo hi = highlights.elementAt(i); if (hi instanceof LayeredHighlightInfo) { LayeredHighlightInfo info = (LayeredHighlightInfo)hi; minX = Math.min(minX, info.x); @@ -195,7 +195,7 @@ public class DefaultHighlighter extends LayeredHighlighter { int p0 = Integer.MAX_VALUE; int p1 = 0; for (int i = 0; i < len; i++) { - HighlightInfo info = (HighlightInfo) highlights.elementAt(i); + HighlightInfo info = highlights.elementAt(i); p0 = Math.min(p0, info.p0.getOffset()); p1 = Math.max(p1, info.p1.getOffset()); } @@ -282,7 +282,7 @@ public class DefaultHighlighter extends LayeredHighlighter { Shape viewBounds, JTextComponent editor, View view) { for (int counter = highlights.size() - 1; counter >= 0; counter--) { - Object tag = highlights.elementAt(counter); + HighlightInfo tag = highlights.elementAt(counter); if (tag instanceof LayeredHighlightInfo) { LayeredHighlightInfo lhi = (LayeredHighlightInfo)tag; int start = lhi.getStartOffset(); @@ -333,7 +333,7 @@ public class DefaultHighlighter extends LayeredHighlighter { private final static Highlighter.Highlight[] noHighlights = new Highlighter.Highlight[0]; - private Vector highlights = new Vector(); // Vector + private Vector highlights = new Vector(); private JTextComponent component; private boolean drawsLayeredHighlights; private SafeDamager safeDamager = new SafeDamager(); @@ -573,8 +573,8 @@ public class DefaultHighlighter extends LayeredHighlighter { * call. */ class SafeDamager implements Runnable { - private Vector p0 = new Vector(10); - private Vector p1 = new Vector(10); + private Vector p0 = new Vector(10); + private Vector p1 = new Vector(10); private Document lastDoc = null; /** @@ -589,8 +589,8 @@ public class DefaultHighlighter extends LayeredHighlighter { int len = p0.size(); for (int i = 0; i < len; i++){ mapper.damageRange(component, - ((Position)p0.get(i)).getOffset(), - ((Position)p1.get(i)).getOffset()); + p0.get(i).getOffset(), + p1.get(i).getOffset()); } } } diff --git a/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java b/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java index 4939a7615c3..d3ba5d98df8 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultStyledDocument.java @@ -84,7 +84,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc */ public DefaultStyledDocument(Content c, StyleContext styles) { super(c, styles); - listeningStyles = new Vector(); + listeningStyles = new Vector is received. */ - private java.util.List _stateInfos; + private List _stateInfos; /** * Current style. @@ -151,7 +152,7 @@ class SynthParser extends HandlerBase { /** * Bindings for the current InputMap */ - private java.util.List _inputMapBindings; + private List _inputMapBindings; /** * ID for the input map. This is cached as @@ -177,30 +178,30 @@ class SynthParser extends HandlerBase { /** * List of ColorTypes. This is populated in startColorType. */ - private java.util.List _colorTypes; + private List _colorTypes; /** * defaultsPropertys are placed here. */ - private Map _defaultsMap; + private Map _defaultsMap; /** * List of SynthStyle.Painters that will be applied to the current style. */ - private java.util.List _stylePainters; + private List _stylePainters; /** * List of SynthStyle.Painters that will be applied to the current state. */ - private java.util.List _statePainters; + private List _statePainters; SynthParser() { _mapping = new HashMap(); - _stateInfos = new ArrayList(); - _colorTypes = new ArrayList(); - _inputMapBindings = new ArrayList(); - _stylePainters = new ArrayList(); - _statePainters = new ArrayList(); + _stateInfos = new ArrayList(); + _colorTypes = new ArrayList(); + _inputMapBindings = new ArrayList(); + _stylePainters = new ArrayList(); + _statePainters = new ArrayList(); } /** @@ -219,7 +220,7 @@ class SynthParser extends HandlerBase { public void parse(InputStream inputStream, DefaultSynthStyleFactory factory, URL urlResourceBase, Class classResourceBase, - Map defaultsMap) + Map defaultsMap) throws ParseException, IllegalArgumentException { if (inputStream == null || factory == null || (urlResourceBase == null && classResourceBase == null)) { @@ -333,7 +334,7 @@ class SynthParser extends HandlerBase { * type type, this will throw an exception. */ private Object lookup(String key, Class type) throws SAXException { - Object value = null; + Object value; if (_handler != null) { if ((value = _handler.lookup(key)) != null) { return checkCast(value, type); @@ -423,15 +424,12 @@ class SynthParser extends HandlerBase { private void endStyle() throws SAXException { int size = _stylePainters.size(); if (size > 0) { - _style.setPainters((ParsedSynthStyle.PainterInfo[]) - _stylePainters.toArray(new ParsedSynthStyle. - PainterInfo[size])); + _style.setPainters(_stylePainters.toArray(new ParsedSynthStyle.PainterInfo[size])); _stylePainters.clear(); } size = _stateInfos.size(); if (size > 0) { - _style.setStateInfo((ParsedSynthStyle.StateInfo[])_stateInfos. - toArray(new ParsedSynthStyle.StateInfo[size])); + _style.setStateInfo(_stateInfos.toArray(new ParsedSynthStyle.StateInfo[size])); _stateInfos.clear(); } _style = null; @@ -501,9 +499,7 @@ class SynthParser extends HandlerBase { private void endState() throws SAXException { int size = _statePainters.size(); if (size > 0) { - _stateInfo.setPainters((ParsedSynthStyle.PainterInfo[]) - _statePainters.toArray(new ParsedSynthStyle. - PainterInfo[size])); + _stateInfo.setPainters(_statePainters.toArray(new ParsedSynthStyle.PainterInfo[size])); _statePainters.clear(); } _stateInfo = null; @@ -684,8 +680,7 @@ class SynthParser extends HandlerBase { int max = 0; for (int counter = _colorTypes.size() - 1; counter >= 0; counter--) { - max = Math.max(max, ((ColorType)_colorTypes.get(counter)). - getID()); + max = Math.max(max, _colorTypes.get(counter).getID()); } if (colors == null || colors.length <= max) { Color[] newColors = new Color[max + 1]; @@ -696,7 +691,7 @@ class SynthParser extends HandlerBase { } for (int counter = _colorTypes.size() - 1; counter >= 0; counter--) { - colors[((ColorType)_colorTypes.get(counter)).getID()] = color; + colors[_colorTypes.get(counter).getID()] = color; } _stateInfo.setColors(colors); } @@ -705,7 +700,7 @@ class SynthParser extends HandlerBase { private void startProperty(AttributeList attributes, Object property) throws SAXException { Object value = null; - Object key = null; + String key = null; // Type of the value: 0=idref, 1=boolean, 2=dimension, 3=insets, // 4=integer,5=string int iType = 0; @@ -1027,7 +1022,7 @@ class SynthParser extends HandlerBase { } } - private void addPainterOrMerge(java.util.List painters, String method, + private void addPainterOrMerge(List painters, String method, SynthPainter painter, int direction) { ParsedSynthStyle.PainterInfo painterInfo; painterInfo = new ParsedSynthStyle.PainterInfo(method, diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java index ddbc7ae7e69..21466d96093 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java @@ -48,13 +48,13 @@ class SynthSplitPaneUI extends BasicSplitPaneUI implements * Keys to use for forward focus traversal when the JComponent is * managing focus. */ - private static Set managingFocusForwardTraversalKeys; + private static Set managingFocusForwardTraversalKeys; /** * Keys to use for backward focus traversal when the JComponent is * managing focus. */ - private static Set managingFocusBackwardTraversalKeys; + private static Set managingFocusBackwardTraversalKeys; /** * Style for the JSplitPane. @@ -96,7 +96,7 @@ class SynthSplitPaneUI extends BasicSplitPaneUI implements // focus forward traversal key if (managingFocusForwardTraversalKeys==null) { - managingFocusForwardTraversalKeys = new HashSet(); + managingFocusForwardTraversalKeys = new HashSet(); managingFocusForwardTraversalKeys.add( KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0)); } @@ -104,7 +104,7 @@ class SynthSplitPaneUI extends BasicSplitPaneUI implements managingFocusForwardTraversalKeys); // focus backward traversal key if (managingFocusBackwardTraversalKeys==null) { - managingFocusBackwardTraversalKeys = new HashSet(); + managingFocusBackwardTraversalKeys = new HashSet(); managingFocusBackwardTraversalKeys.add( KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK)); } diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthStyle.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthStyle.java index c9475f91b54..ab9e42b41e5 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthStyle.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthStyle.java @@ -53,7 +53,7 @@ public abstract class SynthStyle { /** * Contains the default values for certain properties. */ - private static Map DEFAULT_VALUES; + private static Map DEFAULT_VALUES; /** * Shared SynthGraphics. @@ -715,7 +715,7 @@ public abstract class SynthStyle { private static Object getDefaultValue(Object key) { synchronized(SynthStyle.class) { if (DEFAULT_VALUES == null) { - DEFAULT_VALUES = new HashMap(); + DEFAULT_VALUES = new HashMap(); populateDefaultValues(); } Object value = DEFAULT_VALUES.get(key); diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java index f52d3a68b0d..d07c4d5ad88 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java @@ -66,7 +66,7 @@ class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI { protected void installDefaults() { // Installs the text cursor on the component super.installDefaults(); - updateStyle((JTextComponent)getComponent()); + updateStyle(getComponent()); } protected void uninstallDefaults() { diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java index 5b7cbd0a5f5..28bbdf843c4 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java @@ -232,7 +232,7 @@ class SynthTextFieldUI protected void installDefaults() { // Installs the text cursor on the component super.installDefaults(); - updateStyle((JTextComponent)getComponent()); + updateStyle(getComponent()); getComponent().addFocusListener(this); } diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java index 1e12a820ece..464b947b071 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java @@ -390,7 +390,7 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, } private Rectangle getDropLineRect(JTree.DropLocation loc) { - Rectangle rect = null; + Rectangle rect; TreePath path = loc.getPath(); int index = loc.getChildIndex(); boolean ltr = tree.getComponentOrientation().isLeftToRight(); @@ -523,7 +523,7 @@ class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, // Don't paint the renderer if editing this row. boolean selected = tree.isRowSelected(row); - JTree.DropLocation dropLocation = (JTree.DropLocation)tree.getDropLocation(); + JTree.DropLocation dropLocation = tree.getDropLocation(); boolean isDrop = dropLocation != null && dropLocation.getChildIndex() == -1 && path == dropLocation.getPath(); diff --git a/jdk/src/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java b/jdk/src/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java index de209df68eb..f66692e5778 100644 --- a/jdk/src/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java +++ b/jdk/src/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java @@ -44,7 +44,7 @@ import javax.swing.plaf.*; * @author Scott Violet */ public class DefaultSynthStyle extends SynthStyle implements Cloneable { - private static final Object PENDING = new String("Pending"); + private static final String PENDING = "Pending"; /** * Should the component be opaque? @@ -690,8 +690,8 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { StateInfo[] states = getStateInfo(); if (states != null) { buf.append("states["); - for (int i = 0; i < states.length; i++) { - buf.append(states[i].toString()).append(','); + for (StateInfo state : states) { + buf.append(state.toString()).append(','); } buf.append(']').append(','); } @@ -888,7 +888,7 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { * Returns the number of states that are similar between the * ComponentState this StateInfo represents and val. */ - private final int getMatchCount(int val) { + private int getMatchCount(int val) { // This comes from BigInteger.bitCnt val &= state; val -= (0xaaaaaaaa & val) >>> 1; diff --git a/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java b/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java index abd99439ed0..2721764d1d7 100644 --- a/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java +++ b/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java @@ -735,7 +735,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { * Data model for a type-face selection combo-box. */ protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { - Vector directories = new Vector(); + Vector directories = new Vector(); int[] depths = null; File selectedDirectory = null; JFileChooser chooser = getFileChooser(); @@ -778,7 +778,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { // Get the canonical (full) path. This has the side // benefit of removing extraneous chars from the path, // for example /foo/bar/ becomes /foo/bar - File canonical = null; + File canonical; try { canonical = directory.getCanonicalFile(); } catch (IOException e) { @@ -791,7 +791,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { File sf = useShellFolder ? ShellFolder.getShellFolder(canonical) : canonical; File f = sf; - Vector path = new Vector(10); + Vector path = new Vector(10); do { path.addElement(f); } while ((f = f.getParentFile()) != null); @@ -799,7 +799,7 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { int pathCount = path.size(); // Insert chain at appropriate place in vector for (int i = 0; i < pathCount; i++) { - f = (File)path.get(i); + f = path.get(i); if (directories.contains(f)) { int topIndex = directories.indexOf(f); for (int j = i-1; j >= 0; j--) { @@ -818,12 +818,12 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { private void calculateDepths() { depths = new int[directories.size()]; for (int i = 0; i < depths.length; i++) { - File dir = (File)directories.get(i); + File dir = directories.get(i); File parent = dir.getParentFile(); depths[i] = 0; if (parent != null) { for (int j = i-1; j >= 0; j--) { - if (parent.equals((File)directories.get(j))) { + if (parent.equals(directories.get(j))) { depths[i] = depths[j] + 1; break; } @@ -940,8 +940,8 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { FileFilter currentFilter = getFileChooser().getFileFilter(); boolean found = false; if(currentFilter != null) { - for(int i=0; i < filters.length; i++) { - if(filters[i] == currentFilter) { + for (FileFilter filter : filters) { + if (filter == currentFilter) { found = true; } } From f7be937495c26e171cca46739ba26ac275468eb6 Mon Sep 17 00:00:00 2001 From: Igor Kushnirskiy Date: Fri, 25 Jul 2008 11:32:12 -0400 Subject: [PATCH 036/289] 6608456: need API to define RepaintManager per components hierarchy Reviewed-by: alexp --- jdk/make/javax/swing/Makefile | 2 +- .../com/sun/java/swing/SwingUtilities3.java | 91 ++++++++++ .../classes/javax/swing/RepaintManager.java | 51 ++++++ .../RepaintManager/6608456/bug6608456.java | 162 ++++++++++++++++++ 4 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java create mode 100644 jdk/test/javax/swing/RepaintManager/6608456/bug6608456.java diff --git a/jdk/make/javax/swing/Makefile b/jdk/make/javax/swing/Makefile index c2056a45ce2..e112e609cd9 100644 --- a/jdk/make/javax/swing/Makefile +++ b/jdk/make/javax/swing/Makefile @@ -33,7 +33,7 @@ include $(BUILDDIR)/common/Defs.gmk # Files # include FILES.gmk -AUTO_FILES_JAVA_DIRS = javax/swing sun/swing +AUTO_FILES_JAVA_DIRS = javax/swing sun/swing com/sun/java/swing AUTO_JAVA_PRUNE = plaf SUBDIRS = html32dtd plaf diff --git a/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java b/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java new file mode 100644 index 00000000000..2ace1e4ce77 --- /dev/null +++ b/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java @@ -0,0 +1,91 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.java.swing; + +import sun.awt.AppContext; +import java.awt.Component; +import javax.swing.JComponent; +import javax.swing.RepaintManager; + +/** + * A collection of utility methods for Swing. + *

+ * WARNING: While this class is public, it should not be treated as + * public API and its API may change in incompatable ways between dot dot + * releases and even patch releases. You should not rely on this class even + * existing. + * + * This is a second part of sun.swing.SwingUtilities2. It is required + * to provide services for JavaFX applets. + * + */ +public class SwingUtilities3 { + /** + * The {@code clientProperty} key for delegate {@code RepaintManager} + */ + private static final Object DELEGATE_REPAINT_MANAGER_KEY = + new StringBuilder("DelegateRepaintManagerKey"); + + /** + * Registers delegate RepaintManager for {@code JComponent}. + */ + public static void setDelegateRepaintManager(JComponent component, + RepaintManager repaintManager) { + /* setting up flag in AppContext to speed up lookups in case + * there are no delegate RepaintManagers used. + */ + AppContext.getAppContext().put(DELEGATE_REPAINT_MANAGER_KEY, + Boolean.TRUE); + + component.putClientProperty(DELEGATE_REPAINT_MANAGER_KEY, + repaintManager); + } + + /** + * Returns delegate {@code RepaintManager} for {@code component} hierarchy. + */ + public static RepaintManager getDelegateRepaintManager(Component + component) { + RepaintManager delegate = null; + if (Boolean.TRUE == AppContext.getAppContext().get( + DELEGATE_REPAINT_MANAGER_KEY)) { + while (delegate == null && component != null) { + while (component != null + && ! (component instanceof JComponent)) { + component = component.getParent(); + } + if (component != null) { + delegate = (RepaintManager) + ((JComponent) component) + .getClientProperty(DELEGATE_REPAINT_MANAGER_KEY); + component = component.getParent(); + } + + } + } + return delegate; + } +} diff --git a/jdk/src/share/classes/javax/swing/RepaintManager.java b/jdk/src/share/classes/javax/swing/RepaintManager.java index 91034dbf8f2..81c81602255 100644 --- a/jdk/src/share/classes/javax/swing/RepaintManager.java +++ b/jdk/src/share/classes/javax/swing/RepaintManager.java @@ -40,6 +40,8 @@ import sun.awt.SunToolkit; import sun.java2d.SunGraphicsEnvironment; import sun.security.action.GetPropertyAction; +import com.sun.java.swing.SwingUtilities3; + /** * This class manages repaint requests, allowing the number @@ -303,6 +305,11 @@ public class RepaintManager */ public synchronized void addInvalidComponent(JComponent invalidComponent) { + RepaintManager delegate = getDelegate(invalidComponent); + if (delegate != null) { + delegate.addInvalidComponent(invalidComponent); + return; + } Component validateRoot = null; /* Find the first JComponent ancestor of this component whose @@ -373,6 +380,11 @@ public class RepaintManager * @see #addInvalidComponent */ public synchronized void removeInvalidComponent(JComponent component) { + RepaintManager delegate = getDelegate(component); + if (delegate != null) { + delegate.removeInvalidComponent(component); + return; + } if(invalidComponents != null) { int index = invalidComponents.indexOf(component); if(index != -1) { @@ -464,6 +476,11 @@ public class RepaintManager */ public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { + RepaintManager delegate = getDelegate(c); + if (delegate != null) { + delegate.addDirtyRegion(c, x, y, w, h); + return; + } addDirtyRegion0(c, x, y, w, h); } @@ -588,6 +605,10 @@ public class RepaintManager * dirty. */ public Rectangle getDirtyRegion(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + return delegate.getDirtyRegion(aComponent); + } Rectangle r = null; synchronized(this) { r = (Rectangle)dirtyComponents.get(aComponent); @@ -603,6 +624,11 @@ public class RepaintManager * completely painted during the next paintDirtyRegions() call. */ public void markCompletelyDirty(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + delegate.markCompletelyDirty(aComponent); + return; + } addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE); } @@ -611,6 +637,11 @@ public class RepaintManager * get painted during the next paintDirtyRegions() call. */ public void markCompletelyClean(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + delegate.markCompletelyClean(aComponent); + return; + } synchronized(this) { dirtyComponents.remove(aComponent); } @@ -623,6 +654,10 @@ public class RepaintManager * if it return true. */ public boolean isCompletelyDirty(JComponent aComponent) { + RepaintManager delegate = getDelegate(aComponent); + if (delegate != null) { + return delegate.isCompletelyDirty(aComponent); + } Rectangle r; r = getDirtyRegion(aComponent); @@ -900,6 +935,10 @@ public class RepaintManager * repaint manager. */ public Image getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) { + RepaintManager delegate = getDelegate(c); + if (delegate != null) { + return delegate.getOffscreenBuffer(c, proposedWidth, proposedHeight); + } return _getOffscreenBuffer(c, proposedWidth, proposedHeight); } @@ -917,6 +956,11 @@ public class RepaintManager */ public Image getVolatileOffscreenBuffer(Component c, int proposedWidth,int proposedHeight) { + RepaintManager delegate = getDelegate(c); + if (delegate != null) { + return delegate.getVolatileOffscreenBuffer(c, proposedWidth, + proposedHeight); + } GraphicsConfiguration config = c.getGraphicsConfiguration(); if (config == null) { config = GraphicsEnvironment.getLocalGraphicsEnvironment(). @@ -1550,4 +1594,11 @@ public class RepaintManager prePaintDirtyRegions(); } } + private RepaintManager getDelegate(Component c) { + RepaintManager delegate = SwingUtilities3.getDelegateRepaintManager(c); + if (this == delegate) { + delegate = null; + } + return delegate; + } } diff --git a/jdk/test/javax/swing/RepaintManager/6608456/bug6608456.java b/jdk/test/javax/swing/RepaintManager/6608456/bug6608456.java new file mode 100644 index 00000000000..1d8a14fcaa2 --- /dev/null +++ b/jdk/test/javax/swing/RepaintManager/6608456/bug6608456.java @@ -0,0 +1,162 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * + * @bug 6608456 + * @author Igor Kushnirskiy + * @summary tests if delegate RepaintManager gets invoked. + */ + +import java.awt.*; +import java.lang.reflect.Method; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +import javax.swing.JComponent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.RepaintManager; +import javax.swing.SwingUtilities; + + + +public class bug6608456 { + private static final TestFuture testFuture = new TestFuture(); + public static void main(String[] args) throws Exception { + final JComponent component = invokeAndWait( + new Callable() { + public JComponent call() throws Exception { + RepaintManager.setCurrentManager(new TestRepaintManager()); + JFrame frame = new JFrame("test"); + frame.setLayout(new FlowLayout()); + JButton button = new JButton("default"); + + frame.add(button); + button = new JButton("delegate"); + if ( ! registerDelegate( + button, new TestRepaintManager())) { + return null; + } + frame.add(button); + frame.pack(); + frame.setVisible(true); + return button; + } + }); + if (component == null) { + throw new RuntimeException("failed. can not register delegate"); + } + blockTillDisplayed(component); + // trigger repaint for delegate RepaintManager + invokeAndWait( + new Callable() { + public Void call() { + component.repaint(); + return null; + } + }); + try { + if (testFuture.get(10, TimeUnit.SECONDS)) { + // passed + } + } catch (Exception e) { + throw new RuntimeException("failed", e); + } finally { + JFrame frame = (JFrame) SwingUtilities + .getAncestorOfClass(JFrame.class, component); + if (frame != null) { + frame.dispose(); + } + } + } + static class TestRepaintManager extends RepaintManager { + @Override + public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { + if (RepaintManager.currentManager(c) == this) { + testFuture.defaultCalled(); + } else { + testFuture.delegateCalled(); + } + super.addDirtyRegion(c, x, y, w, h); + } + } + static class TestFuture extends FutureTask { + private volatile boolean defaultCalled = false; + private volatile boolean delegateCalled = false; + public TestFuture() { + super(new Callable() { + public Boolean call() { + return null; + } + }); + } + public void defaultCalled() { + defaultCalled = true; + updateState(); + } + public void delegateCalled() { + delegateCalled = true; + updateState(); + } + private void updateState() { + if (defaultCalled && delegateCalled) { + set(Boolean.TRUE); + } + } + } + + private static boolean registerDelegate(JComponent c, + RepaintManager repaintManager) { + boolean rv = false; + try { + Class clazz = Class.forName("com.sun.java.swing.SwingUtilities3"); + Method method = clazz.getMethod("setDelegateRepaintManager", + JComponent.class, RepaintManager.class); + method.invoke(clazz, c, repaintManager); + rv = true; + } catch (Exception ignore) { + } + return rv; + } + static T invokeAndWait(Callable callable) throws Exception { + FutureTask future = new FutureTask(callable); + SwingUtilities.invokeLater(future); + return future.get(); + } + + public static void blockTillDisplayed(Component comp) { + Point p = null; + while (p == null) { + try { + p = comp.getLocationOnScreen(); + } catch (IllegalStateException e) { + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } + } + } + } +} From 97c80b8c8476d3499583fdeb1d2dd69fc1d15f81 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 25 Jul 2008 09:07:29 -0700 Subject: [PATCH 037/289] 6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089) Reviewed-by: kvn --- hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp | 6 +++--- hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 9d17fce5ff3..058c230282f 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -779,9 +779,9 @@ class StubGenerator: public StubCodeGenerator { __ shrl(end, CardTableModRefBS::card_shift); __ subl(end, start); // end --> count __ BIND(L_loop); - ExternalAddress base((address)ct->byte_map_base); - Address index(start, count, Address::times_1, 0); - __ movbyte(ArrayAddress(base, index), 0); + intptr_t disp = (intptr_t) ct->byte_map_base; + Address cardtable(start, count, Address::times_1, disp); + __ movb(cardtable, 0); __ decrement(count); __ jcc(Assembler::greaterEqual, L_loop); } diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 68188361b50..c3b61d5bf76 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -1222,8 +1222,16 @@ class StubGenerator: public StubCodeGenerator { __ shrq(end, CardTableModRefBS::card_shift); __ subq(end, start); // number of bytes to copy + intptr_t disp = (intptr_t) ct->byte_map_base; + if (__ is_simm32(disp)) { + Address cardtable(noreg, noreg, Address::no_scale, disp); + __ lea(scratch, cardtable); + } else { + ExternalAddress cardtable((address)disp); + __ lea(scratch, cardtable); + } + const Register count = end; // 'end' register contains bytes count now - __ lea(scratch, ExternalAddress((address)ct->byte_map_base)); __ addq(start, scratch); __ BIND(L_loop); __ movb(Address(start, count, Address::times_1), 0); From 873a9176c75501f08faca765df10ef6b4f8879a5 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 25 Jul 2008 21:00:05 +0400 Subject: [PATCH 038/289] 6630275: The spec on VetoableChangeSupport.fireVetoableChange should be updated Reviewed-by: peterz, rupashka --- .../java/beans/PropertyChangeSupport.java | 195 ++++++++-------- .../java/beans/VetoableChangeSupport.java | 215 ++++++++++-------- .../VetoableChangeSupport/Test6630275.java | 81 +++++++ 3 files changed, 293 insertions(+), 198 deletions(-) create mode 100644 jdk/test/java/beans/VetoableChangeSupport/Test6630275.java diff --git a/jdk/src/share/classes/java/beans/PropertyChangeSupport.java b/jdk/src/share/classes/java/beans/PropertyChangeSupport.java index 2d4ed88fdb3..2a3f79ff3f2 100644 --- a/jdk/src/share/classes/java/beans/PropertyChangeSupport.java +++ b/jdk/src/share/classes/java/beans/PropertyChangeSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,91 +208,91 @@ public class PropertyChangeSupport implements Serializable { } /** - * Report a bound property update to any registered listeners. - * No event is fired if old and new are equal and non-null. - * + * Reports a bound property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. + *

+ * No event is fired if old and new values are equal and non-null. *

* This is merely a convenience wrapper around the more general - * firePropertyChange method that takes {@code - * PropertyChangeEvent} value. + * {@link #firePropertyChange(PropertyChangeEvent)} method. * - * @param propertyName The programmatic name of the property - * that was changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that was changed + * @param oldValue the old value of the property + * @param newValue the new value of the property */ - public void firePropertyChange(String propertyName, - Object oldValue, Object newValue) { - if (oldValue != null && newValue != null && oldValue.equals(newValue)) { - return; + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) { + firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue)); } - firePropertyChange(new PropertyChangeEvent(source, propertyName, - oldValue, newValue)); } /** - * Report an int bound property update to any registered listeners. - * No event is fired if old and new are equal. + * Reports an integer bound property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. + *

+ * No event is fired if old and new values are equal. *

* This is merely a convenience wrapper around the more general - * firePropertyChange method that takes Object values. + * {@link #firePropertyChange(String, Object, Object)} method. * - * @param propertyName The programmatic name of the property - * that was changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that was changed + * @param oldValue the old value of the property + * @param newValue the new value of the property */ - public void firePropertyChange(String propertyName, - int oldValue, int newValue) { - if (oldValue == newValue) { - return; + public void firePropertyChange(String propertyName, int oldValue, int newValue) { + if (oldValue != newValue) { + firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue)); } - firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue)); } /** - * Report a boolean bound property update to any registered listeners. - * No event is fired if old and new are equal. + * Reports a boolean bound property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. + *

+ * No event is fired if old and new values are equal. *

* This is merely a convenience wrapper around the more general - * firePropertyChange method that takes Object values. + * {@link #firePropertyChange(String, Object, Object)} method. * - * @param propertyName The programmatic name of the property - * that was changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that was changed + * @param oldValue the old value of the property + * @param newValue the new value of the property */ - public void firePropertyChange(String propertyName, - boolean oldValue, boolean newValue) { - if (oldValue == newValue) { - return; + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { + if (oldValue != newValue) { + firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); } - firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); } /** - * Fire an existing PropertyChangeEvent to any registered listeners. - * No event is fired if the given event's old and new values are - * equal and non-null. - * @param evt The PropertyChangeEvent object. + * Fires a property change event to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. + *

+ * No event is fired if the given event's old and new values are equal and non-null. + * + * @param event the {@code PropertyChangeEvent} to be fired */ - public void firePropertyChange(PropertyChangeEvent evt) { - Object oldValue = evt.getOldValue(); - Object newValue = evt.getNewValue(); - String propertyName = evt.getPropertyName(); - if (oldValue != null && newValue != null && oldValue.equals(newValue)) { - return; - } - PropertyChangeListener[] common = this.map.get(null); - PropertyChangeListener[] named = (propertyName != null) - ? this.map.get(propertyName) - : null; + public void firePropertyChange(PropertyChangeEvent event) { + Object oldValue = event.getOldValue(); + Object newValue = event.getNewValue(); + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) { + String name = event.getPropertyName(); - fire(common, evt); - fire(named, evt); + PropertyChangeListener[] common = this.map.get(null); + PropertyChangeListener[] named = (name != null) + ? this.map.get(name) + : null; + + fire(common, event); + fire(named, event); + } } - private void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) { + private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) { if (listeners != null) { for (PropertyChangeListener listener : listeners) { listener.propertyChange(event); @@ -301,78 +301,69 @@ public class PropertyChangeSupport implements Serializable { } /** - * Report a bound indexed property update to any registered - * listeners. + * Reports a bound indexed property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. *

- * No event is fired if old and new values are equal - * and non-null. - * + * No event is fired if old and new values are equal and non-null. *

* This is merely a convenience wrapper around the more general - * firePropertyChange method that takes {@code PropertyChangeEvent} value. + * {@link #firePropertyChange(PropertyChangeEvent)} method. * - * @param propertyName The programmatic name of the property that - * was changed. - * @param index index of the property element that was changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that was changed + * @param index the index of the property element that was changed + * @param oldValue the old value of the property + * @param newValue the new value of the property * @since 1.5 */ - public void fireIndexedPropertyChange(String propertyName, int index, - Object oldValue, Object newValue) { - firePropertyChange(new IndexedPropertyChangeEvent - (source, propertyName, oldValue, newValue, index)); + public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) { + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) { + firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index)); + } } /** - * Report an int bound indexed property update to any registered - * listeners. + * Reports an integer bound indexed property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. *

* No event is fired if old and new values are equal. *

* This is merely a convenience wrapper around the more general - * fireIndexedPropertyChange method which takes Object values. + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method. * - * @param propertyName The programmatic name of the property that - * was changed. - * @param index index of the property element that was changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that was changed + * @param index the index of the property element that was changed + * @param oldValue the old value of the property + * @param newValue the new value of the property * @since 1.5 */ - public void fireIndexedPropertyChange(String propertyName, int index, - int oldValue, int newValue) { - if (oldValue == newValue) { - return; + public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) { + if (oldValue != newValue) { + fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue)); } - fireIndexedPropertyChange(propertyName, index, - Integer.valueOf(oldValue), - Integer.valueOf(newValue)); } /** - * Report a boolean bound indexed property update to any - * registered listeners. + * Reports a boolean bound indexed property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. *

* No event is fired if old and new values are equal. *

* This is merely a convenience wrapper around the more general - * fireIndexedPropertyChange method which takes Object values. + * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method. * - * @param propertyName The programmatic name of the property that - * was changed. - * @param index index of the property element that was changed. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that was changed + * @param index the index of the property element that was changed + * @param oldValue the old value of the property + * @param newValue the new value of the property * @since 1.5 */ - public void fireIndexedPropertyChange(String propertyName, int index, - boolean oldValue, boolean newValue) { - if (oldValue == newValue) { - return; + public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) { + if (oldValue != newValue) { + fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); } - fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), - Boolean.valueOf(newValue)); } /** diff --git a/jdk/src/share/classes/java/beans/VetoableChangeSupport.java b/jdk/src/share/classes/java/beans/VetoableChangeSupport.java index 7d1418e17d2..f6707b49f7f 100644 --- a/jdk/src/share/classes/java/beans/VetoableChangeSupport.java +++ b/jdk/src/share/classes/java/beans/VetoableChangeSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,126 +208,149 @@ public class VetoableChangeSupport implements Serializable { } /** - * Report a vetoable property update to any registered listeners. If - * anyone vetos the change, then fire a new event reverting everyone to - * the old value and then rethrow the PropertyVetoException. + * Reports a constrained property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. *

- * No event is fired if old and new are equal and non-null. - * - * @param propertyName The programmatic name of the property - * that is about to change.. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. - * @exception PropertyVetoException if the recipient wishes the property - * change to be rolled back. - */ - public void fireVetoableChange(String propertyName, - Object oldValue, Object newValue) - throws PropertyVetoException { - if (oldValue != null && newValue != null && oldValue.equals(newValue)) { - return; - } - PropertyChangeEvent evt = new PropertyChangeEvent(source, propertyName, - oldValue, newValue); - fireVetoableChange(evt); - } - - /** - * Report a int vetoable property update to any registered listeners. - * No event is fired if old and new are equal. + * Any listener can throw a {@code PropertyVetoException} to veto the update. + * If one of the listeners vetoes the update, this method passes + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value + * to all listeners that already confirmed this update + * and throws the {@code PropertyVetoException} again. + *

+ * No event is fired if old and new values are equal and non-null. *

* This is merely a convenience wrapper around the more general - * fireVetoableChange method that takes Object values. + * {@link #fireVetoableChange(PropertyChangeEvent)} method. * - * @param propertyName The programmatic name of the property - * that is about to change. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that is about to change + * @param oldValue the old value of the property + * @param newValue the new value of the property + * @throws PropertyVetoException if one of listeners vetoes the property update */ - public void fireVetoableChange(String propertyName, - int oldValue, int newValue) - throws PropertyVetoException { - if (oldValue == newValue) { - return; + public void fireVetoableChange(String propertyName, Object oldValue, Object newValue) + throws PropertyVetoException { + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) { + fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue)); } - fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue)); } /** - * Report a boolean vetoable property update to any registered listeners. - * No event is fired if old and new are equal. + * Reports an integer constrained property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. + *

+ * Any listener can throw a {@code PropertyVetoException} to veto the update. + * If one of the listeners vetoes the update, this method passes + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value + * to all listeners that already confirmed this update + * and throws the {@code PropertyVetoException} again. + *

+ * No event is fired if old and new values are equal. *

* This is merely a convenience wrapper around the more general - * fireVetoableChange method that takes Object values. + * {@link #fireVetoableChange(String, Object, Object)} method. * - * @param propertyName The programmatic name of the property - * that is about to change. - * @param oldValue The old value of the property. - * @param newValue The new value of the property. + * @param propertyName the programmatic name of the property that is about to change + * @param oldValue the old value of the property + * @param newValue the new value of the property + * @throws PropertyVetoException if one of listeners vetoes the property update */ - public void fireVetoableChange(String propertyName, - boolean oldValue, boolean newValue) - throws PropertyVetoException { - if (oldValue == newValue) { - return; + public void fireVetoableChange(String propertyName, int oldValue, int newValue) + throws PropertyVetoException { + if (oldValue != newValue) { + fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue)); } - fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); } /** - * Fire a vetoable property update to any registered listeners. If - * anyone vetos the change, then fire a new event reverting everyone to - * the old value and then rethrow the PropertyVetoException. + * Reports a boolean constrained property update to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. *

- * No event is fired if old and new are equal and non-null. + * Any listener can throw a {@code PropertyVetoException} to veto the update. + * If one of the listeners vetoes the update, this method passes + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value + * to all listeners that already confirmed this update + * and throws the {@code PropertyVetoException} again. + *

+ * No event is fired if old and new values are equal. + *

+ * This is merely a convenience wrapper around the more general + * {@link #fireVetoableChange(String, Object, Object)} method. * - * @param evt The PropertyChangeEvent to be fired. - * @exception PropertyVetoException if the recipient wishes the property - * change to be rolled back. + * @param propertyName the programmatic name of the property that is about to change + * @param oldValue the old value of the property + * @param newValue the new value of the property + * @throws PropertyVetoException if one of listeners vetoes the property update */ - public void fireVetoableChange(PropertyChangeEvent evt) - throws PropertyVetoException { - - Object oldValue = evt.getOldValue(); - Object newValue = evt.getNewValue(); - String propertyName = evt.getPropertyName(); - if (oldValue != null && newValue != null && oldValue.equals(newValue)) { - return; + public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue) + throws PropertyVetoException { + if (oldValue != newValue) { + fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue)); } - VetoableChangeListener[] common = this.map.get(null); - VetoableChangeListener[] named = (propertyName != null) - ? this.map.get(propertyName) - : null; - fire(common, evt); - fire(named, evt); } - private void fire(VetoableChangeListener[] listeners, PropertyChangeEvent event) throws PropertyVetoException { - if (listeners != null) { - VetoableChangeListener current = null; - try { - for (VetoableChangeListener listener : listeners) { - current = listener; - listener.vetoableChange(event); - } - } catch (PropertyVetoException veto) { - // Create an event to revert everyone to the old value. - event = new PropertyChangeEvent( this.source, - event.getPropertyName(), - event.getNewValue(), - event.getOldValue() ); - for (VetoableChangeListener listener : listeners) { - if (current == listener) { - break; - } - try { - listener.vetoableChange(event); - } catch (PropertyVetoException ex) { - // We just ignore exceptions that occur during reversions. + /** + * Fires a property change event to listeners + * that have been registered to track updates of + * all properties or a property with the specified name. + *

+ * Any listener can throw a {@code PropertyVetoException} to veto the update. + * If one of the listeners vetoes the update, this method passes + * a new "undo" {@code PropertyChangeEvent} that reverts to the old value + * to all listeners that already confirmed this update + * and throws the {@code PropertyVetoException} again. + *

+ * No event is fired if the given event's old and new values are equal and non-null. + * + * @param event the {@code PropertyChangeEvent} to be fired + * @throws PropertyVetoException if one of listeners vetoes the property update + */ + public void fireVetoableChange(PropertyChangeEvent event) + throws PropertyVetoException { + Object oldValue = event.getOldValue(); + Object newValue = event.getNewValue(); + if (oldValue == null || newValue == null || !oldValue.equals(newValue)) { + String name = event.getPropertyName(); + + VetoableChangeListener[] common = this.map.get(null); + VetoableChangeListener[] named = (name != null) + ? this.map.get(name) + : null; + + VetoableChangeListener[] listeners; + if (common == null) { + listeners = named; + } + else if (named == null) { + listeners = common; + } + else { + listeners = new VetoableChangeListener[common.length + named.length]; + System.arraycopy(common, 0, listeners, 0, common.length); + System.arraycopy(named, 0, listeners, common.length, named.length); + } + if (listeners != null) { + int current = 0; + try { + while (current < listeners.length) { + listeners[current].vetoableChange(event); + current++; } } - // And now rethrow the PropertyVetoException. - throw veto; + catch (PropertyVetoException veto) { + event = new PropertyChangeEvent(this.source, name, newValue, oldValue); + for (int i = 0; i < current; i++) { + try { + listeners[i].vetoableChange(event); + } + catch (PropertyVetoException exception) { + // ignore exceptions that occur during rolling back + } + } + throw veto; // rethrow the veto exception + } } } } diff --git a/jdk/test/java/beans/VetoableChangeSupport/Test6630275.java b/jdk/test/java/beans/VetoableChangeSupport/Test6630275.java new file mode 100644 index 00000000000..ce68720d809 --- /dev/null +++ b/jdk/test/java/beans/VetoableChangeSupport/Test6630275.java @@ -0,0 +1,81 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6630275 + * @summary Tests VetoableChangeSupport specification + * @author Sergey Malenkov + */ + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; + +public class Test6630275 { + private static final String PROPERTY = "property"; // NON-NLS: predefined property name + + public static void main(String[] args) { + CheckListener first = new CheckListener(false); + CheckListener second = new CheckListener(true); + CheckListener third = new CheckListener(false); + + VetoableChangeSupport vcs = new VetoableChangeSupport(Test6630275.class); + vcs.addVetoableChangeListener(first); + vcs.addVetoableChangeListener(PROPERTY, first); + vcs.addVetoableChangeListener(PROPERTY, second); + vcs.addVetoableChangeListener(PROPERTY, third); + try { + vcs.fireVetoableChange(PROPERTY, true, false); + } catch (PropertyVetoException exception) { + first.validate(); + second.validate(); + third.validate(); + return; // expected exception + } + throw new Error("exception should be thrown"); + } + + private static class CheckListener implements VetoableChangeListener { + private final boolean veto; + private boolean odd; // even/odd check for notification + + private CheckListener(boolean veto) { + this.veto = veto; + } + + private void validate() { + if (this.veto != this.odd) + throw new Error(this.odd + ? "undo event expected" + : "unexpected undo event"); + } + + public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException { + this.odd = !this.odd; + if (this.veto) + throw new PropertyVetoException("disable all changes", event); + } + } +} From b4ae1216b3d0441294a6485c7f36f8df48340b50 Mon Sep 17 00:00:00 2001 From: Igor Kushnirskiy Date: Fri, 25 Jul 2008 14:13:59 -0400 Subject: [PATCH 039/289] 6638195: need API for EventQueueDelegate Reviewed-by: bchristi --- .../com/sun/java/swing/SwingUtilities3.java | 83 +++++++++++ .../classes/java/awt/EventDispatchThread.java | 20 ++- .../classes/sun/awt/EventQueueDelegate.java | 71 +++++++++ .../awt/EventQueue/6638195/bug6638195.java | 138 ++++++++++++++++++ 4 files changed, 309 insertions(+), 3 deletions(-) create mode 100644 jdk/src/share/classes/sun/awt/EventQueueDelegate.java create mode 100644 jdk/test/java/awt/EventQueue/6638195/bug6638195.java diff --git a/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java b/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java index 2ace1e4ce77..9268d7370a3 100644 --- a/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java +++ b/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java @@ -25,7 +25,12 @@ package com.sun.java.swing; +import sun.awt.EventQueueDelegate; import sun.awt.AppContext; +import java.util.Map; +import java.util.concurrent.Callable; +import java.awt.AWTEvent; +import java.awt.EventQueue; import java.awt.Component; import javax.swing.JComponent; import javax.swing.RepaintManager; @@ -88,4 +93,82 @@ public class SwingUtilities3 { } return delegate; } + + /* + * We use maps to avoid reflection. Hopefully it should perform better + * this way. + */ + public static void setEventQueueDelegate( + Map> map) { + EventQueueDelegate.setDelegate(new EventQueueDelegateFromMap(map)); + } + + private static class EventQueueDelegateFromMap + implements EventQueueDelegate.Delegate { + private final AWTEvent[] afterDispatchEventArgument; + private final Object[] afterDispatchHandleArgument; + private final Callable afterDispatchCallable; + + private final AWTEvent[] beforeDispatchEventArgument; + private final Callable beforeDispatchCallable; + + private final EventQueue[] getNextEventEventQueueArgument; + private final Callable getNextEventCallable; + + @SuppressWarnings("unchecked") + public EventQueueDelegateFromMap(Map> objectMap) { + Map methodMap = objectMap.get("afterDispatch"); + afterDispatchEventArgument = (AWTEvent[]) methodMap.get("event"); + afterDispatchHandleArgument = (Object[]) methodMap.get("handle"); + afterDispatchCallable = (Callable) methodMap.get("method"); + + methodMap = objectMap.get("beforeDispatch"); + beforeDispatchEventArgument = (AWTEvent[]) methodMap.get("event"); + beforeDispatchCallable = (Callable) methodMap.get("method"); + + methodMap = objectMap.get("getNextEvent"); + getNextEventEventQueueArgument = + (EventQueue[]) methodMap.get("eventQueue"); + getNextEventCallable = (Callable) methodMap.get("method"); + } + + @Override + public void afterDispatch(AWTEvent event, Object handle) { + afterDispatchEventArgument[0] = event; + afterDispatchHandleArgument[0] = handle; + try { + afterDispatchCallable.call(); + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + } + } + + @Override + public Object beforeDispatch(AWTEvent event) { + beforeDispatchEventArgument[0] = event; + try { + return beforeDispatchCallable.call(); + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + } + return null; + } + + @Override + public AWTEvent getNextEvent(EventQueue eventQueue) { + getNextEventEventQueueArgument[0] = eventQueue; + try { + return getNextEventCallable.call(); + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + } + return null; + } + } } diff --git a/jdk/src/share/classes/java/awt/EventDispatchThread.java b/jdk/src/share/classes/java/awt/EventDispatchThread.java index f49bacb670a..23d08a0d418 100644 --- a/jdk/src/share/classes/java/awt/EventDispatchThread.java +++ b/jdk/src/share/classes/java/awt/EventDispatchThread.java @@ -39,6 +39,7 @@ import java.util.Vector; import java.util.logging.*; import sun.awt.dnd.SunDragSourceContextPeer; +import sun.awt.EventQueueDelegate; /** * EventDispatchThread is a package-private AWT class which takes @@ -243,10 +244,16 @@ class EventDispatchThread extends Thread { try { AWTEvent event; boolean eventOK; + EventQueueDelegate.Delegate delegate = + EventQueueDelegate.getDelegate(); do { - event = (id == ANY_EVENT) - ? theQueue.getNextEvent() - : theQueue.getNextEvent(id); + if (delegate != null && id == ANY_EVENT) { + event = delegate.getNextEvent(theQueue); + } else { + event = (id == ANY_EVENT) + ? theQueue.getNextEvent() + : theQueue.getNextEvent(id); + } eventOK = true; synchronized (eventFilters) { @@ -272,7 +279,14 @@ class EventDispatchThread extends Thread { eventLog.log(Level.FINEST, "Dispatching: " + event); } + Object handle = null; + if (delegate != null) { + handle = delegate.beforeDispatch(event); + } theQueue.dispatchEvent(event); + if (delegate != null) { + delegate.afterDispatch(event, handle); + } return true; } catch (ThreadDeath death) { diff --git a/jdk/src/share/classes/sun/awt/EventQueueDelegate.java b/jdk/src/share/classes/sun/awt/EventQueueDelegate.java new file mode 100644 index 00000000000..8f8a6f3fe0b --- /dev/null +++ b/jdk/src/share/classes/sun/awt/EventQueueDelegate.java @@ -0,0 +1,71 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.awt; + +import java.awt.AWTEvent; +import java.awt.EventQueue; + + +public class EventQueueDelegate { + private static final Object EVENT_QUEUE_DELEGATE_KEY = + new StringBuilder("EventQueueDelegate.Delegate"); + + public static void setDelegate(Delegate delegate) { + AppContext.getAppContext().put(EVENT_QUEUE_DELEGATE_KEY, delegate); + } + public static Delegate getDelegate() { + return + (Delegate) AppContext.getAppContext().get(EVENT_QUEUE_DELEGATE_KEY); + } + public interface Delegate { + /** + * This method allows for changing {@code EventQueue} events order. + * + * @param eventQueue current {@code EventQueue} + * @return next {@code event} for the {@code EventDispatchThread} + */ + + public AWTEvent getNextEvent(EventQueue eventQueue) throws InterruptedException; + + /** + * Notifies delegate before EventQueue.dispatch method. + * + * Note: this method may mutate the event + * + * @param event to be dispatched by {@code dispatch} method + * @return handle to be passed to {@code afterDispatch} method + */ + public Object beforeDispatch(AWTEvent event); + + /** + * Notifies delegate after EventQueue.dispatch method. + * + * @param event {@code event} dispatched by the {@code dispatch} method + * @param handle object which came from {@code beforeDispatch} method + */ + public void afterDispatch(AWTEvent event, Object handle); + } +} diff --git a/jdk/test/java/awt/EventQueue/6638195/bug6638195.java b/jdk/test/java/awt/EventQueue/6638195/bug6638195.java new file mode 100644 index 00000000000..b1109967071 --- /dev/null +++ b/jdk/test/java/awt/EventQueue/6638195/bug6638195.java @@ -0,0 +1,138 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * + * @bug 6638195 + * @author Igor Kushnirskiy + * @summary tests if EventQueueDelegate.Delegate is invoked. + */ + +import sun.awt.EventQueueDelegate; +import com.sun.java.swing.SwingUtilities3; + +import java.util.*; +import java.util.concurrent.*; +import java.awt.*; + +public class bug6638195 { + public static void main(String[] args) throws Exception { + MyEventQueueDelegate delegate = new MyEventQueueDelegate(); + EventQueueDelegate.setDelegate(delegate); + runTest(delegate); + + delegate = new MyEventQueueDelegate(); + SwingUtilities3.setEventQueueDelegate(getObjectMap(delegate)); + runTest(delegate); + } + + private static void runTest(MyEventQueueDelegate delegate) throws Exception { + EventQueue.invokeLater( + new Runnable() { + public void run() { + } + }); + final CountDownLatch latch = new CountDownLatch(1); + EventQueue.invokeLater( + new Runnable() { + public void run() { + latch.countDown(); + } + }); + latch.await(); + if (! delegate.allInvoked()) { + throw new RuntimeException("failed"); + } + } + + static Map> getObjectMap( + final EventQueueDelegate.Delegate delegate) { + Map> objectMap = + new HashMap>(); + Map methodMap; + + final AWTEvent[] afterDispatchEventArgument = new AWTEvent[1]; + final Object[] afterDispatchHandleArgument = new Object[1]; + Callable afterDispatchCallable = + new Callable() { + public Void call() { + delegate.afterDispatch(afterDispatchEventArgument[0], + afterDispatchHandleArgument[0]); + return null; + } + }; + methodMap = new HashMap(); + methodMap.put("event", afterDispatchEventArgument); + methodMap.put("handle", afterDispatchHandleArgument); + methodMap.put("method", afterDispatchCallable); + objectMap.put("afterDispatch", methodMap); + + final AWTEvent[] beforeDispatchEventArgument = new AWTEvent[1]; + Callable beforeDispatchCallable = + new Callable() { + public Object call() { + return delegate.beforeDispatch( + beforeDispatchEventArgument[0]); + } + }; + methodMap = new HashMap(); + methodMap.put("event", beforeDispatchEventArgument); + methodMap.put("method", beforeDispatchCallable); + objectMap.put("beforeDispatch", methodMap); + + final EventQueue[] getNextEventEventQueueArgument = new EventQueue[1]; + Callable getNextEventCallable = + new Callable() { + public AWTEvent call() throws Exception { + return delegate.getNextEvent( + getNextEventEventQueueArgument[0]); + } + }; + methodMap = new HashMap(); + methodMap.put("eventQueue", getNextEventEventQueueArgument); + methodMap.put("method", getNextEventCallable); + objectMap.put("getNextEvent", methodMap); + + return objectMap; + } + static class MyEventQueueDelegate implements EventQueueDelegate.Delegate { + private volatile boolean getNextEventInvoked = false; + private volatile boolean beforeDispatchInvoked = false; + private volatile boolean afterDispatchInvoked = false; + public AWTEvent getNextEvent(EventQueue eventQueue) + throws InterruptedException { + getNextEventInvoked = true; + return eventQueue.getNextEvent(); + } + public Object beforeDispatch(AWTEvent event) { + beforeDispatchInvoked = true; + return null; + } + public void afterDispatch(AWTEvent event, Object handle) { + afterDispatchInvoked = true; + } + private boolean allInvoked() { + return getNextEventInvoked && beforeDispatchInvoked && afterDispatchInvoked; + } + } +} From 1dce4ceddd3c2e0a986e7e5fcdc46790ef8043fa Mon Sep 17 00:00:00 2001 From: Igor Kushnirskiy Date: Fri, 25 Jul 2008 14:26:27 -0400 Subject: [PATCH 040/289] 6699328: NullPointerException in EventQueue.dispatchEvent when applet is closed, only reprise/scenario applet Reviewed-by: bchristi --- .../com/sun/java/swing/SwingUtilities3.java | 32 +++++++++++-------- .../classes/sun/awt/EventQueueDelegate.java | 4 +-- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java b/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java index 9268d7370a3..28d9e8af6ec 100644 --- a/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java +++ b/jdk/src/share/classes/com/sun/java/swing/SwingUtilities3.java @@ -133,42 +133,46 @@ public class SwingUtilities3 { } @Override - public void afterDispatch(AWTEvent event, Object handle) { + public void afterDispatch(AWTEvent event, Object handle) throws InterruptedException { afterDispatchEventArgument[0] = event; afterDispatchHandleArgument[0] = handle; try { afterDispatchCallable.call(); + } catch (InterruptedException e) { + throw e; + } catch (RuntimeException e) { + throw e; } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } + throw new RuntimeException(e); } } @Override - public Object beforeDispatch(AWTEvent event) { + public Object beforeDispatch(AWTEvent event) throws InterruptedException { beforeDispatchEventArgument[0] = event; try { return beforeDispatchCallable.call(); + } catch (InterruptedException e) { + throw e; + } catch (RuntimeException e) { + throw e; } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } + throw new RuntimeException(e); } - return null; } @Override - public AWTEvent getNextEvent(EventQueue eventQueue) { + public AWTEvent getNextEvent(EventQueue eventQueue) throws InterruptedException { getNextEventEventQueueArgument[0] = eventQueue; try { return getNextEventCallable.call(); + } catch (InterruptedException e) { + throw e; + } catch (RuntimeException e) { + throw e; } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } + throw new RuntimeException(e); } - return null; } } } diff --git a/jdk/src/share/classes/sun/awt/EventQueueDelegate.java b/jdk/src/share/classes/sun/awt/EventQueueDelegate.java index 8f8a6f3fe0b..c9d0a90d2af 100644 --- a/jdk/src/share/classes/sun/awt/EventQueueDelegate.java +++ b/jdk/src/share/classes/sun/awt/EventQueueDelegate.java @@ -58,7 +58,7 @@ public class EventQueueDelegate { * @param event to be dispatched by {@code dispatch} method * @return handle to be passed to {@code afterDispatch} method */ - public Object beforeDispatch(AWTEvent event); + public Object beforeDispatch(AWTEvent event) throws InterruptedException; /** * Notifies delegate after EventQueue.dispatch method. @@ -66,6 +66,6 @@ public class EventQueueDelegate { * @param event {@code event} dispatched by the {@code dispatch} method * @param handle object which came from {@code beforeDispatch} method */ - public void afterDispatch(AWTEvent event, Object handle); + public void afterDispatch(AWTEvent event, Object handle) throws InterruptedException; } } From 7b4a7f7bdc40568b99edf9ea7341d8e29d8a9d87 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 25 Jul 2008 11:32:56 -0700 Subject: [PATCH 041/289] 6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform") Reviewed-by: kvn --- hotspot/src/share/vm/ci/ciMethodBlocks.cpp | 2 +- .../src/share/vm/opto/idealGraphPrinter.cpp | 2 + hotspot/src/share/vm/opto/ifnode.cpp | 6 + .../test/compiler/6712835/Test6712835.java | 1578 +++++++++++++++++ 4 files changed, 1587 insertions(+), 1 deletion(-) create mode 100644 hotspot/test/compiler/6712835/Test6712835.java diff --git a/hotspot/src/share/vm/ci/ciMethodBlocks.cpp b/hotspot/src/share/vm/ci/ciMethodBlocks.cpp index 9bfba219b88..2810523f4fc 100644 --- a/hotspot/src/share/vm/ci/ciMethodBlocks.cpp +++ b/hotspot/src/share/vm/ci/ciMethodBlocks.cpp @@ -351,7 +351,7 @@ void ciBlock::set_exception_range(int start_bci, int limit_bci) { } #ifndef PRODUCT -static char *flagnames[] = { +static const char *flagnames[] = { "Processed", "Handler", "MayThrow", diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index 114a7ea17c7..de961127e68 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -473,10 +473,12 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { print_prop("is_dontcare", "false"); } +#ifdef ASSERT Node* old = C->matcher()->find_old_node(node); if (old != NULL) { print_prop("old_node_idx", old->_idx); } +#endif } if (node->is_Proj()) { diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index 073d4202f68..c6a76a853e1 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -725,6 +725,11 @@ static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) { int true_path = phi->is_diamond_phi(); if( true_path == 0 ) return NULL; + // Make sure that iff and the control of the phi are different. This + // should really only happen for dead control flow since it requires + // an illegal cycle. + if (phi->in(0)->in(1)->in(0) == iff) return NULL; + // phi->region->if_proj->ifnode->bool->cmp BoolNode *bol2 = phi->in(0)->in(1)->in(0)->in(1)->as_Bool(); @@ -751,6 +756,7 @@ static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) { } Node* new_bol = (flip ? phase->transform( bol2->negate(phase) ) : bol2); + assert(new_bol != iff->in(1), "must make progress"); iff->set_req(1, new_bol); // Intervening diamond probably goes dead phase->C->set_major_progress(); diff --git a/hotspot/test/compiler/6712835/Test6712835.java b/hotspot/test/compiler/6712835/Test6712835.java new file mode 100644 index 00000000000..2f1dbda198c --- /dev/null +++ b/hotspot/test/compiler/6712835/Test6712835.java @@ -0,0 +1,1578 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6712835 + * @summary Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform") + * @run main/othervm -Xcomp Test6712835 + */ + +/* Complexity upper bound: 349851 ops */ + +abstract class Tester_Class_0 { + boolean var_1 = true; + static double var_2; + float var_3 = 1.8301116E38F; + final String var_4 = "wck"; + final static short var_5 = 25624; + + + public Tester_Class_0() + { + var_2 = (byte)1.7374809293839066E308; + { + double var_18 = false ? 8027040614338917376L * var_3 + - (var_2 = var_5) : (var_3 += (char)4.491494085158084E307); + var_3 *= ~ ((byte)702579792) / 6600332715431236608L; + long var_19 = 0L; + var_18 -= 1759091496; + do + { + final long var_20 = (new long[(byte)(var_3 += + +1.6695243696502334E308)][(byte)((byte)1110410742 | ~var_19)])[var_1 & var_1 ? (byte)1047514041090199552L : (byte)var_5][(byte)(var_1 ? 123309551 : - ((byte)5932930312361050112L))]; + var_19++; + final short var_21 = var_5; + } while (var_19 < 1 && var_1 ^ var_3 == + ((byte)var_5)); + { + int var_22; + } + { + var_4.endsWith("o"); + } + int var_23 = 0; + var_1 &= (var_1 = true); + for (byte var_24 = 26; (var_1 = !var_1) && var_23 < 1; var_18 += var_1 ^ (var_1 |= false) ^ true ? var_24 : (byte)1504077779675035648L) + { + var_18 *= var_23; + var_23++; + float var_25; + (((new Tester_Class_0[var_24][var_24][var_24])[var_24])[var_24 >>= var_19][var_24 &= 6702582681202665472L]).var_3 *= var_5; + } + var_1 = (var_3 -= var_5) > (byte)func_2(1317089759, var_5, (byte)var_19) % (false & true ? 475183200 : 8947159119888251904L); + var_18 /= ~var_19 ^ ((byte)(var_18 %= (int)var_5) >= 6773554922270913536L ? (byte)var_5 : (byte)'u'); + var_3 = ~ ((byte)var_19); + } + double var_26 = 0; + var_1 &= (var_1 |= ! (var_1 |= true)); + while (var_26 < 1) + { + var_2 = 'e'; + var_26++; + var_1 ^= !true | 'j' * ((var_2 = 93384362) + var_5) <= var_5; + var_2 = true ? 2056852215 : var_5; + } + switch ((new char[(byte)var_3])[(byte)(short)var_4.charAt(438929928)] / (new byte[(byte)1779353916050551808L][(byte)+ ~8903539475459755008L])[(byte)836413337621087232L][(byte)784406244]) + { + case 101: + var_3 -= var_5; + break; + + case 'L': + + case 20: + final int var_27 = 2146473580; + break; + + case 18: + + default: + "mwh".substring((byte)(float)'A' % var_5, ']' | var_5 ^ ~ ((byte)'E')); + break; + + case 'H': + + } + var_3 = var_5; + long var_28; + var_28 = (var_1 = 'u' != (var_3 = var_1 ? 1384770002488557568L : ~ ~6691557565676772352L)) ? - ((byte)938410603) : var_5; + ((new Tester_Class_0[(byte)var_26])[(byte)'w']).var_3 = (byte)(short)'I'; + var_2 = (var_1 ^= "sfltwylm".startsWith("ytmeds")) ? 1837260339 * 434565574 : (new double[(byte)var_26])[(byte)var_3]; + } + + + + public boolean equals(Object obj) + { + var_2 = 785819716 / 'i'; + switch ((! (var_1 ^= var_1) ^ (! ((false | (var_1 |= var_1)) ^ !false) ? false : (var_1 |= !false)) ? var_1 : ! !var_1 ^ var_1) ? 1426689390 : var_5 * var_5) + { + case '`': + + case 89: + + case 13: + char var_9 = 'W'; + break; + + case 31: + + case 15: + + case 'm': + var_1 &= var_1; + break; + + case 'Z': + + case 34: + String[] var_10 = (new String[(byte)5534253842608756736L][(byte)'M'])[(byte)8717534666212195328L]; + break; + + case 124: + + } + var_3 += var_5; + var_1 |= (var_1 |= (var_1 = (var_1 |= var_5 >= (var_2 = (byte)var_3)))); + var_1 ^= (var_1 = var_4.endsWith(new String())); + var_2 = (var_3 %= 664966429); + { + var_4.lastIndexOf((int)('i' * (! !true & (true & !var_1) ? (byte)2.2562587635371023E307 : (byte)(var_3 %= var_3)) / var_3), 'P' % (false ? (byte)'N' : (byte)943393108)); + } + var_3 /= false | ! !var_1 ? (char)1.3721055E38F : '\\'; + if (var_1) + { + var_4.compareTo("uaqmqwg"); + } + else + { + var_1 ^= var_1 & (var_1 &= (var_1 ^= (var_1 ^= var_1))); + } + var_3 *= (new int[(byte)1980200282][(byte)'i'])[(byte)(var_2 = (byte)'O')][false ? (byte)2.4739911E38F : (byte)- ((byte)1.6045903096088714E308)]; + var_1 = var_5 != (byte)var_5 & (1.5002759009669559E308 < (byte)5110733568033040384L ^ (var_1 ? (var_1 ^= true) : var_1)); + long var_11; + return (var_2 = (byte)'B') < 550125954; + } + + + public static char func_0(final int arg_0, long[] arg_1, final boolean arg_2) + { + var_2 = (short)(false ? (byte)1.2577737E38F : (byte)'t'); + "xdf".codePointBefore((!arg_2 ? (byte)1426638765 : (byte)541094055) * ((byte)var_5 / var_5)); + ((new Tester_Class_0[(byte)(short)(var_2 = 'A')])[(byte)arg_0]).var_3 = 7823141134226481152L; + ((new Tester_Class_0[(byte)- ~1368497135389664256L])[!false || true ? (byte)2.5393905E38F : (byte)2.4415902E38F]).var_3 -= (int)(false ? (byte)var_5 : (byte)"musnlk".charAt(785792957)); + ((new Tester_Class_0[(byte)357672172])[(byte)7.709380171237795E307]).var_3 = arg_0; + ((new Tester_Class_0[(byte)var_5])[(byte)('Z' / + + -2.6037312E38F)]).var_3 %= arg_2 ? + - - + - + +4.6761156E37F : (byte)- (var_2 = - - ~3113191255384341504L); + (("exseqpham" + "uigdxg").equalsIgnoreCase("oeutvibnv") ? "l" : "qra").replace(false ^ true ? 't' : "jwpf".charAt(+ ((byte)arg_0)), 6.624090730243228E307 > 2.7771497E38F ? 't' : "tcfesyg".charAt(arg_0)); + ((new Tester_Class_0[(byte)arg_0][(byte)6943189372481268736L])[(byte)2.6713643513095145E307][(byte)var_5]).var_1 &= !"ipgqq".endsWith("aecnyvpmf"); + ((new Tester_Class_0[(byte)(+ +2158971337956592640L ^ var_5)])[false ? (byte)8594725249859841024L : (byte)var_5]).var_3 = (byte)"jd".charAt((byte)1.6298661301128909E307 << (byte)'B'); + var_2 = (float)1014982842 * (byte)var_5 * ((new Tester_Class_0[(byte)2.7842814E38F])[(byte)"n".charAt('e' ^ (byte)arg_0)]).var_3; + if (false) + { + ((new Tester_Class_0[(byte)8.702990410251979E307][(byte)8.865924E37F])[(byte)var_5][(byte)+ ((long)var_5)]).var_1 ^= arg_2; + } + else + { + ((new Tester_Class_0[(byte)('I' | var_5)])[(byte)('L' + (+ - - (var_2 = 'N') + 1.324025E38F))]).var_3 = var_5 % '[' + (byte)var_5; + } + ((new Tester_Class_0[(byte)7.41761E37F][(byte)(var_2 = var_5)])[(byte)var_5][(byte)'o']).var_1 &= false; + ((new Tester_Class_0[(byte)+ ((byte)7.9065203E37F)])[(byte)var_5]).var_1 ^= 630582880 > - (var_2 = var_5); + return 'K'; + } + + protected float func_1(int arg_0, final Object arg_1, Object arg_2) + { + var_1 ^= (var_1 ^= true) & !var_1; + { + var_3 -= var_3; + var_2 = var_1 && (var_1 &= ! !true) | + ~3353396000385141760L < 7949306917320622080L ? (byte)306954754 : (byte)var_5; + final long var_12 = 1048994076885686272L; + } + short var_13 = 8706; + byte var_14 = (new byte[(byte)6.697464316212731E307])[(byte)var_4.indexOf("clbr", (byte)var_5 + 'F')]; + ((new Tester_Class_0[var_14][var_14 &= 'b'])[var_14][var_14]).var_1 |= var_14 >= var_3; + (((new String[var_14][var_14])[var_14])[var_14]).codePointAt(585064460); + var_14 -= 2121015302; + var_2 = 1.241922E38F; + { + (((new Tester_Class_0[var_14][var_14 ^= 'y'])[var_14])[var_14 |= var_14]).var_3 *= 5756647686007829504L; + } + { + var_13--; + } + double var_15; + var_1 = (var_1 = true) ? false : true; + arg_0--; + return var_3; + } + + public final static short func_2(int arg_0, final short arg_1, byte arg_2) + { + arg_0 %= (((new Tester_Class_0[arg_2][arg_2])[arg_2++][--arg_2]).var_1 |= true) ? 'e' : var_5 >>> arg_2; + float var_16 = ((false ? ~3951083684045828096L >>> - -3880809660598466560L : arg_0) ^ arg_1) - 1.1257035E37F; + var_2 = var_5 + 3.3679594E38F; + arg_2 += true & (((new Tester_Class_0[arg_2])[arg_2 *= 4301185995603340288L]).var_1 = arg_1 != arg_1) ? (var_2 = arg_0) : 988311987505040384L + ']' >>> --arg_2; + arg_2 = arg_2; + var_16 /= (arg_2 += (arg_0 += (var_16 %= arg_2)) + (var_16 -= arg_2)); + var_16 += 7416220016668043264L; + ((new Tester_Class_0[arg_2])[arg_2]).var_1 &= false; + ((new Tester_Class_0[--arg_2])[--arg_2]).var_1 = true | (true & true ? true : false); + arg_2 -= (var_2 = 7997355759027275776L); + ((new Tester_Class_0[arg_2])[arg_2 %= 8660960251961819136L]).var_3 *= 4180634858198604800L; + arg_0 /= -1.3063173E38F; + var_2 = arg_2; + var_2 = (6266377813429248L ^ 'j') / (!false & (1.1423139843154216E308 >= (var_2 = arg_2) || (((new Tester_Class_0[arg_2])[arg_2]).var_1 ^= true)) ? (short)('e' * arg_0) : var_5); + --arg_0; + var_2 = (+ - ~8598445599816821760L << arg_1) % 1890075208 & (!true & !true ^ false & false ? 'w' : 'm') % (5614521287604667392L / arg_2) & ~193105176465084416L; + arg_2 &= (arg_2 |= arg_0) ^ ((((new Tester_Class_0[arg_2][arg_2])[arg_2])[arg_2]).var_1 ? arg_2 : (new long[arg_2])[arg_2]); + ((new Tester_Class_0[arg_2 &= 'V'][arg_2])[arg_2 /= 5486057194586717184L][arg_2 %= var_16]).var_1 |= (new boolean[((new Tester_Class_0[arg_2])[arg_2]).var_1 ? arg_2 : arg_2])[arg_2]; + return ((((new Tester_Class_0[arg_2][arg_2][arg_2])[--arg_2])[arg_2 |= arg_2][arg_2 %= 6782653882738869248L]).var_1 ? false : !true | "hopq".equalsIgnoreCase("wvm") | "qmhtjvm".endsWith("gewqas")) && ! !false & false ? arg_1 : arg_1; + } + + protected final static char func_3(byte arg_0, final int arg_1, final short arg_2, long[] arg_3) + { + ((new Tester_Class_0[arg_0 ^= 1902924521091955712L])[arg_0]).var_1 &= ((((new Tester_Class_0[arg_0][arg_0])[--arg_0])[arg_0 *= - -1.0959788E38F]).var_1 = false); + { + var_2 = (new float[arg_0][(byte)1082004329])[arg_0][arg_0 <<= 'T']; + } + ((new Tester_Class_0[arg_0 >>= arg_1][arg_0])[arg_0][arg_0]).var_1 |= ((new Tester_Class_0[arg_0])[--arg_0]).var_4.startsWith(((new Tester_Class_0[arg_0])[arg_0]).var_4); + ((new Tester_Class_0[(byte)var_5])[arg_0]).var_4.substring(273513722, 'f' * 'n').substring((new short[arg_0][arg_0])[arg_0][arg_0] % 'C' >> (arg_3[arg_0] - 's') % ("".charAt(arg_1) & var_5)); + var_2 = 'Q' + (char)arg_0; + { + ((new Tester_Class_0[++arg_0])[arg_0]).var_1 ^= !true || !true ? !false ^ false : ! (1.7030813E38F != ~arg_0); + } + { + "jbdu".indexOf(((new Tester_Class_0[arg_0 *= 2628674024589069312L])[arg_0 -= arg_1]).var_4, "gqglwwbab".charAt(~arg_0) >>> 'M'); + } + { + --arg_0; + } + ((new Tester_Class_0[arg_0])[arg_0]).var_1 = 'n' == ('t' | (+9156142987836739584L | 's')) - 2915339344736463872L; + int var_17; + var_17 = 'k'; + var_17 = (((new Tester_Class_0[arg_0])[arg_0]).var_1 &= false) ? (short)'q' : arg_2; + return '`'; + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_0.var_5 = "; result += Test6712835.Printer.print(var_5); + result += "\n"; + result += "Tester_Class_0.var_4 = "; result += Test6712835.Printer.print(var_4); + result += "\n"; + result += "Tester_Class_0.var_1 = "; result += Test6712835.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_0.var_2 = "; result += Test6712835.Printer.print(var_2); + result += "\n"; + result += "Tester_Class_0.var_3 = "; result += Test6712835.Printer.print(var_3); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Tester_Class_1 extends Tester_Class_0 { + final boolean var_29 = false; + static short var_30; + Tester_Class_0 var_31; + + + public Tester_Class_1() + { + new String(); + byte var_43 = (var_1 ? var_29 : var_1) ? (byte)(~ ~ ~6520122970162626560L | ~6642750731731981312L) : (byte)(var_30 = var_5); + { + var_2 = Tester_Class_0.var_5; + } + ((Tester_Class_0)(new Object[var_43])[var_43]).var_1 = var_29; + var_43 += 512311665; + } + + + + + final int func_0() + { + Tester_Class_0.var_2 = var_29 ? (var_29 ? (byte)'D' : (byte)Tester_Class_0.var_5) : (!var_1 ^ var_1 | (var_1 ^= var_1) ? (byte)'J' : (byte)51510881); + new String(); + new String(); + new String(); + return 1731501229; + } + + private final static void func_1(final String arg_0, final Object arg_1) + { + long var_32 = ((new Tester_Class_1[(byte)37719380])['I' == Tester_Class_0.var_5 + Tester_Class_0.var_5 ? (byte)(var_30 = (byte)1.3043569561522328E308) : (byte)1.1111420042091164E308]).var_1 ? ~2569063513521638400L - Tester_Class_0.var_5 ^ 'm' : 660383226; + ((Tester_Class_0)arg_1).var_3 += (char)8417109805993570304L; + var_30 = var_5; + var_2 = (new byte[(byte)2102078692])[(byte)7.942050823719592E307]; + if (((new Tester_Class_1[(byte)224717297])[(byte)2889830453578512384L]).var_1) + { + Tester_Class_0.var_2 = (new byte[(byte)'C'])[(byte)Tester_Class_0.var_5]; + } + else + { + var_32 <<= 'u'; + } + Tester_Class_0.var_2 = Tester_Class_0.var_5; + final Object var_33 = arg_1; + final byte var_34 = 40; + ++var_32; + (((new Tester_Class_1[var_34][var_34])[var_34][var_34]).var_31 = ((new Tester_Class_0[var_34][var_34])[var_34])[var_34]).var_1 ^= (((new Tester_Class_1[var_34][var_34])[var_34][var_34]).var_31 = (Tester_Class_0)var_33).var_1; + ((new Tester_Class_1[var_34])[var_34]).var_31 = (((new Tester_Class_1[var_34])[((new Tester_Class_1[var_34][var_34])[var_34][var_34]).var_1 ? var_34 : var_34]).var_31 = (((new Tester_Class_1[(byte)2.4941036E38F])[var_34]).var_31 = (Tester_Class_0)arg_1)); + } + + public static int[][] func_2(long arg_0, final float arg_1, short arg_2, final double arg_3) + { + long var_35; + { + arg_0++; + var_2 = true ? (byte)9.691601510156328E307 : (byte)"a".charAt(~ ((byte)arg_1)); + if (((new Tester_Class_1[(byte)'\\'][(byte)arg_2])[(byte)arg_2][(byte)arg_0]).var_29) + { + arg_2++; + } + else + { + Tester_Class_0.var_2 = arg_2; + var_30 = arg_2; + Tester_Class_0.var_2 = arg_0; + } + arg_2 /= 157487965; + arg_2 -= func_2(~ ((byte)arg_0), (short)arg_3, (byte)+2.2503214E38F); + } + arg_0--; + double var_36; + arg_0 <<= (arg_0 >>= (arg_0 = 'O')); + { + arg_0++; + --arg_0; + } + --arg_2; + ++arg_2; + "gbcrkn".length(); + var_30 = (short)7.14672E37F; + { + arg_0 %= (arg_0 >>= (arg_2 *= (byte)1.5835087622116814E308)) % arg_3; + var_36 = 'n'; + int[][] var_37 = new int[(byte)(double)arg_0][(byte)(arg_2 >>= 'o')]; + if ((byte)1390907656194158592L <= arg_2) + { + "uuoeps".indexOf("", 899321600); + } + else + { + var_36 = - ~ -arg_0; + } + short var_38 = var_5; + var_36 = ~arg_0 + (6482428938632186880L + 6995927649252739072L); + } + if (((new Tester_Class_1[(byte)arg_1][(byte)arg_2])[(new byte[(byte)arg_0])[(byte)var_5]][(byte)'s']).var_1 = false) + { + ++arg_0; + } + else + { + ((new Tester_Class_1[(byte)2.7176027E38F])[(byte)((arg_2 -= 2.595396436487417E307) % 'p')]).var_1 ^= ((new Tester_Class_1[(byte)4.393706E36F])[false ? (byte)4826960994531808256L : (byte)arg_0]).var_29; + } + int var_39 = 0; + arg_2 <<= 'Y'; + while (var_39 < 1 && false) + { + arg_0++; + var_39++; + Object var_40; + ((Tester_Class_0)(var_40 = new long[(byte)3.285531E38F])).var_3 += var_39; + } + Object var_41; + "w".substring(1359453539); + return new int[(byte)((arg_2 /= 4.143015135482291E307) - 3.2659622E38F)][(byte)++arg_2]; + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_1.var_5 = "; result += Test6712835.Printer.print(var_5); + result += "\n"; + result += "Tester_Class_1.var_30 = "; result += Test6712835.Printer.print(var_30); + result += "\n"; + result += "Tester_Class_1.var_4 = "; result += Test6712835.Printer.print(var_4); + result += "\n"; + result += "Tester_Class_1.var_1 = "; result += Test6712835.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_1.var_29 = "; result += Test6712835.Printer.print(var_29); + result += "\n"; + result += "Tester_Class_1.var_2 = "; result += Test6712835.Printer.print(var_2); + result += "\n"; + result += "Tester_Class_1.var_3 = "; result += Test6712835.Printer.print(var_3); + result += "\n"; + result += "Tester_Class_1.var_31 = "; result += Test6712835.Printer.print(var_31); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Tester_Class_2 extends Tester_Class_0 { + static float var_44 = 2.7867988E38F; + static byte var_45; + static long var_46 = 4319798868443575296L; + + + public Tester_Class_2() + { + Tester_Class_1.var_30 = (byte)3.1718026E38F; + var_45 = (new byte[(byte)'o'])[var_45 = (byte)Tester_Class_0.var_5]; + Tester_Class_1.var_30 = (Tester_Class_1.var_30 = Tester_Class_0.var_5); + if (true) + { + ++var_46; + boolean var_51 = false ? (var_1 &= !var_1) : true; + --var_46; + if (false) + { + var_3 *= 6.882788442363403E307; + } + else + { + Tester_Class_0.var_2 = '`'; + } + final float var_52 = (var_1 ^= var_1 || (var_1 &= false)) | (var_51 |= (var_51 &= false)) ? (byte)4.751813848964725E307 : (var_3 *= var_5); + (false ? var_4 : var_4).startsWith("j" + var_4); + var_46++; + var_3 %= Tester_Class_1.var_5; + } + else + { + Tester_Class_1.var_30 = (var_45 = (var_45 = (var_45 = (byte)Tester_Class_1.var_5))); + Tester_Class_1.var_2 = (var_3 -= ~ ((byte)var_46) - 2018787280); + Tester_Class_1.var_30 = (Tester_Class_1.var_30 = (Tester_Class_1.var_30 = (Tester_Class_1.var_30 = var_5))); + } + char var_53; + ++var_46; + short var_54 = 138; + ++var_46; + var_2 = 1435782089; + Tester_Class_0.var_2 = var_46; + } + + + + + protected final boolean func_0(final boolean arg_0, final boolean arg_1) + { + var_2 = 2.6153986361247174E307; + var_45 = (var_45 = (var_45 = (var_45 = (var_45 = (byte)(var_44 += var_46))))); + var_46++; + long var_47 = 0L; + var_3 -= + ((byte)(~var_46 * ~var_46 ^ var_46 % 1910419567)); + do + { + ++var_46; + var_47++; + char var_48 = 'b'; + } while (var_47 < 2); + new Tester_Class_1().var_31 = ((new Tester_Class_1[var_45 = (byte)3.0853839E38F])[(new byte[var_45 = (byte)1.4974966426791287E308])[var_45 = (byte)Tester_Class_0.var_5]]).var_1 ? new Tester_Class_1() : new Tester_Class_1(); + var_45 = (var_45 = (byte)var_44); + double var_49 = 0; + var_45 = (byte)(Tester_Class_1.var_30 = Tester_Class_0.var_5); + while (((false ^ (var_1 &= var_1) | (var_1 |= arg_0) ? new Tester_Class_1() : new Tester_Class_1()).var_29 ? var_1 : false && (var_1 ^= arg_0)) && (var_49 < 3 && (true ? new Tester_Class_1() : new Tester_Class_1()).var_1)) + { + var_45 = (var_45 = (var_45 = (var_45 = (var_45 = (byte)1.933612E38F)))); + var_49++; + var_45 = (var_45 = (var_45 = (var_45 = (byte)685709636))); + long var_50; + } + var_45 = (var_45 = (var_45 = (byte)var_5)); + var_46--; + return true; + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_2.var_46 = "; result += Test6712835.Printer.print(var_46); + result += "\n"; + result += "Tester_Class_2.var_2 = "; result += Test6712835.Printer.print(var_2); + result += "\n"; + result += "Tester_Class_2.var_3 = "; result += Test6712835.Printer.print(var_3); + result += "\n"; + result += "Tester_Class_2.var_44 = "; result += Test6712835.Printer.print(var_44); + result += "\n"; + result += "Tester_Class_2.var_5 = "; result += Test6712835.Printer.print(var_5); + result += "\n"; + result += "Tester_Class_2.var_45 = "; result += Test6712835.Printer.print(var_45); + result += "\n"; + result += "Tester_Class_2.var_4 = "; result += Test6712835.Printer.print(var_4); + result += "\n"; + result += "Tester_Class_2.var_1 = "; result += Test6712835.Printer.print(var_1); + result += ""; + result += "\n]"; + return result; + } +} + + +class Tester_Class_3 extends Tester_Class_0 { + static boolean var_55 = true; + short var_56; + char var_57 = (char)723612093; + final static byte var_58 = 118; + static float var_59 = true ? -2818156175448416256L : - - (Tester_Class_2.var_44 += var_58); + static Tester_Class_1 var_60; + byte var_61 = 112; + Tester_Class_2[] var_62; + static short var_63 = 19813; + static double var_64 = (var_55 = true) ? (Tester_Class_1.var_2 = 'M') : Tester_Class_2.var_46; + + + public Tester_Class_3() + { + var_56 = var_58; + Tester_Class_1 var_65 = var_60 = (var_60 = (var_60 = (new Tester_Class_1[var_61 |= '\\'])[(var_1 = true) || var_55 ? var_58 : var_61])); + var_64 /= 1253632965 * '`'; + Tester_Class_2.var_46 >>>= var_58; + (((var_61 = var_58) * (var_55 ? 1641980027 : var_63) >= 1490788063 ? var_65 : var_65).var_29 ? var_65 : var_65).var_31 = (new Tester_Class_2[var_58])[var_58]; + ++var_63; + new String(); + var_64 += var_55 ? (var_61 >>>= 'Q') : (var_63 <<= var_57); + ((new Tester_Class_2().var_3 >= Tester_Class_2.var_46 ? !var_55 : var_4.startsWith(var_4, 586086925)) ? "gjsdhuop" : "juqrt").substring(("pm" + ((new Tester_Class_2[var_61][var_58])[var_58][var_58]).var_4).codePointBefore((~var_61 << 3032688286897486848L) - Tester_Class_1.var_5), (var_61 += 4.0796373033184064E306) >> (Tester_Class_2.var_46 >>> var_58)); + var_63 -= (var_63 ^= var_57); + var_64 = var_5 - (Tester_Class_2.var_46 *= var_57); + Tester_Class_2.var_46 &= 7544159045139005440L; + var_55 |= false; + Tester_Class_2.var_46 = var_61; + } + + + + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_3.var_57 = "; result += Test6712835.Printer.print(var_57); + result += "\n"; + result += "Tester_Class_3.var_62 = "; result += Test6712835.Printer.print(var_62); + result += "\n"; + result += "Tester_Class_3.var_2 = "; result += Test6712835.Printer.print(var_2); + result += "\n"; + result += "Tester_Class_3.var_64 = "; result += Test6712835.Printer.print(var_64); + result += "\n"; + result += "Tester_Class_3.var_3 = "; result += Test6712835.Printer.print(var_3); + result += "\n"; + result += "Tester_Class_3.var_59 = "; result += Test6712835.Printer.print(var_59); + result += "\n"; + result += "Tester_Class_3.var_5 = "; result += Test6712835.Printer.print(var_5); + result += "\n"; + result += "Tester_Class_3.var_56 = "; result += Test6712835.Printer.print(var_56); + result += "\n"; + result += "Tester_Class_3.var_63 = "; result += Test6712835.Printer.print(var_63); + result += "\n"; + result += "Tester_Class_3.var_58 = "; result += Test6712835.Printer.print(var_58); + result += "\n"; + result += "Tester_Class_3.var_61 = "; result += Test6712835.Printer.print(var_61); + result += "\n"; + result += "Tester_Class_3.var_4 = "; result += Test6712835.Printer.print(var_4); + result += "\n"; + result += "Tester_Class_3.var_1 = "; result += Test6712835.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_3.var_55 = "; result += Test6712835.Printer.print(var_55); + result += "\n"; + result += "Tester_Class_3.var_60 = "; result += Test6712835.Printer.print(var_60); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Tester_Class_4 { + static long var_66; + final long var_67 = 7113579489152300032L * 985636454; + int[] var_68; + Tester_Class_3 var_69; + final long var_70 = Tester_Class_2.var_46 <<= Tester_Class_1.var_5; + byte var_71 = Tester_Class_3.var_58; + + + public Tester_Class_4() + { + Tester_Class_2.var_46++; + (var_69 = new Tester_Class_3()).var_61 += (!true | (Tester_Class_3.var_55 ^= Tester_Class_3.var_55) ? new Tester_Class_3() : new Tester_Class_3()).var_61; + final String[][] var_79 = new String[var_71 >>= (Tester_Class_3.var_63 ^= 'm')][((Tester_Class_3)(new Tester_Class_1().var_31 = new Tester_Class_2())).var_61 >>= (var_71 >>>= (Tester_Class_2.var_46 += 465205188010511360L))]; + ++(var_69 = (var_69 = (var_69 = (Tester_Class_3)(new Object[Tester_Class_3.var_58][var_71])[Tester_Class_3.var_58][var_71]))).var_61; + (((new Tester_Class_2[var_71][Tester_Class_3.var_58])[Tester_Class_2.var_45 = var_71])[var_71]).var_3 += (Tester_Class_2.var_46 <<= (Tester_Class_2.var_46 /= 9.03047405760868E307) >> (new Tester_Class_2().var_1 ? 2099696051 : Tester_Class_3.var_63)); + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = new Tester_Class_1()))); + char var_80; + Tester_Class_3.var_64 += 355712574; + ++Tester_Class_2.var_46; + } + + + + + private final static Tester_Class_1 func_0(boolean arg_0, double arg_1) + { + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = new Tester_Class_1()); + byte var_72 = (byte)Tester_Class_2.var_46; + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = new Tester_Class_1())))); + float var_73 = 0F; + "flfix".offsetByCodePoints((Tester_Class_3.var_63 ^= 3286104714651747328L) + ((Tester_Class_3)(new Tester_Class_0[var_72])[var_72]).var_61, Tester_Class_0.var_5 + Tester_Class_3.var_58); + while (var_73 < 2 && (false ? (Tester_Class_3.var_60 = new Tester_Class_1()) : (Tester_Class_1)(new Tester_Class_0[var_72])[var_72]).var_29) + { + ((Tester_Class_3)(Tester_Class_0)(new Object[var_72])[Tester_Class_3.var_58]).var_61 >>= ((new Tester_Class_4[var_72])[var_72]).var_67; + var_73++; + new String("blod"); + --var_72; + } + ((new Tester_Class_4[Tester_Class_3.var_58][var_72])[new Tester_Class_3().var_61][Tester_Class_3.var_58]).var_69 = new Tester_Class_3(); + float var_74 = (! ("dkcx".lastIndexOf(Tester_Class_1.var_5 >> - (var_72 >>>= 1433506903139345408L)) == Tester_Class_2.var_46) ? 'O' : 'e' - new Tester_Class_2().var_3) * ~ (var_72 ^= var_72); + Tester_Class_3.var_60 = !true ? new Tester_Class_1() : (new Tester_Class_1[Tester_Class_3.var_58])[var_72]; + ((arg_0 &= Tester_Class_3.var_55 | (Tester_Class_3.var_60 = new Tester_Class_1()).var_29) ? (Tester_Class_3.var_60 = (Tester_Class_1)(new Tester_Class_1().var_31 = new Tester_Class_2())) : (Tester_Class_3.var_60 = (new Tester_Class_1[var_72])[Tester_Class_3.var_58])).var_31 = (new Tester_Class_3[var_72 |= 546982927])[Tester_Class_3.var_58]; + long var_75 = 0L; + final double var_76 = +arg_1; + while (var_75 < 1) + { + short var_77; + var_75++; + new Tester_Class_3().var_57 = (false & true ? new Tester_Class_3() : new Tester_Class_3()).var_57; + (Tester_Class_3.var_60 = (new Tester_Class_1[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_31 = (new Tester_Class_2[Tester_Class_3.var_58][var_72])[var_72][var_72]; + } + Tester_Class_3.var_64 *= (arg_0 ? (Tester_Class_3.var_55 ^= (arg_0 ^= arg_0)) & ! (Tester_Class_3.var_55 = arg_0) : arg_0) ^ new Tester_Class_1().var_29 ? ++((new Tester_Class_3[var_72][var_72])[(new byte[Tester_Class_3.var_58])[Tester_Class_3.var_58]][(((new Tester_Class_4[var_72][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_3.var_58]).var_69 = (new Tester_Class_3[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_61]).var_57 : 'C'; + long var_78; + var_74 %= (Tester_Class_3.var_55 |= (arg_0 = (arg_0 ^= (arg_0 &= !arg_0)))) ? new Tester_Class_3().var_61 : (Tester_Class_3.var_63 ^= var_72); + arg_1 /= (Tester_Class_2.var_46 &= 'W'); + --(((new Tester_Class_4[var_72])[var_72]).var_69 = (((new Tester_Class_4[var_72])[var_72]).var_69 = new Tester_Class_3())).var_61; + return (new Tester_Class_1[var_72][Tester_Class_3.var_58])[var_72][new Tester_Class_3().var_61]; + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_4.var_68 = "; result += Test6712835.Printer.print(var_68); + result += "\n"; + result += "Tester_Class_4.var_66 = "; result += Test6712835.Printer.print(var_66); + result += "\n"; + result += "Tester_Class_4.var_67 = "; result += Test6712835.Printer.print(var_67); + result += "\n"; + result += "Tester_Class_4.var_70 = "; result += Test6712835.Printer.print(var_70); + result += "\n"; + result += "Tester_Class_4.var_71 = "; result += Test6712835.Printer.print(var_71); + result += "\n"; + result += "Tester_Class_4.var_69 = "; result += Test6712835.Printer.print(var_69); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Tester_Class_5 extends Tester_Class_0 { + static boolean var_81; + final int var_82 = 174395841; + int var_83; + byte var_84; + boolean var_85 = Tester_Class_3.var_55; + static boolean var_86 = Tester_Class_3.var_55; + + + public Tester_Class_5() + { + { + short var_87 = (new short[Tester_Class_3.var_58][var_84 = Tester_Class_3.var_58])[(((new Tester_Class_4[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_69 = (Tester_Class_3)(Tester_Class_0)(new Object[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_61][Tester_Class_3.var_58]; + Tester_Class_4 var_88 = var_85 ^ (var_81 = false) ? (new Tester_Class_4[Tester_Class_3.var_58])[Tester_Class_3.var_58] : (new Tester_Class_4[Tester_Class_3.var_58])[Tester_Class_3.var_58]; + { + ++var_87; + } + short var_89; + (var_88.var_69 = (new Tester_Class_3[var_88.var_71][var_88.var_71])[var_88.var_71][var_88.var_71]).var_61 += (((Tester_Class_2)(new Tester_Class_1().var_31 = new Tester_Class_2())).var_3 = Tester_Class_3.var_58); + var_88 = var_88; + } + { + ++Tester_Class_2.var_46; + --Tester_Class_2.var_46; + } + { + Tester_Class_2.var_46++; + Tester_Class_3.var_64 /= Tester_Class_3.var_59; + ((Tester_Class_4)(new Object[Tester_Class_2.var_45 = Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_71 %= (var_3 /= 3637233239489444864L); + ++Tester_Class_2.var_46; + } + new Tester_Class_3().var_57++; + var_85 &= (Tester_Class_3.var_55 |= false); + Tester_Class_3.var_60 = new Tester_Class_1(); + Tester_Class_2.var_46++; + ((Tester_Class_3)(true ? (new Tester_Class_2[Tester_Class_3.var_58])[Tester_Class_3.var_58] : (new Tester_Class_0[Tester_Class_3.var_58])[Tester_Class_2.var_45 = Tester_Class_3.var_58])).var_57 *= ((new Tester_Class_3[Tester_Class_3.var_58])[(byte)'`']).var_57; + var_3 += (int)Tester_Class_3.var_59 ^ (Tester_Class_2.var_46 -= Tester_Class_2.var_46) % ~((new Tester_Class_4[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_71; + ++Tester_Class_2.var_46; + --Tester_Class_2.var_46; + var_83 = Tester_Class_3.var_58; + } + + + + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_5.var_82 = "; result += Test6712835.Printer.print(var_82); + result += "\n"; + result += "Tester_Class_5.var_83 = "; result += Test6712835.Printer.print(var_83); + result += "\n"; + result += "Tester_Class_5.var_2 = "; result += Test6712835.Printer.print(var_2); + result += "\n"; + result += "Tester_Class_5.var_3 = "; result += Test6712835.Printer.print(var_3); + result += "\n"; + result += "Tester_Class_5.var_5 = "; result += Test6712835.Printer.print(var_5); + result += "\n"; + result += "Tester_Class_5.var_84 = "; result += Test6712835.Printer.print(var_84); + result += "\n"; + result += "Tester_Class_5.var_4 = "; result += Test6712835.Printer.print(var_4); + result += "\n"; + result += "Tester_Class_5.var_1 = "; result += Test6712835.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_5.var_81 = "; result += Test6712835.Printer.print(var_81); + result += "\n"; + result += "Tester_Class_5.var_85 = "; result += Test6712835.Printer.print(var_85); + result += "\n"; + result += "Tester_Class_5.var_86 = "; result += Test6712835.Printer.print(var_86); + result += ""; + result += "\n]"; + return result; + } +} + + +class Tester_Class_6 extends Tester_Class_0 { + long var_90 = 8467263472031702016L; + final static int var_91 = 1648594448 * ']'; + char var_92 = 'x'; + short var_93 = Tester_Class_3.var_63; + Tester_Class_4 var_94; + String[] var_95; + static short var_96 = Tester_Class_3.var_63 -= 83376045 << 40225606; + final static double var_97 = 5.387227213380301E307; + final static short var_98 = Tester_Class_3.var_63 &= var_91; + byte var_99 = 44; + + + public Tester_Class_6() + { + (Tester_Class_3.var_60 = (Tester_Class_1)(new Object[Tester_Class_3.var_58][var_99])[Tester_Class_3.var_58][var_99]).var_31 = true | true ? (Tester_Class_5)(new Object[var_99])[Tester_Class_3.var_58] : (Tester_Class_5)(new Object[Tester_Class_3.var_58])[var_99]; + var_92 &= 'p'; + Tester_Class_5.var_81 = (((new Tester_Class_1[var_99][Tester_Class_3.var_58])[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_29; + { + { + ++Tester_Class_2.var_46; + Tester_Class_3.var_2 = var_98; + var_93 -= var_96; + } + Tester_Class_2.var_46--; + { + (var_5 == (((Tester_Class_3)(new Tester_Class_0[var_99])[Tester_Class_3.var_58]).var_61 /= var_5) ? "fsajxeuao".replace('s', 'K') : var_4).substring('e' >>> var_5).toLowerCase(); + } + var_93 %= ((new Tester_Class_6[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_90; + var_93 /= var_93; + if (Tester_Class_5.var_86) + { + (var_94 = (new Tester_Class_4[var_99])[var_99]).var_69 = (new Tester_Class_3[var_99])[var_99 %= -var_90]; + } + else + { + --var_96; + } + var_93 *= 'O'; + final long var_103 = 7573900518735055872L; + --Tester_Class_3.var_63; + } + Tester_Class_3.var_64 /= var_93; + if (true) + { + --Tester_Class_2.var_46; + Tester_Class_5 var_104; + final double var_105 = Tester_Class_3.var_64 += Tester_Class_5.var_86 & (new Tester_Class_2().var_1 & ((Tester_Class_3.var_55 = (var_1 ^= Tester_Class_5.var_86) & false) & (Tester_Class_5.var_81 = Tester_Class_5.var_86))) ? (byte)'g' : var_99; + Tester_Class_3.var_64 *= var_99; + } + else + { + char var_106 = var_92 -= Tester_Class_3.var_58; + } + double[] var_107 = ((new double[Tester_Class_3.var_58][var_99][var_99])[var_99])[false ? Tester_Class_3.var_58 : Tester_Class_3.var_58]; + var_99 <<= (Tester_Class_3.var_63 >>= Tester_Class_3.var_58); + ++var_99; + } + + + + + final static byte func_0(final byte arg_0, final char arg_1, final Tester_Class_5[] arg_2) + { + ((Tester_Class_4)(new Object[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][arg_0]).var_69 = (Tester_Class_3)(new Tester_Class_0[Tester_Class_3.var_58])[Tester_Class_2.var_45 = Tester_Class_3.var_58]; + long var_100 = 0L; + Tester_Class_3.var_64 /= (Tester_Class_5.var_86 = true) || 'o' > (Tester_Class_3.var_63 -= (float)arg_0) ? var_98 : 1.7875238E38F; + do + { + Tester_Class_3.var_64 %= var_5; + var_100++; + Tester_Class_3.var_64 += var_96 + 'r'; + } while (true && (var_100 < 1 && (new Tester_Class_1().var_29 ? new Tester_Class_1() : (new Tester_Class_1[arg_0][Tester_Class_3.var_58])[arg_0][Tester_Class_3.var_58]).var_29)); + (Tester_Class_3.var_55 ^ (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = new Tester_Class_1()))).var_29 ? new Tester_Class_3() : new Tester_Class_3()).var_57 = ((((new Tester_Class_6[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_3.var_58]).var_94 = (((new Tester_Class_6[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][arg_0]).var_94 = (new Tester_Class_4[Tester_Class_3.var_58][arg_0])[Tester_Class_3.var_58][Tester_Class_3.var_58])).var_69 = new Tester_Class_3()).var_57; + final double var_101 = 1.6798216578519203E308; + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = false ? new Tester_Class_1() : (Tester_Class_3.var_60 = new Tester_Class_1())); + Tester_Class_2 var_102 = new Tester_Class_2(); + return Tester_Class_3.var_58; + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_6.var_92 = "; result += Test6712835.Printer.print(var_92); + result += "\n"; + result += "Tester_Class_6.var_91 = "; result += Test6712835.Printer.print(var_91); + result += "\n"; + result += "Tester_Class_6.var_95 = "; result += Test6712835.Printer.print(var_95); + result += "\n"; + result += "Tester_Class_6.var_90 = "; result += Test6712835.Printer.print(var_90); + result += "\n"; + result += "Tester_Class_6.var_2 = "; result += Test6712835.Printer.print(var_2); + result += "\n"; + result += "Tester_Class_6.var_97 = "; result += Test6712835.Printer.print(var_97); + result += "\n"; + result += "Tester_Class_6.var_3 = "; result += Test6712835.Printer.print(var_3); + result += "\n"; + result += "Tester_Class_6.var_5 = "; result += Test6712835.Printer.print(var_5); + result += "\n"; + result += "Tester_Class_6.var_93 = "; result += Test6712835.Printer.print(var_93); + result += "\n"; + result += "Tester_Class_6.var_96 = "; result += Test6712835.Printer.print(var_96); + result += "\n"; + result += "Tester_Class_6.var_98 = "; result += Test6712835.Printer.print(var_98); + result += "\n"; + result += "Tester_Class_6.var_99 = "; result += Test6712835.Printer.print(var_99); + result += "\n"; + result += "Tester_Class_6.var_4 = "; result += Test6712835.Printer.print(var_4); + result += "\n"; + result += "Tester_Class_6.var_1 = "; result += Test6712835.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_6.var_94 = "; result += Test6712835.Printer.print(var_94); + result += ""; + result += "\n]"; + return result; + } +} + + +abstract class Tester_Class_7 { + final static char var_108 = '_'; + static Tester_Class_3 var_109; + final short var_110 = 4360; + short var_111; + Object var_112; + Tester_Class_4 var_113; + static Tester_Class_5 var_114; + final short var_115 = Tester_Class_6.var_96; + final static float var_116 = Tester_Class_3.var_59; + + + public Tester_Class_7() + { + --Tester_Class_2.var_46; + --Tester_Class_6.var_96; + var_113 = (new Tester_Class_4[new Tester_Class_6().var_99])[Tester_Class_3.var_58]; + --Tester_Class_2.var_46; + Tester_Class_6.var_96--; + Tester_Class_3.var_63 -= 'i'; + if (!Tester_Class_5.var_86) + { + Tester_Class_3.var_64 %= var_116; + if ((Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)(Tester_Class_0)(var_112 = "yosyghjm"))).var_29) + { + Tester_Class_2.var_46++; + } + else + { + (var_114 = (var_114 = (Tester_Class_5)(Tester_Class_0)(var_112 = "bxt"))).var_83 = (Tester_Class_2.var_45 = (Tester_Class_2.var_45 = Tester_Class_3.var_58)); + } + var_114 = (var_114 = (var_114 = (var_114 = (var_114 = (var_114 = (Tester_Class_5)(var_112 = "blrobgg")))))); + var_113 = (((Tester_Class_6)(var_112 = "popebwfp")).var_94 = (new Tester_Class_4[Tester_Class_3.var_58])[Tester_Class_3.var_58]); + } + else + { + Tester_Class_3.var_60 = new Tester_Class_1(); + } + final Tester_Class_6 var_122 = new Tester_Class_6(); + var_122.var_92 &= (var_122.var_92 |= var_108); + ((new Tester_Class_5[var_122.var_99])[((new Tester_Class_3[Tester_Class_3.var_58])[var_122.var_99--]).var_61]).var_83 = 1708230145; + } + + + + public boolean equals(Object obj) + { + (((Tester_Class_5.var_81 = (Tester_Class_5.var_81 = false)) ? (Tester_Class_3.var_55 &= false) : !Tester_Class_3.var_55 & ((Tester_Class_1)obj).var_29) ? (new Tester_Class_2[Tester_Class_3.var_58])[Tester_Class_3.var_58] : (Tester_Class_2)obj).equals((Tester_Class_5.var_86 |= Tester_Class_3.var_55) | (Tester_Class_3.var_55 = Tester_Class_3.var_55) ? obj : (Tester_Class_6)(Tester_Class_0)obj); + Tester_Class_3.var_64 *= 2.8258473339654136E307; + { + final int var_118 = 1248523063; + short var_119 = 30906; + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)obj); + ((Tester_Class_6)(((Tester_Class_1)obj).var_31 = ((var_113 = (Tester_Class_4)obj).var_69 = (Tester_Class_3)obj))).var_94 = (var_113 = (Tester_Class_4)(var_112 = (Tester_Class_1)obj)); + } + final Tester_Class_1 var_120 = false ^ (((Tester_Class_1)obj).var_1 = !true) ^ (((Tester_Class_6)(Tester_Class_0)obj).var_92 *= (((Tester_Class_3)obj).var_57 |= (Tester_Class_2.var_46 >>= 6986775136305733632L))) < (byte)Tester_Class_6.var_97 ? (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)obj)) : (true ? (Tester_Class_1)obj : (Tester_Class_1)obj); + (var_114 = (var_114 = (Tester_Class_5)obj)).var_83 = (((new Tester_Class_6[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_92 &= ((Tester_Class_4)obj).var_70 << (Tester_Class_2.var_45 = Tester_Class_3.var_58)); + var_114 = (Tester_Class_5)obj; + obj = ((Tester_Class_3.var_60 = var_120).var_29 ? false : false) ? (new Tester_Class_6[Tester_Class_3.var_58])[Tester_Class_3.var_58] : obj; + (var_120.var_29 ? (Tester_Class_6)(obj = (Tester_Class_3.var_60 = var_120)) : (new Tester_Class_6[Tester_Class_3.var_58])[((Tester_Class_3)obj).var_61 ^= Tester_Class_6.var_91]).var_90 ^= 2127530040436251648L; + Object var_121; + return (new boolean[Tester_Class_3.var_58])[((var_113 = (Tester_Class_4)obj).var_69 = (var_109 = (new Tester_Class_3[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_3.var_58])).var_61]; + } + + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_7.var_108 = "; result += Test6712835.Printer.print(var_108); + result += "\n"; + result += "Tester_Class_7.var_116 = "; result += Test6712835.Printer.print(var_116); + result += "\n"; + result += "Tester_Class_7.var_110 = "; result += Test6712835.Printer.print(var_110); + result += "\n"; + result += "Tester_Class_7.var_111 = "; result += Test6712835.Printer.print(var_111); + result += "\n"; + result += "Tester_Class_7.var_115 = "; result += Test6712835.Printer.print(var_115); + result += "\n"; + result += "Tester_Class_7.var_114 = "; result += Test6712835.Printer.print(var_114); + result += "\n"; + result += "Tester_Class_7.var_113 = "; result += Test6712835.Printer.print(var_113); + result += "\n"; + result += "Tester_Class_7.var_109 = "; result += Test6712835.Printer.print(var_109); + result += "\n"; + result += "Tester_Class_7.var_112 = "; result += Test6712835.Printer.print(var_112); + result += ""; + result += "\n]"; + return result; + } +} + + +class Tester_Class_8 extends Tester_Class_7 { + static char var_123; + Tester_Class_4 var_124; + static short var_125; + + + public Tester_Class_8() + { + { + Tester_Class_3.var_64 -= (Tester_Class_2.var_46 *= Tester_Class_3.var_64); + { + Tester_Class_2.var_46--; + } + ++Tester_Class_3.var_63; + Tester_Class_5.var_86 |= true; + Tester_Class_6.var_96--; + } + "w".indexOf(312689020); + if (false) + { + (Tester_Class_7.var_114 = (new Tester_Class_5[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_83 = 'I'; + } + else + { + --Tester_Class_6.var_96; + } + switch (Tester_Class_5.var_86 ? Tester_Class_3.var_58 : Tester_Class_3.var_58) + { + case 95: + + case 35: + + } + Tester_Class_6.var_96--; + Tester_Class_3.var_64 *= 4.516167673347119E307; + --Tester_Class_3.var_63; + { + int var_126; + } + Tester_Class_3.var_60 = new Tester_Class_1(); + Tester_Class_2.var_46++; + ((new Tester_Class_6[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_99 &= Tester_Class_6.var_91; + ((new Tester_Class_1[((new Tester_Class_4[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_71])[((Tester_Class_3)(var_112 = "fsmtm")).var_61]).var_31 = (Tester_Class_2)(new Tester_Class_0[Tester_Class_3.var_58])[Tester_Class_3.var_58]; + } + + + + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_8.var_108 = "; result += Test6712835.Printer.print(var_108); + result += "\n"; + result += "Tester_Class_8.var_123 = "; result += Test6712835.Printer.print(var_123); + result += "\n"; + result += "Tester_Class_8.var_116 = "; result += Test6712835.Printer.print(var_116); + result += "\n"; + result += "Tester_Class_8.var_110 = "; result += Test6712835.Printer.print(var_110); + result += "\n"; + result += "Tester_Class_8.var_111 = "; result += Test6712835.Printer.print(var_111); + result += "\n"; + result += "Tester_Class_8.var_115 = "; result += Test6712835.Printer.print(var_115); + result += "\n"; + result += "Tester_Class_8.var_125 = "; result += Test6712835.Printer.print(var_125); + result += "\n"; + result += "Tester_Class_8.var_114 = "; result += Test6712835.Printer.print(var_114); + result += "\n"; + result += "Tester_Class_8.var_113 = "; result += Test6712835.Printer.print(var_113); + result += "\n"; + result += "Tester_Class_8.var_124 = "; result += Test6712835.Printer.print(var_124); + result += "\n"; + result += "Tester_Class_8.var_109 = "; result += Test6712835.Printer.print(var_109); + result += "\n"; + result += "Tester_Class_8.var_112 = "; result += Test6712835.Printer.print(var_112); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Tester_Class_9 { + final static String var_127 = "pxk"; + Tester_Class_2 var_128; + final static char var_129 = '\\'; + static float var_130; + static boolean var_131; + final static float var_132 = Tester_Class_3.var_59; + static Tester_Class_0 var_133; + boolean[] var_134; + + + public Tester_Class_9() + { + Tester_Class_2.var_44 -= Tester_Class_3.var_58; + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (new Tester_Class_1[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_3.var_58])); + { + Tester_Class_8 var_136; + } + ++Tester_Class_2.var_46; + Tester_Class_6.var_96--; + var_128 = (var_128 = (var_128 = (Tester_Class_2)(var_133 = (new Tester_Class_1[Tester_Class_3.var_58])[Tester_Class_3.var_58]))); + ++Tester_Class_6.var_96; + ++Tester_Class_2.var_46; + Tester_Class_4 var_137; + var_128 = (var_128 = (new Tester_Class_2[Tester_Class_3.var_58])[Tester_Class_3.var_58]); + (Tester_Class_8.var_114 = (Tester_Class_8.var_114 = (new Tester_Class_5[Tester_Class_3.var_58])[Tester_Class_3.var_58])).var_83 = (((new Tester_Class_4[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_3.var_58]).var_69 = (new Tester_Class_3[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_3.var_58]).var_57++; + Tester_Class_2.var_46++; + } + + + + + protected static short func_1() + { + { + Tester_Class_3.var_63--; + } + Tester_Class_3.var_64 *= Tester_Class_2.var_46; + short var_135; + Tester_Class_3.var_64 -= Tester_Class_6.var_96; + return new Tester_Class_6().var_93; + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_9.var_129 = "; result += Test6712835.Printer.print(var_129); + result += "\n"; + result += "Tester_Class_9.var_134 = "; result += Test6712835.Printer.print(var_134); + result += "\n"; + result += "Tester_Class_9.var_130 = "; result += Test6712835.Printer.print(var_130); + result += "\n"; + result += "Tester_Class_9.var_132 = "; result += Test6712835.Printer.print(var_132); + result += "\n"; + result += "Tester_Class_9.var_131 = "; result += Test6712835.Printer.print(var_131); + result += "\n"; + result += "Tester_Class_9.var_127 = "; result += Test6712835.Printer.print(var_127); + result += "\n"; + result += "Tester_Class_9.var_128 = "; result += Test6712835.Printer.print(var_128); + result += "\n"; + result += "Tester_Class_9.var_133 = "; result += Test6712835.Printer.print(var_133); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Tester_Class_10 extends Tester_Class_0 { + final static byte var_138 = 78; + Object var_139; + final static boolean var_140 = true; + float var_141 = 1.2816267E38F; + Tester_Class_8 var_142; + static Tester_Class_3 var_143; + short var_144 = var_1 ? (Tester_Class_6.var_96 &= 8024552544994698240L) : Tester_Class_0.var_5; + final boolean var_145 = var_140; + long var_146; + float[] var_147; + + + public Tester_Class_10() + { + "xuc".codePointCount(new Tester_Class_6().var_99 / ((new Tester_Class_9().var_128 = new Tester_Class_2()).var_1 ? var_138 : (int)(Tester_Class_3.var_64 += Tester_Class_3.var_64)), 882345740); + Tester_Class_3.var_64 /= Tester_Class_9.var_132; + Tester_Class_9.var_127.indexOf((Tester_Class_7.var_114 = (Tester_Class_8.var_114 = (Tester_Class_5)(var_139 = "mcyagebtv"))).var_83 = var_145 ? (Tester_Class_2.var_45 = Tester_Class_3.var_58) : Tester_Class_6.var_96); + --Tester_Class_2.var_46; + final float var_148 = 3.0263434E38F; + ((Tester_Class_7.var_114 = (Tester_Class_5)(Tester_Class_9.var_133 = new Tester_Class_1())).var_85 & ((Tester_Class_1)(var_139 = new Tester_Class_6())).var_1 ? "gmxwrgik" : Tester_Class_9.var_127).compareTo(var_4); + --Tester_Class_2.var_46; + new Tester_Class_6(); + ++Tester_Class_2.var_46; + Tester_Class_3.var_60 = Tester_Class_5.var_86 ? new Tester_Class_1() : new Tester_Class_1(); + { + --Tester_Class_6.var_96; + ((Tester_Class_7)(var_139 = new Tester_Class_1().var_4)).var_112 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)(var_139 = "gugsy"))); + } + Tester_Class_9.var_133 = (Tester_Class_3.var_60 = new Tester_Class_1()); + if (var_140 & !var_140) + { + Tester_Class_6.var_96++; + } + else + { + Tester_Class_2.var_46++; + } + { + ++new Tester_Class_6().var_92; + } + Tester_Class_7.var_109 = (((new Tester_Class_4[Tester_Class_3.var_58])[Tester_Class_3.var_58]).var_69 = (var_143 = new Tester_Class_3())); + Tester_Class_3.var_63--; + } + + + + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_10.var_147 = "; result += Test6712835.Printer.print(var_147); + result += "\n"; + result += "Tester_Class_10.var_146 = "; result += Test6712835.Printer.print(var_146); + result += "\n"; + result += "Tester_Class_10.var_3 = "; result += Test6712835.Printer.print(var_3); + result += "\n"; + result += "Tester_Class_10.var_141 = "; result += Test6712835.Printer.print(var_141); + result += "\n"; + result += "Tester_Class_10.var_5 = "; result += Test6712835.Printer.print(var_5); + result += "\n"; + result += "Tester_Class_10.var_144 = "; result += Test6712835.Printer.print(var_144); + result += "\n"; + result += "Tester_Class_10.var_138 = "; result += Test6712835.Printer.print(var_138); + result += "\n"; + result += "Tester_Class_10.var_1 = "; result += Test6712835.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_10.var_140 = "; result += Test6712835.Printer.print(var_140); + result += "\n"; + result += "Tester_Class_10.var_145 = "; result += Test6712835.Printer.print(var_145); + result += "\n"; + result += "Tester_Class_10.var_139 = "; result += Test6712835.Printer.print(var_139); + result += "\n"; + result += "Tester_Class_10.var_142 = "; result += Test6712835.Printer.print(var_142); + result += "\n"; + result += "Tester_Class_10.var_2 = "; result += Test6712835.Printer.print(var_2); + result += "\n"; + result += "Tester_Class_10.var_4 = "; result += Test6712835.Printer.print(var_4); + result += "\n"; + result += "Tester_Class_10.var_143 = "; result += Test6712835.Printer.print(var_143); + result += ""; + result += "\n]"; + return result; + } +} + + +interface Tester_Interface_11 { + public Tester_Class_4 func_0(final int arg_0, final byte arg_1); + public Tester_Class_2 func_1(Tester_Class_5 arg_0, final Tester_Class_0 arg_1, final int arg_2); +} + +public class Test6712835 { + final boolean var_149 = false; + Tester_Class_8 var_150; + final long var_151 = 8058077687473630208L; + + + protected final Tester_Class_1 func_0(final Object arg_0, Tester_Class_3 arg_1, final Tester_Class_4 arg_2, int arg_3) + { + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)arg_0)); + --Tester_Class_3.var_63; + (var_150 = (((new Tester_Class_10[arg_2.var_71])[(((Tester_Class_6)arg_0).var_94 = arg_2).var_71 &= Tester_Class_3.var_63 << ~arg_2.var_71]).var_142 = (var_150 = (((Tester_Class_10)arg_0).var_142 = (Tester_Class_8)arg_0)))).var_113 = arg_2; + Tester_Class_7.var_114 = (Tester_Class_7.var_114 = false ? (Tester_Class_5)arg_0 : (Tester_Class_5)arg_0); + ((((arg_1 = arg_1).var_1 |= "lgcrda".equalsIgnoreCase("ontlkst")) ? (Tester_Class_1)arg_0 : (Tester_Class_3.var_60 = (Tester_Class_1)arg_0)).var_29 ? (arg_1 = (Tester_Class_3)(((Tester_Class_7)arg_0).var_112 = (Tester_Class_9)arg_0)) : arg_1).var_57 >>>= ']'; + Tester_Class_8.var_114 = (Tester_Class_5)arg_0; + ((Tester_Class_3.var_55 &= (arg_1.var_1 = true)) ? (Tester_Class_6)(new Tester_Class_0[Tester_Class_3.var_58][Tester_Class_10.var_138])[Tester_Class_10.var_138][Tester_Class_10.var_138] : (Tester_Class_6)arg_0).var_94 = arg_2; + { + Tester_Class_3.var_55 &= ((Tester_Class_3.var_60 = new Tester_Class_1()).var_1 &= false); + Tester_Class_2.var_44 -= (arg_3 |= + ~6610561718704644096L); + ((Tester_Class_8)arg_0).var_113 = ((((Tester_Class_10)(Tester_Class_0)arg_0).var_142 = (var_150 = (Tester_Class_8)arg_0)).var_124 = arg_2); + (! (false | Tester_Class_5.var_86) ? (Tester_Class_10)arg_0 : (new Tester_Class_10[arg_1.var_61][arg_1.var_61])[Tester_Class_10.var_138][Tester_Class_10.var_138]).var_139 = ((Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)arg_0)).var_31 = (((Tester_Class_9)arg_0).var_128 = (((Tester_Class_9)arg_0).var_128 = (Tester_Class_2)arg_0))); + } + final Tester_Interface_11 var_152 = !((Tester_Class_1)arg_0).var_29 ^ Tester_Class_5.var_86 ? (new Tester_Interface_11[arg_2.var_71][arg_1.var_61])[arg_1.var_61][arg_1.var_61] : (new Tester_Interface_11[arg_2.var_71][arg_2.var_71])[Tester_Class_10.var_138][Tester_Class_3.var_58]; + Tester_Class_3.var_64 /= (arg_3 >>= ++((Tester_Class_6)(Tester_Class_0)arg_0).var_92) * Tester_Class_9.var_132; + Tester_Class_0 var_153 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)arg_0))))).var_31 = (((new Tester_Class_9[arg_1.var_61])[arg_1.var_61 *= 634692606]).var_128 = !false ? (Tester_Class_2)arg_0 : (Tester_Class_2)arg_0); + (Tester_Class_10.var_140 ? (Tester_Class_7)arg_0 : (var_150 = (Tester_Class_8)(Tester_Class_7)arg_0)).var_112 = Tester_Class_3.var_64 != ((((Tester_Class_10)(var_153 = (Tester_Class_8.var_114 = (Tester_Class_5)arg_0))).var_1 |= arg_1.var_1) ? (Tester_Class_6)var_153 : (Tester_Class_6)var_153).var_99-- ? (Tester_Class_7)((var_150 = (Tester_Class_8)arg_0).var_112 = (Tester_Class_10)var_153) : (Tester_Class_7)arg_0; + (((new Tester_Class_7[Tester_Class_10.var_138][arg_2.var_71])[Tester_Class_3.var_58])[arg_2.var_71]).var_112 = arg_0; + if (!false) + { + arg_3 <<= (Tester_Class_2.var_46 /= - ((byte)((Tester_Class_10)arg_0).var_144)) - ((Tester_Class_6)arg_0).var_99; + } + else + { + ((Tester_Class_7)(((Tester_Class_8)arg_0).var_112 = var_153)).var_113 = arg_2; + ((Tester_Class_9)arg_0).var_128 = (((Tester_Class_9)(((Tester_Class_7)arg_0).var_112 = (Tester_Class_7)arg_0)).var_128 = (((Tester_Class_9)arg_0).var_128 = (Tester_Class_2)arg_0)); + } + (((Tester_Class_10)arg_0).var_142 = (Tester_Class_8)arg_0).var_124 = (((Tester_Class_6)var_153).var_94 = arg_2); + final char var_154 = arg_1.var_57 %= ((Tester_Class_6)var_153).var_93--; + (true ? arg_1 : (arg_1 = arg_1)).equals(arg_0); + (Tester_Class_10.var_140 ? (new Tester_Class_6[Tester_Class_10.var_138])[arg_2.var_71] : (new Tester_Class_6[(Tester_Class_10.var_143 = arg_1).var_61])[arg_1.var_61]).var_94 = ((((new Tester_Class_7[arg_2.var_71][arg_1.var_61][Tester_Class_10.var_138])[Tester_Class_10.var_138])[arg_2.var_71 = arg_2.var_71][Tester_Class_10.var_138]).var_113 = (((Tester_Class_7)arg_0).var_113 = arg_2)); + Tester_Class_3.var_60 = ((Tester_Class_10)(((Tester_Class_7)arg_0).var_112 = (Tester_Class_7)(((Tester_Class_10)var_153).var_139 = new Tester_Class_6[Tester_Class_10.var_138][Tester_Class_10.var_138]))).var_1 ? (Tester_Class_3.var_60 = (Tester_Class_1)var_153) : (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)(Tester_Class_9.var_133 = (Tester_Class_10)arg_0))); + ((Tester_Class_7)(((Tester_Class_10)arg_0).var_139 = new Tester_Class_10[Tester_Class_3.var_58][--arg_2.var_71])).var_112 = new byte[(((Tester_Class_8)(Tester_Class_7)((var_150 = (var_150 = (Tester_Class_8)arg_0)).var_112 = arg_2)).var_113 = (((Tester_Class_7)arg_0).var_113 = arg_2)).var_71]; + Tester_Class_8 var_155; + (Tester_Class_3.var_55 & arg_2.equals(arg_0) ? (Tester_Class_10)var_153 : (Tester_Class_10)var_153).var_3 %= Tester_Class_6.var_91; + return ((Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)var_153)))).var_29 ? ! !true : Tester_Class_10.var_140 | Tester_Class_3.var_55) || Tester_Class_3.var_55 ? (Tester_Class_3.var_60 = (Tester_Class_1)(((Tester_Class_10)var_153).var_139 = (Tester_Class_6)var_153)) : new Tester_Class_1(); + } + + protected Tester_Class_5 func_1(Tester_Class_0 arg_0, final float arg_1) + { + (!Tester_Class_10.var_140 ? (Tester_Class_6)arg_0 : (Tester_Class_6)arg_0).var_90 /= ((Tester_Class_8.var_109 = (new boolean[Tester_Class_10.var_138][Tester_Class_3.var_58])[((Tester_Class_6)arg_0).var_99][Tester_Class_10.var_138] ? (Tester_Class_3)((Tester_Class_3.var_60 = (Tester_Class_1)arg_0).var_31 = (Tester_Class_6)arg_0) : (Tester_Class_3)arg_0).var_61 *= Tester_Class_3.var_58); + { + "".toLowerCase(); + } + ((Tester_Class_10)arg_0).var_139 = new Tester_Class_8(); + arg_0 = (new Tester_Class_6[((Tester_Class_6)arg_0).var_99])[Tester_Class_3.var_58]; + if (((Tester_Class_10)(arg_0 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)arg_0)))).var_145) + { + Tester_Class_3.var_63++; + } + else + { + ++Tester_Class_2.var_46; + } + (((Tester_Class_3.var_55 ^= Tester_Class_3.var_55 ^ true) ? (Tester_Class_10)arg_0 : (Tester_Class_10)arg_0).var_145 || true ? (Tester_Class_6)arg_0 : (Tester_Class_6)(((Tester_Class_7)(((Tester_Class_10)arg_0).var_139 = (Tester_Class_10)arg_0)).var_112 = "jlixai")).var_99--; + Tester_Class_5.var_81 = Tester_Class_3.var_55 && ! (arg_0.var_1 = arg_0.var_1); + { + ((new Tester_Class_6[Tester_Class_3.var_58])[(true ? (Tester_Class_6)(Tester_Class_9.var_133 = (Tester_Class_10)arg_0) : (Tester_Class_6)(((Tester_Class_1)arg_0).var_31 = (Tester_Class_10)arg_0)).var_99]).var_90 *= (Tester_Class_3.var_64 %= Tester_Class_3.var_63); + } + ++Tester_Class_2.var_46; + Tester_Class_0 var_156; + Tester_Class_2.var_46++; + Tester_Class_8.var_114 = (Tester_Class_7.var_114 = (Tester_Class_8.var_114 = (Tester_Class_5)arg_0)); + Tester_Class_6.func_2((Tester_Class_7.var_114 = (Tester_Class_7.var_114 = (Tester_Class_7.var_114 = (Tester_Class_5)arg_0))).var_83 = (byte)(((Tester_Class_10)arg_0).var_142 = (new Tester_Class_8[Tester_Class_3.var_58][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_10.var_138]).var_110, Tester_Class_6.var_96, (new byte[Tester_Class_3.var_58])[Tester_Class_10.var_138]); + Tester_Class_7.var_114 = (new Tester_Class_5[Tester_Class_10.var_138])[((Tester_Class_3)arg_0).var_61]; + boolean var_157 = Tester_Class_10.var_140; + (Tester_Class_3.var_60 = (Tester_Class_1)arg_0).var_1 ^= Tester_Class_10.var_140; + return Tester_Class_8.var_114 = (Tester_Class_7.var_114 = (Tester_Class_8.var_114 = (Tester_Class_5)arg_0)); + } + + final static int func_2(Tester_Class_6 arg_0) + { + new Tester_Class_9(); + { + ++Tester_Class_3.var_63; + } + new Tester_Class_3().var_57--; + Tester_Class_1 var_158; + String var_159; + --Tester_Class_6.var_96; + { + new String(); + } + var_159 = (var_159 = arg_0.var_4); + { + --Tester_Class_2.var_46; + } + final double var_160 = (Tester_Class_7.var_114 = (Tester_Class_8.var_114 = (Tester_Class_8.var_114 = (Tester_Class_5)(new Tester_Class_0[arg_0.var_99][arg_0.var_99])[Tester_Class_3.var_58][Tester_Class_3.var_58]))).var_1 ? Tester_Class_9.var_132 : Tester_Class_6.var_97; + Tester_Class_8 var_161; + char var_162 = 'O'; + Tester_Class_2.var_46++; + Tester_Class_6.var_96++; + { + new String(); + } + ++Tester_Class_6.var_96; + var_162 >>= ((new Tester_Class_4[arg_0.var_99])[arg_0.var_99++]).var_70 >> Tester_Class_6.var_91; + (Tester_Class_7.var_114 = (Tester_Class_7.var_114 = (new Tester_Class_5[Tester_Class_3.var_58])[++arg_0.var_99])).var_83 = (arg_0.var_93 <<= Tester_Class_7.var_108); + --Tester_Class_6.var_96; + { + new Tester_Class_9().var_128 = new Tester_Class_2(); + } + arg_0 = arg_0; + { + Tester_Class_9 var_163; + } + ((Tester_Class_5)(Tester_Class_9.var_133 = arg_0)).var_83 = (arg_0.var_99 >>= Tester_Class_5.var_5); + arg_0.var_99 = Tester_Class_10.var_138; + Tester_Class_3.var_60 = (var_158 = (Tester_Class_3.var_60 = (Tester_Class_1)(Tester_Class_9.var_133 = arg_0))); + return Tester_Class_6.var_91; + } + + protected final Tester_Class_9 func_3() + { + Tester_Class_2.var_44 = 3210658399310388224L; + ++Tester_Class_6.var_96; + short var_164 = 15978; + var_164++; + Tester_Class_5.var_81 = true; + return Tester_Class_3.var_55 ? new Tester_Class_9() : new Tester_Class_9(); + } + + final static Tester_Class_10 func_4(Tester_Class_3 arg_0, String arg_1, final byte[] arg_2, final Object arg_3) + { + Tester_Class_1 var_165; + Tester_Class_3.var_63 += new Tester_Class_6().var_92 >= 3821095133162842112L ? (arg_0.var_61 |= Tester_Class_6.var_91) : Tester_Class_10.var_138; + return false ? ((var_165 = (Tester_Class_1)arg_3).var_29 ? (Tester_Class_10)arg_3 : (Tester_Class_10)arg_3) : (Tester_Class_10)(Tester_Class_0)arg_3; + } + + private static Object func_7(final short arg_0, String arg_1, final Tester_Class_3 arg_2) + { + Tester_Class_3.var_60 = (new Tester_Class_1[arg_2.var_61])[Tester_Class_10.var_138]; + return ((new Tester_Class_7[arg_2.var_61 |= Tester_Class_3.var_63])[arg_2.var_61 *= Tester_Class_6.var_98]).var_112 = new Tester_Class_8(); + } + + public static String execute() + { + try { + Test6712835 t = new Test6712835(); + try { t.test(); } + catch(Throwable e) { } + try { return t.toString(); } + catch (Throwable e) { return "Error during result conversion to String"; } + } catch (Throwable e) { return "Error during test execution"; } + } + + public static void main(String[] args) + { + try { + Test6712835 t = new Test6712835(); + try { t.test(); } + catch(Throwable e) { } + try { System.out.println(t); } + catch(Throwable e) { } + } catch (Throwable e) { } + } + + private void test() + { + Tester_Class_3.var_60 = true ? (Tester_Class_3.var_60 = new Tester_Class_1()) : new Tester_Class_1(); + double var_170 = 0; + Tester_Class_9.var_133 = (new Tester_Class_4().var_69 = new Tester_Class_3()); + new Tester_Class_6(); + String var_171; + new Tester_Class_9(); + do + { + new String(); + var_170++; + Tester_Class_3.var_64 = 1.0240330514364089E307; + new String(); + var_171 = (var_171 = Tester_Class_9.var_127); + Tester_Class_3.var_63--; + } while (var_170 < 525); + ((new Tester_Class_10[Tester_Class_10.var_138])[Tester_Class_2.var_45 = Tester_Class_3.var_58]).var_142 = (Tester_Class_8)(Tester_Class_7)(new Tester_Class_10().var_139 = new Tester_Class_2()); + long var_172 = 0L; + Tester_Class_3.var_64 /= (((new Tester_Class_6[Tester_Class_3.var_58])[Tester_Class_10.var_138]).var_99 ^= ((new Tester_Class_6[Tester_Class_3.var_58])[Tester_Class_10.var_138]).var_90) > 9.462466046830147E307 ? new Tester_Class_6().var_99 : Tester_Class_3.var_58; + short var_173; + (true ? new Tester_Class_2() : (func_3().var_128 = new Tester_Class_2())).var_3 *= (var_150 = new Tester_Class_8()).var_115; + (Tester_Class_3.var_60 = new Tester_Class_1()).var_31 = (((new Tester_Class_9[Tester_Class_3.var_58])[Tester_Class_10.var_138]).var_128 = (func_3().var_128 = (func_3().var_128 = (new Tester_Class_9().var_128 = new Tester_Class_2())))); + for (((new Tester_Class_10[new Tester_Class_6().var_99])[new Tester_Class_6().var_99++]).var_142 = (new Tester_Class_8[Tester_Class_10.var_138])[Tester_Class_3.var_58]; var_172 < 203 && (Tester_Class_3.var_55 &= (new boolean[Tester_Class_2.var_45 = Tester_Class_3.var_58])[Tester_Class_10.var_138]); Tester_Class_9.var_133 = (Tester_Class_7.var_114 = (new Tester_Class_5[Tester_Class_2.var_45 = Tester_Class_10.var_138][Tester_Class_10.var_138])[Tester_Class_3.var_58][Tester_Class_2.var_45 = Tester_Class_3.var_58])) + { + var_171 = Tester_Class_9.var_127; + var_172++; + Tester_Class_3.var_63++; + Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_1)(new Object[Tester_Class_3.var_58][Tester_Class_10.var_138])[Tester_Class_3.var_58][Tester_Class_3.var_58]))); + ++Tester_Class_2.var_46; + Tester_Class_2.var_46--; + Tester_Class_3.var_64 -= Tester_Class_3.var_58; + } + (Tester_Class_3.var_60 = new Tester_Class_1()).var_31 = ((new Tester_Class_8().var_124 = new Tester_Class_4()).var_69 = new Tester_Class_3()); + int var_174 = 0; + ((new Tester_Class_6[Tester_Class_10.var_138][Tester_Class_10.var_138])[Tester_Class_2.var_45 = Tester_Class_10.var_138][Tester_Class_2.var_45 = Tester_Class_3.var_58]).var_92 = 'Z'; + while ((Tester_Class_9.var_131 = Tester_Class_3.var_55) && (var_174 < 24 && !true)) + { + new Tester_Class_10(); + var_174++; + Tester_Class_3.var_64 %= (((new Tester_Class_6[Tester_Class_3.var_58])[Tester_Class_2.var_45 = Tester_Class_3.var_58]).var_93 ^= (byte)Tester_Class_3.var_59); + ((Tester_Class_10)(Tester_Class_9.var_133 = (new Tester_Class_5[((Tester_Class_6)(new Tester_Class_0[Tester_Class_10.var_138])[(byte)(Tester_Class_2.var_46 >>>= Tester_Class_7.var_108)]).var_99])[Tester_Class_10.var_138])).var_139 = (new Tester_Class_10[new Tester_Class_6().var_99][new Tester_Class_4().var_71])[new Tester_Class_4().var_71]; + } + int var_175 = 0; + (Tester_Class_10.var_140 ? (Tester_Class_2)(Tester_Class_9.var_133 = (Tester_Class_7.var_114 = (new Tester_Class_5[Tester_Class_10.var_138])[Tester_Class_10.var_138])) : new Tester_Class_2()).var_1 &= Tester_Class_3.var_55; + do + { + Tester_Class_10.var_143 = new Tester_Class_3(); + var_175++; + ++Tester_Class_2.var_46; + } while ((false ? true : var_149) | !Tester_Class_10.var_140 && var_175 < 97); + Tester_Class_9.var_131 = true; + (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = (Tester_Class_3.var_60 = new Tester_Class_1())))).var_1 &= (((new Tester_Class_10().var_1 = !true) ? new Tester_Class_10() : new Tester_Class_10()).var_145 ? new Tester_Class_3() : new Tester_Class_3()).var_1; + (true ? func_3() : func_3()).var_128 = ((((Tester_Class_5.var_86 = (Tester_Class_3.var_55 &= !var_149)) ? new Tester_Class_10() : new Tester_Class_10()).var_145 ? new Tester_Class_9() : func_3()).var_128 = var_149 ? new Tester_Class_2() : new Tester_Class_2()); + Tester_Class_3.var_59 -= (Tester_Class_5.var_81 = new Tester_Class_1().var_29) ^ !true ? 7920143378515332096L : new Tester_Class_6().var_92; + ((Tester_Class_3.var_60 = new Tester_Class_1()).var_1 ? (new Tester_Class_5[Tester_Class_10.var_138][Tester_Class_3.var_58])[Tester_Class_3.var_58][Tester_Class_3.var_58] : (Tester_Class_8.var_114 = new Tester_Class_5())).var_83 = Tester_Class_10.var_140 ? (Tester_Class_3.var_63 -= 2.0167496E38F) : ++Tester_Class_3.var_63; + double var_176 = 9.327780852480363E307; + } + public String toString() + { + String result = "[\n"; + result += "Test6712835.var_151 = "; result += Printer.print(var_151); + result += "\n"; + result += "Test6712835.var_149 = "; result += Printer.print(var_149); + result += "\n"; + result += "Test6712835.var_150 = "; result += Printer.print(var_150); + result += ""; + result += "\n]"; + return result; + } + static class Printer + { + public static String print(boolean arg) { return String.valueOf(arg); } + public static String print(byte arg) { return String.valueOf(arg); } + public static String print(short arg) { return String.valueOf(arg); } + public static String print(char arg) { return String.valueOf((int)arg); } + public static String print(int arg) { return String.valueOf(arg); } + public static String print(long arg) { return String.valueOf(arg); } + public static String print(float arg) { return String.valueOf(arg); } + public static String print(double arg) { return String.valueOf(arg); } + + + public static String print(Object arg) + { + return print_r(new java.util.Stack(), arg); + } + + private static String print_r(java.util.Stack visitedObjects, Object arg) + { + String result = ""; + if (arg == null) + result += "null"; + else + if (arg.getClass().isArray()) + { + for (int i = 0; i < visitedObjects.size(); i++) + if (visitedObjects.elementAt(i) == arg) return ""; + + visitedObjects.push(arg); + + final String delimiter = ", "; + result += "["; + + if (arg instanceof Object[]) + { + Object[] array = (Object[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print_r(visitedObjects, array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof boolean[]) + { + boolean[] array = (boolean[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof byte[]) + { + byte[] array = (byte[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof short[]) + { + short[] array = (short[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof char[]) + { + char[] array = (char[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof int[]) + { + int[] array = (int[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof long[]) + { + long[] array = (long[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof float[]) + { + float[] array = (float[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof double[]) + { + double[] array = (double[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + + result += "]"; + visitedObjects.pop(); + + } else + { + result += arg.toString(); + } + + return result; + } + } +} From 20de63f383e1417b4e39b9b5197db870a8c56df8 Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 25 Jul 2008 15:54:23 -0700 Subject: [PATCH 042/289] 6700047: C2 failed in idom_no_update Partial peeling shouldn't place clones into loop Reviewed-by: kvn --- hotspot/src/share/vm/opto/loopopts.cpp | 17 +++--- .../test/compiler/6700047/Test6700047.java | 60 +++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 hotspot/test/compiler/6700047/Test6700047.java diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index f7fa3f21b2c..4353219f41c 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -1891,18 +1891,19 @@ void PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, N _igvn.hash_delete(use); use->set_req(j, n_clone); _igvn._worklist.push(use); + Node* use_c; if (!use->is_Phi()) { - Node* use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); - set_ctrl(n_clone, use_c); - assert(!loop->is_member(get_loop(use_c)), "should be outside loop"); - get_loop(use_c)->_body.push(n_clone); + use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); } else { // Use in a phi is considered a use in the associated predecessor block - Node *prevbb = use->in(0)->in(j); - set_ctrl(n_clone, prevbb); - assert(!loop->is_member(get_loop(prevbb)), "should be outside loop"); - get_loop(prevbb)->_body.push(n_clone); + use_c = use->in(0)->in(j); } + if (use_c->is_CountedLoop()) { + use_c = use_c->in(LoopNode::EntryControl); + } + set_ctrl(n_clone, use_c); + assert(!loop->is_member(get_loop(use_c)), "should be outside loop"); + get_loop(use_c)->_body.push(n_clone); _igvn.register_new_node_with_optimizer(n_clone); #if !defined(PRODUCT) if (TracePartialPeeling) { diff --git a/hotspot/test/compiler/6700047/Test6700047.java b/hotspot/test/compiler/6700047/Test6700047.java new file mode 100644 index 00000000000..55921d59465 --- /dev/null +++ b/hotspot/test/compiler/6700047/Test6700047.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6700047 + * @summary C2 failed in idom_no_update + * @run main Test6700047 + */ + +public class Test6700047 { + public static void main(String[] args) { + for (int i = 0; i < 100000; i++) { + intToLeftPaddedAsciiBytes(); + } + } + + public static int intToLeftPaddedAsciiBytes() { + int offset = 40; + int q; + int r; + int i = 100; + int result = 1; + while (offset > 0) { + q = (i * 52429); + r = i; + offset--; + i = q; + if (i == 0) { + break; + } + } + if (offset > 0) { + for(int j = 0; j < offset; j++) { + result++; + } + } + return result; + } +} From 2d1fcda0d7fc039b1d2be6fd72fab6acb01c9804 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 25 Jul 2008 16:03:40 -0700 Subject: [PATCH 043/289] 6729552: jvm98 crashes with SS12 built jdk on Solaris X64 fastdebug version SS12 C++ tripped over new templates usage in instanceKlass.cpp. Reviewed-by: never --- hotspot/make/solaris/makefiles/fastdebug.make | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hotspot/make/solaris/makefiles/fastdebug.make b/hotspot/make/solaris/makefiles/fastdebug.make index 62eaeb8f968..3ac2ae212b1 100644 --- a/hotspot/make/solaris/makefiles/fastdebug.make +++ b/hotspot/make/solaris/makefiles/fastdebug.make @@ -38,6 +38,8 @@ OPT_CFLAGS/SLOWER = -xO2 # Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876) ifeq ($(COMPILER_REV), 5.9) + # To avoid jvm98 crash + OPT_CFLAGS/instanceKlass.o = $(OPT_CFLAGS/SLOWER) # Not clear this workaround could be skipped in some cases. OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) From c936a75ed04433b52cb87c9bd4b5c8958d2b0d3c Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Mon, 28 Jul 2008 10:22:10 +0100 Subject: [PATCH 044/289] 6720185: DiagnosticFormatter refactoring Brand new hierarchy of diagnostic formatters for achieving better reusability Reviewed-by: jjg --- .../tools/javac/api/DiagnosticFormatter.java | 117 ++++++++ .../util/AbstractDiagnosticFormatter.java | 169 +++++++++++ .../javac/util/BasicDiagnosticFormatter.java | 190 +++++++++++++ .../tools/javac/util/DiagnosticFormatter.java | 267 ------------------ .../sun/tools/javac/util/JCDiagnostic.java | 58 +--- .../classes/com/sun/tools/javac/util/Log.java | 18 +- .../javac/util/RawDiagnosticFormatter.java | 107 +++++++ 7 files changed, 606 insertions(+), 320 deletions(-) create mode 100644 langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java create mode 100644 langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java create mode 100644 langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java delete mode 100644 langtools/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java create mode 100644 langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java new file mode 100644 index 00000000000..03bc2fe9468 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java @@ -0,0 +1,117 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.javac.api; + +import java.util.Locale; +import javax.tools.Diagnostic; + +/** + * Provides simple functionalities for javac diagnostic formatting + * @param type of diagnostic handled by this formatter + */ +public interface DiagnosticFormatter> { + + /** + * Whether the source code output for this diagnostic is to be displayed + * + * @param diag diagnostic to be formatted + * @return true if the source line this diagnostic refers to is to be displayed + */ + boolean displaySource(D diag); + + /** + * Format the contents of a diagnostics + * + * @param diag the diagnostic to be formatted + * @param l locale object to be used for i18n + * @return a string representing the diagnostic + */ + public String format(D diag, Locale l); + + /** + * Controls the way in which a diagnostic message is displayed. + * + * @param diag diagnostic to be formatted + * @param l locale object to be used for i18n + * @return string representation of the diagnostic message + */ + public String formatMessage(D diag,Locale l); + + /** + * Controls the way in which a diagnostic kind is displayed. + * + * @param diag diagnostic to be formatted + * @param l locale object to be used for i18n + * @return string representation of the diagnostic prefix + */ + public String formatKind(D diag, Locale l); + + /** + * Controls the way in which a diagnostic source is displayed. + * + * @param diag diagnostic to be formatted + * @param l locale object to be used for i18n + * @return string representation of the diagnostic source + */ + public String formatSource(D diag, Locale l); + + /** + * Controls the way in which a diagnostic position is displayed. + * + * @param diag diagnostic to be formatted + * @param pk enum constant representing the position kind + * @param l locale object to be used for i18n + * @return string representation of the diagnostic position + */ + public String formatPosition(D diag, PositionKind pk, Locale l); + //where + /** + * This enum defines a set of constants for all the kinds of position + * that a diagnostic can be asked for. All positions are intended to be + * relative to a given diagnostic source. + */ + public enum PositionKind { + /** + * Start position + */ + START, + /** + * End position + */ + END, + /** + * Line number + */ + LINE, + /** + * Column number + */ + COLUMN, + /** + * Offset position + */ + OFFSET + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java new file mode 100644 index 00000000000..54844470bcf --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java @@ -0,0 +1,169 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.tools.javac.util; + +import java.util.Collection; +import java.util.Locale; +import javax.tools.JavaFileObject; + +import com.sun.tools.javac.api.DiagnosticFormatter; +import com.sun.tools.javac.api.Formattable; +import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind; +import com.sun.tools.javac.file.JavacFileManager; + +/** + * This abstract class provides a basic implementation of the functionalities that should be provided + * by any formatter used by javac. Among the main features provided by AbstractDiagnosticFormatter are: + * + *